wip: improve computed typing + test for setters
This commit is contained in:
parent
8d99ab1ff8
commit
0aff144f93
@ -1,4 +1,4 @@
|
|||||||
import { computed, reactive, effect, stop } from '../src'
|
import { computed, reactive, effect, stop, ref } from '../src'
|
||||||
|
|
||||||
describe('reactivity/computed', () => {
|
describe('reactivity/computed', () => {
|
||||||
it('should return updated value', () => {
|
it('should return updated value', () => {
|
||||||
@ -123,6 +123,38 @@ describe('reactivity/computed', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should support setter', () => {
|
it('should support setter', () => {
|
||||||
// TODO
|
const n = ref(1)
|
||||||
|
const plusOne = computed({
|
||||||
|
get: () => n.value + 1,
|
||||||
|
set: val => {
|
||||||
|
n.value = val - 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(plusOne.value).toBe(2)
|
||||||
|
n.value++
|
||||||
|
expect(plusOne.value).toBe(3)
|
||||||
|
|
||||||
|
plusOne.value = 0
|
||||||
|
expect(n.value).toBe(-1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger effect w/ setter', () => {
|
||||||
|
const n = ref(1)
|
||||||
|
const plusOne = computed({
|
||||||
|
get: () => n.value + 1,
|
||||||
|
set: val => {
|
||||||
|
n.value = val - 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let dummy
|
||||||
|
effect(() => {
|
||||||
|
dummy = n.value
|
||||||
|
})
|
||||||
|
expect(dummy).toBe(1)
|
||||||
|
|
||||||
|
plusOne.value = 0
|
||||||
|
expect(dummy).toBe(-1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -45,7 +45,7 @@ describe('reactivity/immutable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not allow mutation', () => {
|
it('should not allow mutation', () => {
|
||||||
const observed = immutable({ foo: 1, bar: { baz: 2 } })
|
const observed: any = immutable({ foo: 1, bar: { baz: 2 } })
|
||||||
observed.foo = 2
|
observed.foo = 2
|
||||||
expect(observed.foo).toBe(1)
|
expect(observed.foo).toBe(1)
|
||||||
expect(warn).toHaveBeenCalledTimes(1)
|
expect(warn).toHaveBeenCalledTimes(1)
|
||||||
@ -76,7 +76,7 @@ describe('reactivity/immutable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not trigger effects when locked', () => {
|
it('should not trigger effects when locked', () => {
|
||||||
const observed = immutable({ a: 1 })
|
const observed: any = immutable({ a: 1 })
|
||||||
let dummy
|
let dummy
|
||||||
effect(() => {
|
effect(() => {
|
||||||
dummy = observed.a
|
dummy = observed.a
|
||||||
@ -88,7 +88,7 @@ describe('reactivity/immutable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger effects when unlocked', () => {
|
it('should trigger effects when unlocked', () => {
|
||||||
const observed = immutable({ a: 1 })
|
const observed: any = immutable({ a: 1 })
|
||||||
let dummy
|
let dummy
|
||||||
effect(() => {
|
effect(() => {
|
||||||
dummy = observed.a
|
dummy = observed.a
|
||||||
@ -146,7 +146,7 @@ describe('reactivity/immutable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should allow mutation when unlocked', () => {
|
it('should allow mutation when unlocked', () => {
|
||||||
const observed: any[] = immutable([{ foo: 1, bar: { baz: 2 } }])
|
const observed: any = immutable([{ foo: 1, bar: { baz: 2 } }])
|
||||||
unlock()
|
unlock()
|
||||||
observed[1] = 2
|
observed[1] = 2
|
||||||
observed.push(3)
|
observed.push(3)
|
||||||
@ -162,7 +162,7 @@ describe('reactivity/immutable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not trigger effects when locked', () => {
|
it('should not trigger effects when locked', () => {
|
||||||
const observed = immutable([{ a: 1 }])
|
const observed: any = immutable([{ a: 1 }])
|
||||||
let dummy
|
let dummy
|
||||||
effect(() => {
|
effect(() => {
|
||||||
dummy = observed[0].a
|
dummy = observed[0].a
|
||||||
@ -177,7 +177,7 @@ describe('reactivity/immutable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger effects when unlocked', () => {
|
it('should trigger effects when unlocked', () => {
|
||||||
const observed = immutable([{ a: 1 }])
|
const observed: any = immutable([{ a: 1 }])
|
||||||
let dummy
|
let dummy
|
||||||
effect(() => {
|
effect(() => {
|
||||||
dummy = observed[0].a
|
dummy = observed[0].a
|
||||||
@ -256,7 +256,7 @@ describe('reactivity/immutable', () => {
|
|||||||
const key1 = {}
|
const key1 = {}
|
||||||
const key2 = {}
|
const key2 = {}
|
||||||
const original = new Collection([[key1, {}], [key2, {}]])
|
const original = new Collection([[key1, {}], [key2, {}]])
|
||||||
const observed = immutable(original)
|
const observed: any = immutable(original)
|
||||||
for (const [key, value] of observed) {
|
for (const [key, value] of observed) {
|
||||||
expect(isImmutable(key)).toBe(true)
|
expect(isImmutable(key)).toBe(true)
|
||||||
expect(isImmutable(value)).toBe(true)
|
expect(isImmutable(value)).toBe(true)
|
||||||
@ -322,7 +322,7 @@ describe('reactivity/immutable', () => {
|
|||||||
if (Collection === Set) {
|
if (Collection === Set) {
|
||||||
test('should retrive immutable values on iteration', () => {
|
test('should retrive immutable values on iteration', () => {
|
||||||
const original = new Collection([{}, {}])
|
const original = new Collection([{}, {}])
|
||||||
const observed = immutable(original)
|
const observed: any = immutable(original)
|
||||||
for (const value of observed) {
|
for (const value of observed) {
|
||||||
expect(isImmutable(value)).toBe(true)
|
expect(isImmutable(value)).toBe(true)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ describe('reactivity/value', () => {
|
|||||||
expect(dummy).toBe(2)
|
expect(dummy).toBe(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should work like a normal property when nested in an observable', () => {
|
it('should work like a normal property when nested in a reactive object', () => {
|
||||||
const a = ref(1)
|
const a = ref(1)
|
||||||
const obj = reactive({
|
const obj = reactive({
|
||||||
a,
|
a,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { effect, ReactiveEffect, activeReactiveEffectStack } from './effect'
|
import { effect, ReactiveEffect, activeReactiveEffectStack } from './effect'
|
||||||
import { UnwrapNestedRefs, knownRefs } from './ref'
|
import { UnwrapNestedRefs, knownRefs, Ref } from './ref'
|
||||||
import { isFunction } from '@vue/shared'
|
import { isFunction } from '@vue/shared'
|
||||||
|
|
||||||
export interface ComputedRef<T> {
|
export interface ComputedRef<T> {
|
||||||
@ -12,9 +12,11 @@ export interface ComputedOptions<T> {
|
|||||||
set: (v: T) => void
|
set: (v: T) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function computed<T>(getter: () => T): ComputedRef<T>
|
||||||
|
export function computed<T>(options: ComputedOptions<T>): Ref<T>
|
||||||
export function computed<T>(
|
export function computed<T>(
|
||||||
getterOrOptions: (() => T) | ComputedOptions<T>
|
getterOrOptions: (() => T) | ComputedOptions<T>
|
||||||
): ComputedRef<T> {
|
): Ref<T> {
|
||||||
const isReadonly = isFunction(getterOrOptions)
|
const isReadonly = isFunction(getterOrOptions)
|
||||||
const getter = isReadonly
|
const getter = isReadonly
|
||||||
? (getterOrOptions as (() => T))
|
? (getterOrOptions as (() => T))
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
immutableCollectionHandlers
|
immutableCollectionHandlers
|
||||||
} from './collectionHandlers'
|
} from './collectionHandlers'
|
||||||
|
|
||||||
import { UnwrapRef } from './ref'
|
import { UnwrapNestedRefs } from './ref'
|
||||||
import { ReactiveEffect } from './effect'
|
import { ReactiveEffect } from './effect'
|
||||||
|
|
||||||
// The main WeakMap that stores {target -> key -> dep} connections.
|
// The main WeakMap that stores {target -> key -> dep} connections.
|
||||||
@ -40,9 +40,8 @@ const canObserve = (value: any): boolean => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ObservableFactory = <T>(target?: T) => UnwrapRef<T>
|
export function reactive<T extends object>(target: T): UnwrapNestedRefs<T>
|
||||||
|
export function reactive(target: object) {
|
||||||
export const reactive = ((target: unknown): any => {
|
|
||||||
// if trying to observe an immutable proxy, return the immutable version.
|
// if trying to observe an immutable proxy, return the immutable version.
|
||||||
if (immutableToRaw.has(target)) {
|
if (immutableToRaw.has(target)) {
|
||||||
return target
|
return target
|
||||||
@ -58,9 +57,12 @@ export const reactive = ((target: unknown): any => {
|
|||||||
mutableHandlers,
|
mutableHandlers,
|
||||||
mutableCollectionHandlers
|
mutableCollectionHandlers
|
||||||
)
|
)
|
||||||
}) as ObservableFactory
|
}
|
||||||
|
|
||||||
export const immutable = ((target: unknown): any => {
|
export function immutable<T extends object>(
|
||||||
|
target: T
|
||||||
|
): Readonly<UnwrapNestedRefs<T>>
|
||||||
|
export function immutable(target: object) {
|
||||||
// value is a mutable observable, retrive its original and return
|
// value is a mutable observable, retrive its original and return
|
||||||
// a readonly version.
|
// a readonly version.
|
||||||
if (observedToRaw.has(target)) {
|
if (observedToRaw.has(target)) {
|
||||||
@ -73,7 +75,7 @@ export const immutable = ((target: unknown): any => {
|
|||||||
immutableHandlers,
|
immutableHandlers,
|
||||||
immutableCollectionHandlers
|
immutableCollectionHandlers
|
||||||
)
|
)
|
||||||
}) as ObservableFactory
|
}
|
||||||
|
|
||||||
function createReactiveObject(
|
function createReactiveObject(
|
||||||
target: any,
|
target: any,
|
||||||
|
@ -21,6 +21,7 @@ export {
|
|||||||
} from '@vue/reactivity'
|
} from '@vue/reactivity'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
Ref,
|
||||||
computed as _computed,
|
computed as _computed,
|
||||||
ComputedRef,
|
ComputedRef,
|
||||||
ComputedOptions,
|
ComputedOptions,
|
||||||
@ -37,9 +38,9 @@ export function recordEffect(effect: ReactiveEffect) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computed<T>(
|
export function computed<T>(getter: () => T): ComputedRef<T>
|
||||||
getterOrOptions: (() => T) | ComputedOptions<T>
|
export function computed<T>(options: ComputedOptions<T>): Ref<T>
|
||||||
): ComputedRef<T> {
|
export function computed<T>(getterOrOptions: any) {
|
||||||
const c = _computed(getterOrOptions)
|
const c = _computed(getterOrOptions)
|
||||||
recordEffect(c.effect)
|
recordEffect(c.effect)
|
||||||
return c
|
return c
|
||||||
|
Loading…
x
Reference in New Issue
Block a user