Skip to content

Commit

Permalink
fix(runtime-core): respect render function from mixins
Browse files Browse the repository at this point in the history
fix #1630
  • Loading branch information
yyx990803 committed Jul 27, 2020
1 parent 71c3c6e commit 354d79c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 21 deletions.
11 changes: 11 additions & 0 deletions packages/runtime-core/__tests__/apiOptions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,17 @@ describe('api: options', () => {
])
})

test('render from mixin', () => {
const Comp = {
mixins: [
{
render: () => 'from mixin'
}
]
}
expect(renderToString(h(Comp))).toBe('from mixin')
})

test('extends', () => {
const calls: string[] = []
const Base = {
Expand Down
40 changes: 21 additions & 19 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ function finishComponentSetup(
instance.render = Component.render as InternalRenderFunction
}
} else if (!instance.render) {
// could be set from setup()
if (compile && Component.template && !Component.render) {
if (__DEV__) {
startMeasure(instance, `compile`)
Expand All @@ -604,25 +605,6 @@ function finishComponentSetup(
;(Component.render as InternalRenderFunction)._rc = true
}

if (__DEV__ && !Component.render) {
/* istanbul ignore if */
if (!compile && Component.template) {
warn(
`Component provided template option but ` +
`runtime compilation is not supported in this build of Vue.` +
(__ESM_BUNDLER__
? ` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".`
: __ESM_BROWSER__
? ` Use "vue.esm-browser.js" instead.`
: __GLOBAL__
? ` Use "vue.global.js" instead.`
: ``) /* should not happen */
)
} else {
warn(`Component is missing template or render function.`)
}
}

instance.render = (Component.render || NOOP) as InternalRenderFunction

// for runtime-compiled render functions using `with` blocks, the render
Expand All @@ -642,6 +624,26 @@ function finishComponentSetup(
applyOptions(instance, Component)
currentInstance = null
}

// warn missing template/render
if (__DEV__ && !Component.render && instance.render === NOOP) {
/* istanbul ignore if */
if (!compile && Component.template) {
warn(
`Component provided template option but ` +
`runtime compilation is not supported in this build of Vue.` +
(__ESM_BUNDLER__
? ` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".`
: __ESM_BROWSER__
? ` Use "vue.esm-browser.js" instead.`
: __GLOBAL__
? ` Use "vue.global.js" instead.`
: ``) /* should not happen */
)
} else {
warn(`Component is missing template or render function.`)
}
}
}

const attrHandlers: ProxyHandler<Data> = {
Expand Down
10 changes: 8 additions & 2 deletions packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
SetupContext,
ComponentInternalOptions,
PublicAPIComponent,
Component
Component,
InternalRenderFunction
} from './component'
import {
isFunction,
Expand Down Expand Up @@ -390,6 +391,7 @@ export function applyOptions(
deactivated,
beforeUnmount,
unmounted,
render,
renderTracked,
renderTriggered,
errorCaptured
Expand All @@ -398,14 +400,18 @@ export function applyOptions(
const publicThis = instance.proxy!
const ctx = instance.ctx
const globalMixins = instance.appContext.mixins
// call it only during dev

if (asMixin && render && instance.render === NOOP) {
instance.render = render as InternalRenderFunction
}

// applyOptions is called non-as-mixin once per instance
if (!asMixin) {
callSyncHook('beforeCreate', options, publicThis, globalMixins)
// global mixins are applied first
applyMixins(instance, globalMixins, deferredData, deferredWatch)
}

// extending a base component...
if (extendsOptions) {
applyOptions(instance, extendsOptions, deferredData, deferredWatch, true)
Expand Down

0 comments on commit 354d79c

Please sign in to comment.