From d2bcedb213876b3f8ec030c4c826c70cb344b936 Mon Sep 17 00:00:00 2001 From: Cr <631807682@qq.com> Date: Mon, 14 Oct 2019 14:15:31 +0800 Subject: [PATCH] feat(apiOptions): warn invalid computed options (#225) --- .../runtime-core/__tests__/apiOptions.spec.ts | 37 +++++++++++++++++++ packages/runtime-core/src/apiOptions.ts | 29 ++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 8c3fbdf2..656f1c36 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -538,5 +538,42 @@ describe('api: options', () => { expect('Invalid watch option: "foo"').toHaveBeenWarned() }) + + test('computed with setter and no getter', () => { + const Comp = { + computed: { + foo: { + set() {} + } + }, + render() {} + } + + const root = nodeOps.createElement('div') + render(h(Comp), root) + expect('Computed property "foo" has no getter.').toHaveBeenWarned() + }) + + test('assigning to computed with no setter', () => { + let instance: any + const Comp = { + computed: { + foo: { + get() {} + } + }, + mounted() { + instance = this + }, + render() {} + } + + const root = nodeOps.createElement('div') + render(h(Comp), root) + instance.foo = 1 + expect( + 'Computed property "foo" was assigned to but it has no setter.' + ).toHaveBeenWarned() + }) }) }) diff --git a/packages/runtime-core/src/apiOptions.ts b/packages/runtime-core/src/apiOptions.ts index fe91d300..6b0fce58 100644 --- a/packages/runtime-core/src/apiOptions.ts +++ b/packages/runtime-core/src/apiOptions.ts @@ -10,7 +10,8 @@ import { isString, isObject, isArray, - EMPTY_OBJ + EMPTY_OBJ, + NOOP } from '@vue/shared' import { computed } from './apiReactivity' import { watch, WatchOptions, CleanupRegistrator } from './apiWatch' @@ -245,12 +246,28 @@ export function applyOptions( if (computedOptions) { for (const key in computedOptions) { const opt = (computedOptions as ComputedOptions)[key] - renderContext[key] = isFunction(opt) - ? computed(opt.bind(ctx)) - : computed({ - get: opt.get.bind(ctx), - set: opt.set.bind(ctx) + + if (isFunction(opt)) { + renderContext[key] = computed(opt.bind(ctx)) + } else { + const { get, set } = opt + if (isFunction(get)) { + renderContext[key] = computed({ + get: get.bind(ctx), + set: isFunction(set) + ? set.bind(ctx) + : __DEV__ + ? () => { + warn( + `Computed property "${key}" was assigned to but it has no setter.` + ) + } + : NOOP }) + } else if (__DEV__) { + warn(`Computed property "${key}" has no getter.`) + } + } } } if (methods) {