From acf98f3da5df3200dc5effc02ebeb3980ce65062 Mon Sep 17 00:00:00 2001 From: vlixin_v Date: Wed, 16 Aug 2023 20:33:40 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix(tenon):=20=E4=BF=AE=E5=A4=8D=20tenon=20?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=97=A0=E6=B3=95=E6=8D=95=E8=8E=B7=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++ .../tenon-vue/src/runtime/handlers/events.ts | 25 ++++++++++++- .../src/runtime/helper/lifecycle-helper.ts | 35 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5e4224bd1..574ad161f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,9 @@ Temporary Items # Log *.log +# Node version +.node-version + # Web node_modules coverage diff --git a/tenon/packages/tenon-vue/src/runtime/handlers/events.ts b/tenon/packages/tenon-vue/src/runtime/handlers/events.ts index 9ac556733..50b117813 100644 --- a/tenon/packages/tenon-vue/src/runtime/handlers/events.ts +++ b/tenon/packages/tenon-vue/src/runtime/handlers/events.ts @@ -1,6 +1,7 @@ import { Base } from '../nodes/Base' import { - ComponentInternalInstance + ComponentInternalInstance, + callWithAsyncErrorHandling } from '@vue/runtime-core' const LongPress = 'longpress' @@ -34,12 +35,34 @@ export function patchEvents( } } +function patchStopImmediatePropagation(e: any, value: EventValue) { + if (Array.isArray(value)) { + const originalStop = e.stopImmediatePropagation; + e.stopImmediatePropagation = () => { + originalStop.call(e); + e._stopped = true; + }; + return value.map((fn) => (e2: any) => !e2._stopped && fn && fn(e2)); + } else { + return value; + } +} + function createInvoker( initialValue: EventValue, instance: ComponentInternalInstance | null ){ // TODO: Array.isArray兼容性测试 const invoker:Invoker = (...args) => { + + // 搜集 Error + callWithAsyncErrorHandling( + patchStopImmediatePropagation([...args], invoker.value), + instance, + 5, + [...args] + ); + if(Array.isArray(initialValue)){ initialValue.forEach((func:Function) => { func.apply(instance, [...args]) diff --git a/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts b/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts index 574f09536..c8be7386a 100644 --- a/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts +++ b/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts @@ -1,3 +1,4 @@ +import { callWithAsyncErrorHandling } from "@vue/runtime-core" interface LifeCycleMixins { onLoad: Array, onReady: Array, @@ -114,5 +115,39 @@ function applyPageMixin(mixins: any): (LifeCycleMixins | null) { } function applyLifeCycle(instance: any, func: Function) { + // callWithAsyncErrorHandling 第三个参数,type 的取值 + // const ErrorTypeStrings = { + // ["sp"]: "serverPrefetch hook", + // ["bc"]: "beforeCreate hook", + // ["c"]: "created hook", + // ["bm"]: "beforeMount hook", + // ["m"]: "mounted hook", + // ["bu"]: "beforeUpdate hook", + // ["u"]: "updated", + // ["bum"]: "beforeUnmount hook", + // ["um"]: "unmounted hook", + // ["a"]: "activated hook", + // ["da"]: "deactivated hook", + // ["ec"]: "errorCaptured hook", + // ["rtc"]: "renderTracked hook", + // ["rtg"]: "renderTriggered hook", + // [0]: "setup function", + // [1]: "render function", + // [2]: "watcher getter", + // [3]: "watcher callback", + // [4]: "watcher cleanup function", + // [5]: "native event handler", + // [6]: "component event handler", + // [7]: "vnode hook", + // [8]: "directive hook", + // [9]: "transition hook", + // [10]: "app errorHandler", + // [11]: "app warnHandler", + // [12]: "ref function", + // [13]: "async component loader", + // [14]: "scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core" + // }; + const errInstance = instance._ + func && callWithAsyncErrorHandling(func, errInstance, 10) return func && func.apply(instance); } From 34ca76ff46c85c045e1fe189a7775020e8f9a60d Mon Sep 17 00:00:00 2001 From: vlixin_v Date: Fri, 25 Aug 2023 20:47:58 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=A7=86?= =?UTF-8?q?=E5=9B=BE=E5=88=B7=E6=96=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tenon/.eslintrc.js | 3 ++- tenon/packages/tenon-dev-tool/src/index.ts | 15 ++++++++++++--- tenon/packages/tenon-dev-tool/src/utils.ts | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/tenon/.eslintrc.js b/tenon/.eslintrc.js index 04cba9b4c..1fb05f885 100644 --- a/tenon/.eslintrc.js +++ b/tenon/.eslintrc.js @@ -21,7 +21,8 @@ module.exports = { 'error', 'ObjectExpression > SpreadElement', 'ObjectPattern > RestElement' - ] + ], + 'no-restricted-syntax': 'off' }, overrides: [ // tests, no restrictions (runs in Node / jest with jsdom) diff --git a/tenon/packages/tenon-dev-tool/src/index.ts b/tenon/packages/tenon-dev-tool/src/index.ts index 3017134d7..5d526b6a4 100644 --- a/tenon/packages/tenon-dev-tool/src/index.ts +++ b/tenon/packages/tenon-dev-tool/src/index.ts @@ -42,13 +42,21 @@ export function run(container: any, type: string = 'tenon-vue') { 'getViewTree': function (ws: any, params: any) { let data = getViewData(formatedNode, type) viewMap = data.viewMap - if (formatedNode?.element?.dbg_getDescription) { - formatedNode.element.dbg_getDescription((node: any) => { + if (params.refresh) { + formatedNode?.element?.dbg_getDescription((node: any) => { + // tenon 特殊处理,外层包裹一个 template,和组件对齐 + if(type === 'tenon-vue'){ + node.tagName = 'template' + } + let refreshFormatedNode = formatNode(node, type, true) + let refreshData = getViewData(refreshFormatedNode, type) + viewMap = refreshData.viewMap; sendMessage(ws, { method: 'setViewTree', params: { ...params, - viewTree: [data.simpleRoot], + refresh: true, + viewTree: [refreshData.simpleRoot], path: path, baseInfo: __GLOBAL__.Hummer.env, devToolType: type @@ -60,6 +68,7 @@ export function run(container: any, type: string = 'tenon-vue') { method: 'setViewTree', params: { ...params, + refresh: false, viewTree: [data.simpleRoot], path: path, baseInfo: __GLOBAL__.Hummer.env, diff --git a/tenon/packages/tenon-dev-tool/src/utils.ts b/tenon/packages/tenon-dev-tool/src/utils.ts index b7e061b80..dae171a00 100644 --- a/tenon/packages/tenon-dev-tool/src/utils.ts +++ b/tenon/packages/tenon-dev-tool/src/utils.ts @@ -70,10 +70,10 @@ export const getPartUrlByParam = (url: string, param: string) => { * @param type * @returns simplenode */ -export const formatNode = function (node: any, type: string = 'tenon-vue') { +export const formatNode = function (node: any, type: string = 'tenon-vue', refresh = false) { let formatedNode = Object.create({}) const treeTraveler = function (node: any, rootView: any) { - processView(node, rootView, type) + processView(node, rootView, type, refresh) if (node.children) { // hummer children类型Array tenon-vue类型Set 处理一下 let arr = Array.from(node.children) @@ -179,7 +179,7 @@ export const getViewData = function (container: any, type: string = 'tenon-vue') // return res // }) // } -const processView = function (node: any, rootView: any, type: string = 'tenon-vue') { +const processView = function (node: any, rootView: any, type: string = 'tenon-vue', refresh = false) { let nameKey = '__NAME', idKey = '__view_id', textKey = '_text', @@ -198,6 +198,16 @@ const processView = function (node: any, rootView: any, type: string = 'tenon-vu srcKey = 'content' rootView.style = node.element.style break; + case 'tenon-vue': + // 刷新之后的节点要格式化一下 + if(refresh){ + nameKey = 'tagName'; + idKey = 'id'; + textKey = 'content'; + srcKey = 'content'; + rootView.style = node.element.style; + } + break default: break; } From cec470edbd10f9e2b07b1228fc29a6f004504cc3 Mon Sep 17 00:00:00 2001 From: vlixin_v Date: Wed, 6 Sep 2023 16:07:33 +0800 Subject: [PATCH 3/5] =?UTF-8?q?chore:=20=E4=BC=98=E5=8C=96=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E9=94=99=E8=AF=AF=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tenon-vue/src/runtime/handlers/events.ts | 26 ++------- .../src/runtime/helper/lifecycle-helper.ts | 56 +++++-------------- 2 files changed, 20 insertions(+), 62 deletions(-) diff --git a/tenon/packages/tenon-vue/src/runtime/handlers/events.ts b/tenon/packages/tenon-vue/src/runtime/handlers/events.ts index 50b117813..898f823f3 100644 --- a/tenon/packages/tenon-vue/src/runtime/handlers/events.ts +++ b/tenon/packages/tenon-vue/src/runtime/handlers/events.ts @@ -35,16 +35,12 @@ export function patchEvents( } } -function patchStopImmediatePropagation(e: any, value: EventValue) { - if (Array.isArray(value)) { - const originalStop = e.stopImmediatePropagation; - e.stopImmediatePropagation = () => { - originalStop.call(e); - e._stopped = true; - }; - return value.map((fn) => (e2: any) => !e2._stopped && fn && fn(e2)); +function patchInvokerHandler(initialValue: any, instance: ComponentInternalInstance | null) { + // TODO: Array.isArray兼容性测试 + if (Array.isArray(initialValue)) { + return initialValue.map(func => () => func && func.apply(instance)) } else { - return value; + return () => initialValue.apply(instance) } } @@ -52,24 +48,14 @@ function createInvoker( initialValue: EventValue, instance: ComponentInternalInstance | null ){ - // TODO: Array.isArray兼容性测试 const invoker:Invoker = (...args) => { - // 搜集 Error callWithAsyncErrorHandling( - patchStopImmediatePropagation([...args], invoker.value), + patchInvokerHandler(initialValue, instance), instance, 5, [...args] ); - - if(Array.isArray(initialValue)){ - initialValue.forEach((func:Function) => { - func.apply(instance, [...args]) - }) - }else { - initialValue.apply(instance, [...args]) - } } invoker.value = initialValue initialValue.invoker = invoker diff --git a/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts b/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts index c8be7386a..0e0e981e4 100644 --- a/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts +++ b/tenon/packages/tenon-vue/src/runtime/helper/lifecycle-helper.ts @@ -1,4 +1,4 @@ -import { callWithAsyncErrorHandling } from "@vue/runtime-core" +import { ComponentInternalInstance, callWithAsyncErrorHandling } from "@vue/runtime-core" interface LifeCycleMixins { onLoad: Array, onReady: Array, @@ -79,14 +79,15 @@ export const initPageLifeCycle = (container: any, instance: any, config: any) => container[lifecycle] = () => { globalLifeCycleMixins[lifecycle].forEach((func: Function) => { - applyLifeCycle(instance, func) - }) - extendOptions && applyLifeCycle(instance, extendOptions[lifecycle]) + lifecycleAsyncErrorTracker(instance, func); + }); + extendOptions && lifecycleAsyncErrorTracker(instance, extendOptions[lifecycle]); + lifeCycleMixins[lifecycle].forEach((func: Function) => { - applyLifeCycle(instance, func) - }) - applyLifeCycle(instance, config[lifecycle]) - } + lifecycleAsyncErrorTracker(instance, func); + }); + lifecycleAsyncErrorTracker(instance, config[lifecycle]); + }; }) } @@ -115,39 +116,10 @@ function applyPageMixin(mixins: any): (LifeCycleMixins | null) { } function applyLifeCycle(instance: any, func: Function) { - // callWithAsyncErrorHandling 第三个参数,type 的取值 - // const ErrorTypeStrings = { - // ["sp"]: "serverPrefetch hook", - // ["bc"]: "beforeCreate hook", - // ["c"]: "created hook", - // ["bm"]: "beforeMount hook", - // ["m"]: "mounted hook", - // ["bu"]: "beforeUpdate hook", - // ["u"]: "updated", - // ["bum"]: "beforeUnmount hook", - // ["um"]: "unmounted hook", - // ["a"]: "activated hook", - // ["da"]: "deactivated hook", - // ["ec"]: "errorCaptured hook", - // ["rtc"]: "renderTracked hook", - // ["rtg"]: "renderTriggered hook", - // [0]: "setup function", - // [1]: "render function", - // [2]: "watcher getter", - // [3]: "watcher callback", - // [4]: "watcher cleanup function", - // [5]: "native event handler", - // [6]: "component event handler", - // [7]: "vnode hook", - // [8]: "directive hook", - // [9]: "transition hook", - // [10]: "app errorHandler", - // [11]: "app warnHandler", - // [12]: "ref function", - // [13]: "async component loader", - // [14]: "scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core" - // }; - const errInstance = instance._ - func && callWithAsyncErrorHandling(func, errInstance, 10) return func && func.apply(instance); } +function lifecycleAsyncErrorTracker(instance: any, func: Function){ + // instance 是编译主入口的 proxy 格式数据,而 instance._ 是 createComponentInstance 实例 + const errorInternalInstance: ComponentInternalInstance = instance._ + func && callWithAsyncErrorHandling(() => applyLifeCycle(instance, func), errorInternalInstance, 10) +} \ No newline at end of file From 8fc58f9af14ebea1108fea6f79fa860bd45bd5b4 Mon Sep 17 00:00:00 2001 From: vlixin_v Date: Wed, 6 Sep 2023 16:27:10 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=E5=BC=82=E6=AD=A5=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E6=90=9C=E9=9B=86=E9=94=99=E8=AF=AF=E6=B7=BB=E5=8A=A0=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tenon/packages/tenon-vue/src/runtime/handlers/events.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tenon/packages/tenon-vue/src/runtime/handlers/events.ts b/tenon/packages/tenon-vue/src/runtime/handlers/events.ts index 898f823f3..ba7421056 100644 --- a/tenon/packages/tenon-vue/src/runtime/handlers/events.ts +++ b/tenon/packages/tenon-vue/src/runtime/handlers/events.ts @@ -35,12 +35,12 @@ export function patchEvents( } } -function patchInvokerHandler(initialValue: any, instance: ComponentInternalInstance | null) { +function patchInvokerHandler(initialValue: any, instance: ComponentInternalInstance | null, args: any) { // TODO: Array.isArray兼容性测试 if (Array.isArray(initialValue)) { - return initialValue.map(func => () => func && func.apply(instance)) + return initialValue.map(func => () => func && func.apply(instance, args)) } else { - return () => initialValue.apply(instance) + return () => initialValue.apply(instance, args) } } @@ -51,7 +51,7 @@ function createInvoker( const invoker:Invoker = (...args) => { // 搜集 Error callWithAsyncErrorHandling( - patchInvokerHandler(initialValue, instance), + patchInvokerHandler(initialValue, instance, [...args]), instance, 5, [...args] From b9375cdb2bb3a7d961314e6c6fb3007549ca8ed4 Mon Sep 17 00:00:00 2001 From: daodaolee Date: Wed, 13 Sep 2023 21:16:32 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(tenon)=EF=BC=9A=E4=BF=AE=E5=A4=8D=20Ten?= =?UTF-8?q?on=20=E7=BB=84=E4=BB=B6=20dataset=20key=20=E5=8F=96=E5=80=BC?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tenon/packages/tenon-vue/src/runtime/nodes/Base.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tenon/packages/tenon-vue/src/runtime/nodes/Base.ts b/tenon/packages/tenon-vue/src/runtime/nodes/Base.ts index f72b75d3d..e82bd2f67 100644 --- a/tenon/packages/tenon-vue/src/runtime/nodes/Base.ts +++ b/tenon/packages/tenon-vue/src/runtime/nodes/Base.ts @@ -202,7 +202,9 @@ export class Base { private setCacheProp(key:string, value:any){ // 如果是 datattr 格式的属性,缓存到 dataset 中,方便事件可以获取到 dataset (Chameleon事件需求) if(/^data/.test(key)){ - let dataKey = key.slice(4).toLowerCase() + // 父组件 data 开头就截取4个,子组件 data- 开头就截取5个 + let cutNum = key.includes('-') ? 5 : 4 + let dataKey = key.slice(cutNum).toLowerCase() if(dataKey){ this.dataset[dataKey] = value }