我的动态组件(布局)不适用于 vuejs 中的命名插槽
My dynamic component (layout) doesn't work with named slots in vuejs
我在将动态生成的布局与命名插槽组合时遇到问题。
为了定义我的布局,我使用“component :is”
//app.vue
<template>
<component :is="layout">
<router-view />
</component>
</template>
<script>
computed: {
layout() {
const layout = this.$route.meta.layout || 'default'
return () => import(`@/app/layouts/${layout}.vue`)
}
},
</script>
//layouts/default.vue
<template>
<div>
<div>
<slot name="header" />
</div>
<div>
<div>
<slot name="sidebar" />
</div>
<div>
<slot name="default"/>
</div>
</div>
</div>
</template>
// views/page.vue
<template>
<div>
<template #header>
<h1>Primitives</h1>
</template>
<template #sidebar>
<ul>
<li v-for="primitive in sections.sections" :key="primitive">
<router-link :to="`/primitives/${primitive}`">{{primitive}}</router-link>
</li>
</ul>
</template>
<template #default>
<router-view :key="$router.path" />
</template>
</div>
</template>
但是现在我的代码中出现了这个错误
'v-slot' directive must be owned by a custom element, but 'div' is not.
并且控制台显示此错误
<\template v-slot> can only appear at the root level inside the receiving component
如果我删除主 div 我会得到错误
The template root requires exactly one element.
我做错了什么?
这个不好解释,请大家多多包涵...
我真的明白你想做什么,但不幸的是,这在 Vue 中是不可能的。
原因是插槽比 Vue 的 模板编译器 特性多于 运行时特性。我的意思是什么?当 Vue 模板编译器看到类似 <template #header>
的东西时,它会获取内部内容并将其编译成一个返回虚拟 DOM 元素的函数。此函数必须传递给某个组件,该组件可以调用它并将结果包含在它自己生成的虚拟 DOM 中。为此,模板编译器需要知道它应该将函数传递给哪个组件(这是 'v-slot' directive must be owned by a custom element, but 'div' is not.
错误消息的真正含义......即编译器正在“寻找”一个组件以将槽内容传递给...... .)
但是您正在尝试使用插槽,就好像它们在运行时是“可发现的”一样。为了让您的代码正常工作,动态布局组件必须 在运行时 以某种方式发现它的子组件(由于 <router-view />
也是动态的)有一些可以使用的插槽内容。这不是插槽在 Vue 中的工作方式。您可以 但不要指望父组件(在本例中为布局)可以“发现”在其子组件中定义的插槽内容...
不幸的是,您的问题的唯一解决方案是在每个“页面”中导入布局组件并将其用作模板中的根元素。您可以使用 mixins 来减少代码重复(定义 layout
computed)
@/mixins/withLayout.js
export default = {
computed: {
layout() {
const layout = this.$route.meta.layout || 'default'
return () => import(`@/app/layouts/${layout}.vue`)
}
}
}
views/page.vue
<template>
<component :is="layout">
<template #header>
<h1>Primitives</h1>
</template>
<template #sidebar>
<ul>
<li v-for="primitive in sections.sections" :key="primitive">
<router-link :to="`/primitives/${primitive}`">{{primitive}}</router-link>
</li>
</ul>
</template>
<template #default>
<router-view :key="$router.path" />
</template>
</component>
</template>
<script>
import withLayout from '@/mixins/withLayout'
export default {
mixins: [withLayout]
}
</script>
我在将动态生成的布局与命名插槽组合时遇到问题。
为了定义我的布局,我使用“component :is”
//app.vue
<template>
<component :is="layout">
<router-view />
</component>
</template>
<script>
computed: {
layout() {
const layout = this.$route.meta.layout || 'default'
return () => import(`@/app/layouts/${layout}.vue`)
}
},
</script>
//layouts/default.vue
<template>
<div>
<div>
<slot name="header" />
</div>
<div>
<div>
<slot name="sidebar" />
</div>
<div>
<slot name="default"/>
</div>
</div>
</div>
</template>
// views/page.vue
<template>
<div>
<template #header>
<h1>Primitives</h1>
</template>
<template #sidebar>
<ul>
<li v-for="primitive in sections.sections" :key="primitive">
<router-link :to="`/primitives/${primitive}`">{{primitive}}</router-link>
</li>
</ul>
</template>
<template #default>
<router-view :key="$router.path" />
</template>
</div>
</template>
但是现在我的代码中出现了这个错误
'v-slot' directive must be owned by a custom element, but 'div' is not.
并且控制台显示此错误
<\template v-slot> can only appear at the root level inside the receiving component
如果我删除主 div 我会得到错误
The template root requires exactly one element.
我做错了什么?
这个不好解释,请大家多多包涵...
我真的明白你想做什么,但不幸的是,这在 Vue 中是不可能的。
原因是插槽比 Vue 的 模板编译器 特性多于 运行时特性。我的意思是什么?当 Vue 模板编译器看到类似 <template #header>
的东西时,它会获取内部内容并将其编译成一个返回虚拟 DOM 元素的函数。此函数必须传递给某个组件,该组件可以调用它并将结果包含在它自己生成的虚拟 DOM 中。为此,模板编译器需要知道它应该将函数传递给哪个组件(这是 'v-slot' directive must be owned by a custom element, but 'div' is not.
错误消息的真正含义......即编译器正在“寻找”一个组件以将槽内容传递给...... .)
但是您正在尝试使用插槽,就好像它们在运行时是“可发现的”一样。为了让您的代码正常工作,动态布局组件必须 在运行时 以某种方式发现它的子组件(由于 <router-view />
也是动态的)有一些可以使用的插槽内容。这不是插槽在 Vue 中的工作方式。您可以
不幸的是,您的问题的唯一解决方案是在每个“页面”中导入布局组件并将其用作模板中的根元素。您可以使用 mixins 来减少代码重复(定义 layout
computed)
@/mixins/withLayout.js
export default = {
computed: {
layout() {
const layout = this.$route.meta.layout || 'default'
return () => import(`@/app/layouts/${layout}.vue`)
}
}
}
views/page.vue
<template>
<component :is="layout">
<template #header>
<h1>Primitives</h1>
</template>
<template #sidebar>
<ul>
<li v-for="primitive in sections.sections" :key="primitive">
<router-link :to="`/primitives/${primitive}`">{{primitive}}</router-link>
</li>
</ul>
</template>
<template #default>
<router-view :key="$router.path" />
</template>
</component>
</template>
<script>
import withLayout from '@/mixins/withLayout'
export default {
mixins: [withLayout]
}
</script>