diff --git a/packages/core/src/componentOptions.ts b/packages/core/src/componentOptions.ts index e03cb3e7..ff3545f2 100644 --- a/packages/core/src/componentOptions.ts +++ b/packages/core/src/componentOptions.ts @@ -5,7 +5,6 @@ import { APIMethods, LifecycleMethods } from './component' -import { Slots } from './vdom' import { isArray, isObject, isFunction } from '@vue/shared' import { normalizePropsOptions } from './componentProps' @@ -22,9 +21,7 @@ export interface ComponentOptions< P = {}, D = {}, This = ComponentInstance
-> extends ComponentClassOptions
{
- data?(): D
- render?: (this: This, props: Readonly, slots: Slots, attrs: Data) => any
+> extends ComponentClassOptions , APIMethods , LifecycleMethods {
// TODO other options
readonly [key: string]: any
}
@@ -164,6 +161,7 @@ export function mergeComponentOptions(to: any, from: any): ComponentOptions {
if (isFunction(value) && isFunction(existing)) {
if (key === 'data') {
// for data we need to merge the returned value
+ // TODO: backwards compat requires recursive merge
res[key] = function() {
return Object.assign(existing.call(this), value.call(this))
}
diff --git a/packages/core/src/componentUtils.ts b/packages/core/src/componentUtils.ts
index d3140581..cad9bb75 100644
--- a/packages/core/src/componentUtils.ts
+++ b/packages/core/src/componentUtils.ts
@@ -1,5 +1,5 @@
import { VNodeFlags } from './flags'
-import { EMPTY_OBJ, isArray, isFunction, isObject } from '@vue/shared'
+import { EMPTY_OBJ, isArray, isObject } from '@vue/shared'
import { h } from './h'
import { VNode, MountedVNode, createFragment } from './vdom'
import {
@@ -104,7 +104,7 @@ export function initializeComponentInstance(instance: ComponentInstance) {
export function renderInstanceRoot(instance: ComponentInstance): VNode {
let vnode
try {
- vnode = instance.render.call(
+ vnode = instance.$options.render.call(
instance.$proxy,
instance.$props,
instance.$slots,
@@ -213,35 +213,26 @@ export function createComponentClassFromOptions(
const proto = AnonymousComponent.prototype as any
for (const key in options) {
const value = options[key]
- // name -> displayName
- if (key === 'name') {
- options.displayName = options.name
- } else if (isFunction(value)) {
- // lifecycle hook / data / render
+ if (key === 'render') {
if (__COMPAT__) {
- if (key === 'render') {
- proto[key] = function() {
- return value.call(this, h)
- }
- } else if (key === 'beforeDestroy') {
- proto.beforeUnmount = value
- } else if (key === 'destroyed') {
- proto.unmounted = value
- } else {
- proto[key] = value
+ options.render = function() {
+ return value.call(this, h)
}
- } else {
- proto[key] = value
}
+ // so that we can call instance.render directly
+ proto.render = options.render
} else if (key === 'computed') {
+ // create computed setters on prototype
+ // (getters are handled by the render proxy)
for (const computedKey in value) {
const computed = value[computedKey]
- const isGet = isFunction(computed)
- Object.defineProperty(proto, computedKey, {
- configurable: true,
- get: isGet ? computed : computed.get,
- set: isGet ? undefined : computed.set
- })
+ const set = isObject(computed) && computed.set
+ if (set) {
+ Object.defineProperty(proto, computedKey, {
+ configurable: true,
+ set
+ })
+ }
}
} else if (key === 'methods') {
for (const method in value) {
@@ -253,6 +244,18 @@ export function createComponentClassFromOptions(
}
proto[method] = value[method]
}
+ } else if (__COMPAT__) {
+ if (key === 'name') {
+ options.displayName = value
+ } else if (key === 'render') {
+ options.render = function() {
+ return value.call(this, h)
+ }
+ } else if (key === 'beforeDestroy') {
+ options.beforeUnmount = value
+ } else if (key === 'destroyed') {
+ options.unmounted = value
+ }
}
}
return AnonymousComponent as ComponentClass