|
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