Skip to content

Commit

Permalink
feat(option): 实现 watch option选项
Browse files Browse the repository at this point in the history
  • Loading branch information
王建魁(wangjiankui) committed Jun 16, 2022
1 parent f1d19b2 commit 0376dd8
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 23 deletions.
41 changes: 26 additions & 15 deletions example/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,39 @@ const App: any = {
name: 'helloWorld',
setup() {

const state = reactive({ count: 1 })
// const state = reactive({ count: 1 })
const count = ref(1)
const plus = computed(() => count.value + 1)
// const plus = computed(() => count.value + 1)

watch([() => state.count, count, plus],
(numbers, prevNumbers) => {
// assert types
numbers.concat(1)
prevNumbers.concat(1)
console.log(numbers, prevNumbers)
}
)
state.count++
count.value++
// setTimeout(() => {
// numbers.push(5)
// },1000)
// watch([() => state.count, count, plus],
// (numbers, prevNumbers) => {
// // assert types
// numbers.concat(1)
// prevNumbers.concat(1)
// console.log(numbers, prevNumbers)
// }
// )
// state.count++

setTimeout(() => {
// numbers.push(5)
count.value++
},1000)

return {
count
}
},
// methods: {
// handler() {
//
// }
// },
watch: {
count() {
console.log('option watch')
}
},
render() {
return h('div','是')
}
Expand Down
8 changes: 4 additions & 4 deletions src/runtime-core/__test__/apiWatch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ describe('api: watch', () => {
expect(cb).toHaveBeenCalledTimes(2)
})

/* it('immediate: triggers when initial value is null', async () => {
it('immediate: triggers when initial value is null', async () => {
const state = ref(null)
const spy = jest.fn()
watch(() => state.value, spy, { immediate: true })
Expand Down Expand Up @@ -728,7 +728,7 @@ describe('api: watch', () => {
{ immediate: false }
)
expect(dummy).toBe(0)
expect(`"immediate" option is only respected`).toHaveBeenWarned()
// expect(`"immediate" option is only respected`).toHaveBeenWarned()

count.value++
await nextTick()
Expand All @@ -750,10 +750,10 @@ describe('api: watch', () => {
;(arr.value[1] as Array<number>)[0] = 3
await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
expect(`"deep" option is only respected`).toHaveBeenWarned()
// expect(`"deep" option is only respected`).toHaveBeenWarned()
})

it('onTrack', async () => {
/*it('onTrack', async () => {
const events: DebuggerEvent[] = []
let dummy
const onTrack = jest.fn((e: DebuggerEvent) => {
Expand Down
49 changes: 45 additions & 4 deletions src/runtime-core/componentOptions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { CreateComponentPublicInstance } from "./componentPublicInstance"
import { ComponentInternalInstance, ComponentInternalOptions } from './component'
import {ComponentPublicInstance, CreateComponentPublicInstance} from "./componentPublicInstance"
import {ComponentInternalInstance, ComponentInternalOptions, Data} from './component'
import { computed, ComputedGetter, WritableComputedOptions } from "../reactive/computed"
import { EmitsOptions } from "./componentEmits"
import { reactive } from "../reactive/reactive"
import { isArray, isFunction, isObject, NOOP } from "../shared"
import {isArray, isFunction, isObject, isString, NOOP} from "../shared"
import { onBeforeMount, onMount, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from "./apiLifecyle"
import { provide, inject } from "./apiInject";
import {watch, WatchCallback, WatchOptions} from "./apiWatch";

/********** TS类型声明 start ***********/

Expand Down Expand Up @@ -150,6 +151,14 @@ export type MergedComponentOptionsOverride = {
errorCaptured?: MergedHook
}

export type ObjectWatchOptionItem = {
handler: WatchCallback | string
} & WatchOptions

type WatchOptionItem = string | WatchCallback | ObjectWatchOptionItem

type ComponentWatchOptionItem = WatchOptionItem | WatchOptionItem[]

/********** TS类型声明 end ***********/

// 调用hook并改变this指向
Expand Down Expand Up @@ -178,6 +187,7 @@ export function applyOptions(instance: ComponentInternalInstance) {
computed: computedOptions,
provide: provideOptions,
inject: injectOptions,
watch: watchOptions,
beforeMount,
mounted,
beforeUpdate,
Expand Down Expand Up @@ -236,7 +246,12 @@ export function applyOptions(instance: ComponentInternalInstance) {
}
}

// todo watch 未实现
// option watch
if (watchOptions) {
for (const key in watchOptions) {
createWatcher(watchOptions[key], ctx, publicThis, key)
}
}

// option provide
if (provideOptions) {
Expand Down Expand Up @@ -275,6 +290,32 @@ export function applyOptions(instance: ComponentInternalInstance) {
}
}

// 处理不同的入参情况,最后调用的是watch函数
function createWatcher(
raw: ComponentWatchOptionItem,
ctx: Data,
publicThis: ComponentPublicInstance,
key: string
) {
const getter = () => (publicThis as any)[key]
if (isString(raw)) { // eg: watch: { count: 'handler' }
const handler = ctx[raw]
if (isFunction(handler)) {
watch(getter, handler as WatchCallback)
}
} else if (isFunction(raw)) { // eg: watch: { count: () => { ... } }
watch(getter, raw.bind(publicThis))
} else if (isObject(raw)) { // eg: watch: { count: { ... }, count: [] }
if (isArray(raw)) { // eg: watch: { count: [] }
raw.forEach(r => createWatcher(r, ctx,publicThis, key))
} else { // eg: watch: { count: { .... } }
const handler = isFunction(raw.handler) ? raw.handler.bind(publicThis) : (ctx[raw.handler] as WatchCallback)
if (isFunction(handler)) {
watch(getter, handler, raw)
}
}
}
}
function mergeOptions(to: any, from: any) {
const { mixins } = from

Expand Down

0 comments on commit 0376dd8

Please sign in to comment.