From bd7a55f6182b28cfc0dfde571489cd597fc08e5e Mon Sep 17 00:00:00 2001 From: Aleksandr Bunin Date: Fri, 27 Sep 2024 17:16:57 +0300 Subject: [PATCH 1/3] in progress --- src/core/component/engines/vue3/component.ts | 20 +++++++++++--------- src/core/component/meta/fill.ts | 8 ++++++++ src/core/component/meta/interface/index.ts | 5 +++++ src/core/component/watch/component-api.ts | 4 ++-- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/core/component/engines/vue3/component.ts b/src/core/component/engines/vue3/component.ts index 37cfc96134..db7214c5c5 100644 --- a/src/core/component/engines/vue3/component.ts +++ b/src/core/component/engines/vue3/component.ts @@ -45,15 +45,17 @@ export function getComponent(meta: ComponentMeta): ComponentOptions { - // eslint-disable-next-line @v4fire/unbound-method - const {unwatch} = watch(ctx.$fields, {deep: true, immediate: true}, handler); - return unwatch; - }; - - ctx.$async.on(emitter, 'mutation', watcher, { - group: 'watchers:suspend' - }); + if (meta.needWatchFields) { + const emitter: Function = (_: unknown, handler: WatchHandler) => { + // eslint-disable-next-line @v4fire/unbound-method + const {unwatch} = watch(ctx.$fields, {deep: true, immediate: true}, handler); + return unwatch; + }; + + ctx.$async.on(emitter, 'mutation', watcher, { + group: 'watchers:suspend' + }); + } return SSR ? {} : ctx.$fields; diff --git a/src/core/component/meta/fill.ts b/src/core/component/meta/fill.ts index 64f81bf178..d06de8b00e 100644 --- a/src/core/component/meta/fill.ts +++ b/src/core/component/meta/fill.ts @@ -156,7 +156,13 @@ export function fillMeta( // Fields [meta.systemFields, meta.fields].forEach((field) => { + let hasForceUpdateFields = false; + Object.entries(field).forEach(([key, field]) => { + if (field?.forceUpdate === true) { + hasForceUpdateFields = true; + } + field?.watchers?.forEach((watcher) => { if (isFunctional && watcher.functional === false) { return; @@ -169,6 +175,8 @@ export function fillMeta( watcherListeners.push(watcher); }); }); + + meta.needWatchFields = hasForceUpdateFields; }); // Computed fields diff --git a/src/core/component/meta/interface/index.ts b/src/core/component/meta/interface/index.ts index 3076cbbde9..243276fc7e 100644 --- a/src/core/component/meta/interface/index.ts +++ b/src/core/component/meta/interface/index.ts @@ -104,6 +104,11 @@ export interface ComponentMeta { */ tiedFields: Dictionary; + /** + * True, if the component needs to add fields watching + */ + needWatchFields: boolean; + /** * A dictionary that contains the accessor methods of the component that support caching or watching */ diff --git a/src/core/component/watch/component-api.ts b/src/core/component/watch/component-api.ts index 8f2b699c11..d73d5061da 100644 --- a/src/core/component/watch/component-api.ts +++ b/src/core/component/watch/component-api.ts @@ -47,7 +47,7 @@ import type { ComponentInterface, RawWatchHandler } from 'core/component/interfa export function implementComponentWatchAPI(component: ComponentInterface): void { const { unsafe, - unsafe: {$async: $a, meta: {computedFields, watchDependencies, watchPropDependencies, params}}, + unsafe: {$async: $a, meta: {computedFields, watchDependencies, watchPropDependencies, params, needWatchFields}}, $renderEngine: {proxyGetters} } = component; @@ -171,7 +171,7 @@ export function implementComponentWatchAPI(component: ComponentInterface): void let fieldsWatcher; - if (isFunctional) { + if (isFunctional || !needWatchFields) { // Don't force watching of fields until it becomes necessary fieldsInfo.value[watcherInitializer] = () => { delete fieldsInfo.value[watcherInitializer]; From db15d959bedcc6b578e139e9173465e510f5bdf8 Mon Sep 17 00:00:00 2001 From: Aleksandr Bunin Date: Mon, 30 Sep 2024 09:49:24 +0300 Subject: [PATCH 2/3] refactor --- src/core/component/engines/vue3/component.ts | 2 +- src/core/component/meta/fill.ts | 8 +++----- src/core/component/meta/interface/index.ts | 4 ++-- src/core/component/watch/bind.ts | 4 ++-- src/core/component/watch/component-api.ts | 4 ++-- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/core/component/engines/vue3/component.ts b/src/core/component/engines/vue3/component.ts index db7214c5c5..2cee24ee5f 100644 --- a/src/core/component/engines/vue3/component.ts +++ b/src/core/component/engines/vue3/component.ts @@ -45,7 +45,7 @@ export function getComponent(meta: ComponentMeta): ComponentOptions { // eslint-disable-next-line @v4fire/unbound-method const {unwatch} = watch(ctx.$fields, {deep: true, immediate: true}, handler); diff --git a/src/core/component/meta/fill.ts b/src/core/component/meta/fill.ts index d06de8b00e..4da65b2c00 100644 --- a/src/core/component/meta/fill.ts +++ b/src/core/component/meta/fill.ts @@ -155,12 +155,12 @@ export function fillMeta( // Fields - [meta.systemFields, meta.fields].forEach((field) => { - let hasForceUpdateFields = false; + meta.hasForceUpdateFields = false; + [meta.systemFields, meta.fields].forEach((field) => { Object.entries(field).forEach(([key, field]) => { if (field?.forceUpdate === true) { - hasForceUpdateFields = true; + meta.hasForceUpdateFields = true; } field?.watchers?.forEach((watcher) => { @@ -175,8 +175,6 @@ export function fillMeta( watcherListeners.push(watcher); }); }); - - meta.needWatchFields = hasForceUpdateFields; }); // Computed fields diff --git a/src/core/component/meta/interface/index.ts b/src/core/component/meta/interface/index.ts index 243276fc7e..791599fdf9 100644 --- a/src/core/component/meta/interface/index.ts +++ b/src/core/component/meta/interface/index.ts @@ -105,9 +105,9 @@ export interface ComponentMeta { tiedFields: Dictionary; /** - * True, if the component needs to add fields watching + * True, if the component has fields with force update option */ - needWatchFields: boolean; + hasForceUpdateFields: boolean; /** * A dictionary that contains the accessor methods of the component that support caching or watching diff --git a/src/core/component/watch/bind.ts b/src/core/component/watch/bind.ts index b766312c48..3295521b3d 100644 --- a/src/core/component/watch/bind.ts +++ b/src/core/component/watch/bind.ts @@ -53,7 +53,7 @@ export function bindRemoteWatchers(component: ComponentInterface, params?: BindR // True if the method has been invoked with passing the custom async instance as a property customAsync = $a !== unsafe.$async; - // Iterate over all registered watchers and listeners and initialize their + // Iterate over all registered watchers and listeners and initialize them Object.entries(watchersMap).forEach(([watchPath, watchers]) => { if (watchers == null) { return; @@ -139,7 +139,7 @@ export function bindRemoteWatchers(component: ComponentInterface, params?: BindR // Currently, we need to create a wrapper for our handler because there // are some conditions associated with the watcher: // - // 1. It may or may doesn't provide arguments from the listened event. + // 1. It may or may not provide arguments from the listened event. // 2. The handler can be specified either as a function or as a component method name. // // Additionally, we have two different scenarios: diff --git a/src/core/component/watch/component-api.ts b/src/core/component/watch/component-api.ts index d73d5061da..2985d42cdb 100644 --- a/src/core/component/watch/component-api.ts +++ b/src/core/component/watch/component-api.ts @@ -47,7 +47,7 @@ import type { ComponentInterface, RawWatchHandler } from 'core/component/interfa export function implementComponentWatchAPI(component: ComponentInterface): void { const { unsafe, - unsafe: {$async: $a, meta: {computedFields, watchDependencies, watchPropDependencies, params, needWatchFields}}, + unsafe: {$async: $a, meta: {computedFields, watchDependencies, watchPropDependencies, params, hasForceUpdateFields}}, $renderEngine: {proxyGetters} } = component; @@ -171,7 +171,7 @@ export function implementComponentWatchAPI(component: ComponentInterface): void let fieldsWatcher; - if (isFunctional || !needWatchFields) { + if (isFunctional || !hasForceUpdateFields) { // Don't force watching of fields until it becomes necessary fieldsInfo.value[watcherInitializer] = () => { delete fieldsInfo.value[watcherInitializer]; From ffdad87decae9f138096fd5ed282dd97b621a6db Mon Sep 17 00:00:00 2001 From: Aleksandr Bunin Date: Mon, 30 Sep 2024 18:25:45 +0300 Subject: [PATCH 3/3] refactor --- src/core/component/meta/create.ts | 1 + src/core/component/meta/fill.ts | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/component/meta/create.ts b/src/core/component/meta/create.ts index b900798319..c30624101c 100644 --- a/src/core/component/meta/create.ts +++ b/src/core/component/meta/create.ts @@ -35,6 +35,7 @@ export function createMeta(component: ComponentConstructorInfo): ComponentMeta { tiedFields: {}, systemFields: {}, computedFields: {}, + hasForceUpdateFields: false, methods: {}, accessors: {}, diff --git a/src/core/component/meta/fill.ts b/src/core/component/meta/fill.ts index 4da65b2c00..10ef7d3224 100644 --- a/src/core/component/meta/fill.ts +++ b/src/core/component/meta/fill.ts @@ -155,8 +155,6 @@ export function fillMeta( // Fields - meta.hasForceUpdateFields = false; - [meta.systemFields, meta.fields].forEach((field) => { Object.entries(field).forEach(([key, field]) => { if (field?.forceUpdate === true) {