From 8602b61efb8ce9f9fca3ff76c799436fd84f1259 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 30 Oct 2018 01:10:03 -0400 Subject: [PATCH] refactor: use more efficient useComputed() implementation --- packages/observer/src/computed.ts | 9 ++++++--- packages/runtime-core/src/componentComputed.ts | 7 +++---- packages/runtime-core/src/componentProxy.ts | 3 ++- packages/runtime-core/src/experimental/hooks.ts | 14 +++++++------- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/observer/src/computed.ts b/packages/observer/src/computed.ts index d63588d0..31033bbb 100644 --- a/packages/observer/src/computed.ts +++ b/packages/observer/src/computed.ts @@ -1,12 +1,15 @@ import { autorun } from './index' import { Autorun, activeAutorunStack } from './autorun' -export interface ComputedGetter { - (): any +export interface ComputedGetter { + (): T runner: Autorun } -export function computed(getter: Function, context?: any): ComputedGetter { +export function computed( + getter: (this: C, ctx: C) => T, + context?: C +): ComputedGetter { let dirty: boolean = true let value: any = undefined const runner = autorun(() => getter.call(context, context), { diff --git a/packages/runtime-core/src/componentComputed.ts b/packages/runtime-core/src/componentComputed.ts index 7e914a1c..3ab80a67 100644 --- a/packages/runtime-core/src/componentComputed.ts +++ b/packages/runtime-core/src/componentComputed.ts @@ -3,6 +3,8 @@ import { computed, stop, ComputedGetter } from '@vue/observer' import { ComponentInstance } from './component' import { ComponentComputedOptions } from './componentOptions' +export type ComputedHandles = Record + export function initializeComputed( instance: ComponentInstance, computedOptions: ComponentComputedOptions | undefined @@ -10,10 +12,7 @@ export function initializeComputed( if (!computedOptions) { return } - const handles: Record< - string, - ComputedGetter - > = (instance._computedGetters = {}) + const handles: ComputedHandles = (instance._computedGetters = {}) const proxy = instance.$proxy for (const key in computedOptions) { const option = computedOptions[key] diff --git a/packages/runtime-core/src/componentProxy.ts b/packages/runtime-core/src/componentProxy.ts index 8319a962..80bd36cb 100644 --- a/packages/runtime-core/src/componentProxy.ts +++ b/packages/runtime-core/src/componentProxy.ts @@ -43,7 +43,8 @@ const renderProxyHandlers = { } else if (key[0] !== '_') { if (__DEV__ && isRendering && !(key in target)) { warn( - `property "${key}" was accessed during render but does not exist on instance.` + `property "${key}" was accessed during render but does not exist ` + + `on instance.` ) } const value = Reflect.get(target, key, receiver) diff --git a/packages/runtime-core/src/experimental/hooks.ts b/packages/runtime-core/src/experimental/hooks.ts index e2d67be4..b4948d3b 100644 --- a/packages/runtime-core/src/experimental/hooks.ts +++ b/packages/runtime-core/src/experimental/hooks.ts @@ -1,7 +1,7 @@ import { ComponentInstance, FunctionalComponent, Component } from '../component' import { mergeLifecycleHooks, Data, WatchOptions } from '../componentOptions' import { VNode, Slots } from '../vdom' -import { observable, computed, stop, ComputedGetter } from '@vue/observer' +import { observable, computed } from '@vue/observer' import { setupWatcher } from '../componentWatch' type RawEffect = () => (() => void) | void @@ -191,14 +191,14 @@ export function useWatch( } export function useComputed(getter: () => T): T { - const computedRef = useRef() - useUnmounted(() => { - stop((computedRef.current as ComputedGetter).runner) - }) + ensureCurrentInstance() + const id = `__hooksComputed${++callIndex}` + const instance = currentInstance as ComponentInstance + const handles = instance._computedGetters || (instance._computedGetters = {}) if (isMounting) { - computedRef.current = computed(getter) + handles[id] = computed(getter) } - return (computedRef.current as ComputedGetter)() + return handles[id]() } export function withHooks(render: FunctionalComponent): new () => Component {