[英]Vue pass slot template to extended component
Is any way to pass a template to extended component?有什么方法可以将模板传递给扩展组件? Example, that illustrates the problem:示例,说明了问题:
There is a component named Slide
with a template like so:有一个名为Slide
的组件,其模板如下:
<template>
<div class="swiper-slide swiper-slide-one">
<div class="swiper-filter"></div>
<slot />
</div>
</template>
In other place i need to create and mount that component in imperative style:在其他地方,我需要以命令式样式创建和安装该组件:
import SlideComponent from '@/components/Slide'
const Slide = Vue.extend(SlideComponent);
new Slide().$mount('#container');
The problem is that i have no idea how to pass a template that will be compiled in the slot of the extended component.问题是我不知道如何传递将在扩展组件的插槽中编译的模板。
You can use Vue.compile combined with $createElement
.您可以将Vue.compile与$createElement
结合使用。
const slotTemplate = `<div><h4>This is the slot content</h4>{{message}}</div>`;
const renderer = Vue.compile(slotTemplate)
const slotContent = {
data(){
return {
message: "some data in the slot"
}
},
render: renderer.render,
staticRenderFns: renderer.staticRenderFns
}
const instance = new Slide();
instance.$slots.default = [instance.$createElement(slotContent)];
instance.$mount("#container");
Above is an example of a slot that requires some data.上面是一个需要一些数据的插槽示例。 If your slot content is just HTML you could get away with just this:如果您的插槽内容只是 HTML,那么您可以摆脱这种情况:
const slotTemplate = `<div><h4>This is the slot content</h4></div>`
const instance = new Slide();
instance.$slots.default = [instance.$createElement(Vue.compile(slotTemplate))];
instance.$mount("#container");
Note: $slots[key] should be an array of vNodes .注意: $slots[key] 应该是一个 vNodes 数组。 It will render correctly if you use a vNode, but there will be bugs (eg when calling vm._update)如果您使用 vNode,它将正确呈现,但会有错误(例如,调用 vm._update 时)
If you are open to change your approach a little bit, a <component>
instead of <slot>
:如果你愿意稍微改变你的方法,一个<component>
而不是<slot>
:
https://jsfiddle.net/jonataswalker/z5Lgbjv8/ https://jsfiddle.net/jonataswalker/z5Lgbjv8/
const Parent = {
template: `<div>
<span>parent content</span>
<component :is="view"></component>
</div>`,
data() {
return { view: '' }
}
}
const Other = {
template: `<div>
<h1>from Other</h1>
</div>`
}
const Slide = Vue.extend(Parent)
// how to pass template to the Parent`s slot?
new Slide({
data: { view: Other }
}).$mount('#container')
(This question is similar to this SO question . I am just gonna share a similar answer I post for that question here.) (这个问题类似于这个SO question 。我只是要分享一个类似的答案,我在这里为这个问题发布。)
The trick is simple.诀窍很简单。 Basically, when extending, create a new component that registers Parent
as a local component.基本上,在扩展时,创建一个将Parent
注册为本地组件的新组件。
Demo: https://jsfiddle.net/jacobgoh101/omjgmb3f/演示: https ://jsfiddle.net/jacobgoh101/omjgmb3f/
const Slide = Vue.extend({
components: {
Parent
},
template: `
<Parent>
<div style="color:red">I am a slot</div>
</Parent>
`
});
new Slide().$mount('#container')
If You can change Your source code structure, You should also be able to use jsx.如果你可以改变你的源代码结构,你应该也可以使用 jsx。 In Vue-Cli3 it requires additional babel plugin, in Nuxt it works out of the box).在 Vue-Cli3 中它需要额外的 babel 插件,在 Nuxt 中它是开箱即用的)。 You simply create some hook function as method or compute, for example:您只需创建一些钩子函数作为方法或计算,例如:
slotHook () {
return(
<template v-slot.../>
)}
and place it inside the render function.并将其放在渲染函数中。 Then, in the child (component extending the default one), You overwrite the slotHook method:然后,在子组件(扩展默认组件)中,您覆盖 slotHook 方法:
slotHook () {
return (
<template v-slot... some-differen-params:.../>
)}
This approach does not cause any errors/issues during render and works flawless.这种方法在渲染过程中不会导致任何错误/问题,并且可以完美运行。 Other approach might be to use PUG templates and their block & extend functionality.其他方法可能是使用 PUG 模板及其块和扩展功能。 I know I'm posting this response quite late, but maybe it could help somebody.我知道我很晚才发布此回复,但也许它可以帮助某人。
You have to pass it like this:你必须像这样传递它:
<Slide>
//HTML code here goes to slot
</Slide>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.