Skip to content

Commit 9b607fe

Browse files
committedJun 22, 2021
fix(watch): fix watch option merging from mixins
fix #3966
1 parent ab6e927 commit 9b607fe

File tree

2 files changed

+89
-20
lines changed

2 files changed

+89
-20
lines changed
 

‎packages/runtime-core/__tests__/apiOptions.spec.ts

+61
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,67 @@ describe('api: options', () => {
279279
assertCall(spyC, 0, [{ qux: 4 }, { qux: 4 }])
280280
})
281281

282+
// #3966
283+
test('watch merging from mixins', async () => {
284+
const mixinA = {
285+
data() {
286+
return {
287+
fromMixinA: ''
288+
}
289+
},
290+
watch: {
291+
obj: {
292+
handler(this: any, to: any) {
293+
this.fromMixinA = to
294+
}
295+
}
296+
}
297+
}
298+
299+
const mixinB = {
300+
data() {
301+
return {
302+
fromMixinB: ''
303+
}
304+
},
305+
watch: {
306+
obj: 'setMixinB'
307+
},
308+
methods: {
309+
setMixinB(this: any, to: any) {
310+
this.fromMixinB = to
311+
}
312+
}
313+
}
314+
315+
let vm: any
316+
const Comp = {
317+
render() {},
318+
mixins: [mixinA, mixinB],
319+
data: () => ({
320+
obj: 'foo',
321+
fromComp: ''
322+
}),
323+
watch: {
324+
obj(this: any, to: any) {
325+
this.fromComp = to
326+
}
327+
},
328+
mounted() {
329+
vm = this
330+
}
331+
}
332+
333+
const root = nodeOps.createElement('div')
334+
render(h(Comp), root)
335+
336+
vm.obj = 'bar'
337+
await nextTick()
338+
expect(vm.fromComp).toBe('bar')
339+
expect(vm.fromMixinA).toBe('bar')
340+
expect(vm.fromMixinB).toBe('bar')
341+
})
342+
282343
test('provide/inject', () => {
283344
const symbolKey = Symbol()
284345
const Root = defineComponent({

‎packages/runtime-core/src/componentOptions.ts

+28-20
Original file line numberDiff line numberDiff line change
@@ -972,25 +972,23 @@ export const internalOptionMergeStrats: Record<string, Function> = {
972972
methods: mergeObjectOptions,
973973
computed: mergeObjectOptions,
974974
// lifecycle
975-
beforeCreate: mergeHook,
976-
created: mergeHook,
977-
beforeMount: mergeHook,
978-
mounted: mergeHook,
979-
beforeUpdate: mergeHook,
980-
updated: mergeHook,
981-
beforeDestroy: mergeHook,
982-
destroyed: mergeHook,
983-
activated: mergeHook,
984-
deactivated: mergeHook,
985-
errorCaptured: mergeHook,
986-
serverPrefetch: mergeHook,
975+
beforeCreate: mergeAsArray,
976+
created: mergeAsArray,
977+
beforeMount: mergeAsArray,
978+
mounted: mergeAsArray,
979+
beforeUpdate: mergeAsArray,
980+
updated: mergeAsArray,
981+
beforeDestroy: mergeAsArray,
982+
destroyed: mergeAsArray,
983+
activated: mergeAsArray,
984+
deactivated: mergeAsArray,
985+
errorCaptured: mergeAsArray,
986+
serverPrefetch: mergeAsArray,
987987
// assets
988988
components: mergeObjectOptions,
989989
directives: mergeObjectOptions,
990-
// watch has special merge behavior in v2, but isn't actually needed in v3.
991-
// since we are only exposing these for compat and nobody should be relying
992-
// on the watch-specific behavior, just expose the object merge strat.
993-
watch: mergeObjectOptions,
990+
// watch
991+
watch: mergeWatchOptions,
994992
// provide / inject
995993
provide: mergeDataFn,
996994
inject: mergeInject
@@ -1038,13 +1036,23 @@ function normalizeInject(
10381036
return raw
10391037
}
10401038

1041-
function mergeHook(
1042-
to: Function[] | Function | undefined,
1043-
from: Function | Function[]
1044-
) {
1039+
function mergeAsArray<T = Function>(to: T[] | T | undefined, from: T | T[]) {
10451040
return to ? [...new Set([].concat(to as any, from as any))] : from
10461041
}
10471042

10481043
function mergeObjectOptions(to: Object | undefined, from: Object | undefined) {
10491044
return to ? extend(extend(Object.create(null), to), from) : from
10501045
}
1046+
1047+
function mergeWatchOptions(
1048+
to: ComponentWatchOptions | undefined,
1049+
from: ComponentWatchOptions | undefined
1050+
) {
1051+
if (!to) return from
1052+
if (!from) return to
1053+
const merged = extend(Object.create(null), to)
1054+
for (const key in from) {
1055+
merged[key] = mergeAsArray(to[key], from[key])
1056+
}
1057+
return merged
1058+
}

0 commit comments

Comments
 (0)
Please sign in to comment.