|
1 | 1 | import { getVueConstructor, getCurrentInstance } from '../runtimeContext' |
2 | 2 | import { createRef, Ref } from '../reactivity' |
3 | | -import { defineComponentInstance } from '../utils/helper' |
4 | | -import { warn } from '../utils' |
| 3 | +import { |
| 4 | + warn, |
| 5 | + noopFn, |
| 6 | + defineComponentInstance, |
| 7 | + getVueInternalClasses, |
| 8 | +} from '../utils' |
5 | 9 |
|
6 | 10 | interface Option<T> { |
7 | 11 | get: () => T |
@@ -31,28 +35,61 @@ export function computed<T>( |
31 | 35 | set = options.set |
32 | 36 | } |
33 | 37 |
|
34 | | - const computedHost = defineComponentInstance(getVueConstructor(), { |
35 | | - computed: { |
36 | | - $$state: { |
37 | | - get, |
38 | | - set, |
| 38 | + let computedSetter |
| 39 | + let computedGetter |
| 40 | + |
| 41 | + if (vm) { |
| 42 | + const { Watcher, Dep } = getVueInternalClasses() |
| 43 | + let watcher: any |
| 44 | + computedGetter = () => { |
| 45 | + if (!watcher) { |
| 46 | + watcher = new Watcher(vm, get, noopFn, { lazy: true }) |
| 47 | + } |
| 48 | + if (watcher.dirty) { |
| 49 | + watcher.evaluate() |
| 50 | + } |
| 51 | + if (Dep.target) { |
| 52 | + watcher.depend() |
| 53 | + } |
| 54 | + return watcher.value |
| 55 | + } |
| 56 | + |
| 57 | + computedSetter = (v: T) => { |
| 58 | + if (__DEV__ && !set) { |
| 59 | + warn('Write operation failed: computed value is readonly.', vm!) |
| 60 | + return |
| 61 | + } |
| 62 | + |
| 63 | + if (set) { |
| 64 | + set(v) |
| 65 | + } |
| 66 | + } |
| 67 | + } else { |
| 68 | + // fallback |
| 69 | + const computedHost = defineComponentInstance(getVueConstructor(), { |
| 70 | + computed: { |
| 71 | + $$state: { |
| 72 | + get, |
| 73 | + set, |
| 74 | + }, |
39 | 75 | }, |
40 | | - }, |
41 | | - }) |
| 76 | + }) |
| 77 | + |
| 78 | + computedGetter = () => (computedHost as any).$$state |
| 79 | + computedSetter = (v: T) => { |
| 80 | + if (__DEV__ && !set) { |
| 81 | + warn('Write operation failed: computed value is readonly.', vm!) |
| 82 | + return |
| 83 | + } |
42 | 84 |
|
43 | | - vm && vm.$on('hook:destroyed', () => computedHost.$destroy()) |
| 85 | + ;(computedHost as any).$$state = v |
| 86 | + } |
| 87 | + } |
44 | 88 |
|
45 | 89 | return createRef<T>( |
46 | 90 | { |
47 | | - get: () => (computedHost as any).$$state, |
48 | | - set: (v: T) => { |
49 | | - if (__DEV__ && !set) { |
50 | | - warn('Write operation failed: computed value is readonly.', vm!) |
51 | | - return |
52 | | - } |
53 | | - |
54 | | - ;(computedHost as any).$$state = v |
55 | | - }, |
| 91 | + get: computedGetter, |
| 92 | + set: computedSetter, |
56 | 93 | }, |
57 | 94 | !set |
58 | 95 | ) |
|
0 commit comments