refactor: use more efficient useComputed() implementation
This commit is contained in:
parent
f9e3e38fdb
commit
8602b61efb
@ -1,12 +1,15 @@
|
|||||||
import { autorun } from './index'
|
import { autorun } from './index'
|
||||||
import { Autorun, activeAutorunStack } from './autorun'
|
import { Autorun, activeAutorunStack } from './autorun'
|
||||||
|
|
||||||
export interface ComputedGetter {
|
export interface ComputedGetter<T = any> {
|
||||||
(): any
|
(): T
|
||||||
runner: Autorun
|
runner: Autorun
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computed(getter: Function, context?: any): ComputedGetter {
|
export function computed<T, C = null>(
|
||||||
|
getter: (this: C, ctx: C) => T,
|
||||||
|
context?: C
|
||||||
|
): ComputedGetter<T> {
|
||||||
let dirty: boolean = true
|
let dirty: boolean = true
|
||||||
let value: any = undefined
|
let value: any = undefined
|
||||||
const runner = autorun(() => getter.call(context, context), {
|
const runner = autorun(() => getter.call(context, context), {
|
||||||
|
@ -3,6 +3,8 @@ import { computed, stop, ComputedGetter } from '@vue/observer'
|
|||||||
import { ComponentInstance } from './component'
|
import { ComponentInstance } from './component'
|
||||||
import { ComponentComputedOptions } from './componentOptions'
|
import { ComponentComputedOptions } from './componentOptions'
|
||||||
|
|
||||||
|
export type ComputedHandles = Record<string, ComputedGetter>
|
||||||
|
|
||||||
export function initializeComputed(
|
export function initializeComputed(
|
||||||
instance: ComponentInstance,
|
instance: ComponentInstance,
|
||||||
computedOptions: ComponentComputedOptions | undefined
|
computedOptions: ComponentComputedOptions | undefined
|
||||||
@ -10,10 +12,7 @@ export function initializeComputed(
|
|||||||
if (!computedOptions) {
|
if (!computedOptions) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const handles: Record<
|
const handles: ComputedHandles = (instance._computedGetters = {})
|
||||||
string,
|
|
||||||
ComputedGetter
|
|
||||||
> = (instance._computedGetters = {})
|
|
||||||
const proxy = instance.$proxy
|
const proxy = instance.$proxy
|
||||||
for (const key in computedOptions) {
|
for (const key in computedOptions) {
|
||||||
const option = computedOptions[key]
|
const option = computedOptions[key]
|
||||||
|
@ -43,7 +43,8 @@ const renderProxyHandlers = {
|
|||||||
} else if (key[0] !== '_') {
|
} else if (key[0] !== '_') {
|
||||||
if (__DEV__ && isRendering && !(key in target)) {
|
if (__DEV__ && isRendering && !(key in target)) {
|
||||||
warn(
|
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)
|
const value = Reflect.get(target, key, receiver)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ComponentInstance, FunctionalComponent, Component } from '../component'
|
import { ComponentInstance, FunctionalComponent, Component } from '../component'
|
||||||
import { mergeLifecycleHooks, Data, WatchOptions } from '../componentOptions'
|
import { mergeLifecycleHooks, Data, WatchOptions } from '../componentOptions'
|
||||||
import { VNode, Slots } from '../vdom'
|
import { VNode, Slots } from '../vdom'
|
||||||
import { observable, computed, stop, ComputedGetter } from '@vue/observer'
|
import { observable, computed } from '@vue/observer'
|
||||||
import { setupWatcher } from '../componentWatch'
|
import { setupWatcher } from '../componentWatch'
|
||||||
|
|
||||||
type RawEffect = () => (() => void) | void
|
type RawEffect = () => (() => void) | void
|
||||||
@ -191,14 +191,14 @@ export function useWatch<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useComputed<T>(getter: () => T): T {
|
export function useComputed<T>(getter: () => T): T {
|
||||||
const computedRef = useRef()
|
ensureCurrentInstance()
|
||||||
useUnmounted(() => {
|
const id = `__hooksComputed${++callIndex}`
|
||||||
stop((computedRef.current as ComputedGetter).runner)
|
const instance = currentInstance as ComponentInstance
|
||||||
})
|
const handles = instance._computedGetters || (instance._computedGetters = {})
|
||||||
if (isMounting) {
|
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 {
|
export function withHooks(render: FunctionalComponent): new () => Component {
|
||||||
|
Loading…
Reference in New Issue
Block a user