vue.js - Vue 组件槽不被视为子槽吗?
问题描述
假设我有一个父组件 Tabs,它将子 Tab 组件作为插槽。
所以设置是这样的:
选项卡(父)
<div>
<slot name="tabChild">
</div>
选项卡(儿童)
<div>
Tab {{name}}
</div>
我的应用
<Tabs>
<Tab slot="tabChild" name="1" ></Tab>
<Tab slot="tabChild" name="1" ></Tab>
</Tabs>
但是,在 Tabs (Parent) 组件中,当我尝试以编程方式访问其子组件时,如下所示:
选项卡组件
mounted(){
let childTabs = this.$children //this is empty??
childTabs = this.$slots //this is correctly the child Tab Components
}
此外,在 Tab (Child) 组件中,当我尝试访问其父组件时,我认为它是 Tabs 组件(因为它们被插入其中),它不是:
选项卡组件
mounted(){
let parentTab = this.$parent //this is MyApp (grandfather), NOT Tabs
}
为什么选项卡子组件插入更大的选项卡组件而不是其子组件?
解决方案
好吧,$parent
将始终引用嵌套在特定组件内部的“直接”父/包装器,因此当需要引用“根”父时,它并不十分可靠。
以下是官方文档的一些很好的摘录:
在大多数情况下,深入到父级会使您的应用程序更难调试和理解,尤其是当您更改父级中的数据时。稍后查看该组件时,将很难弄清楚该突变来自何处。[1]
使用
$parent
和$children
谨慎,因为它们主要用作逃生舱口。更喜欢使用道具和事件进行父子通信。[2]隐式父子通信:Props 和事件应该是父子组件通信的首选,而不是
this.$parent
或 mutating props。
一个理想的 Vue 应用程序是props down,events up。坚持这个约定会让你的组件更容易理解。[3]不幸的是,使用该
$parent
属性并不能很好地扩展到嵌套更深的组件。这就是依赖注入可能有用的地方,使用两个新的实例选项:provide
和inject
. [4]
这是一个演示上述建议的快速示例:
const Parent = Vue.extend({
template: `
<ul :style="{ columnCount: colCount }">
<slot></slot>
</ul>
`,
provide() {
return {
biologicalParent: this
}
},
props: ['value', 'colCount', 'message'],
methods: {
sayIt() {
const
num = this.$children.indexOf(this.value) + 1,
message = [
`I am child no. ${num}`,
`among ${this.$children.length} of my siblings`,
`in ${this.colCount} different lineages.`
]
.join(' ');
this.$emit('update:message', message);
}
},
watch: {
value: 'sayIt'
}
});
const Child = Vue.extend({
template: `<li v-text="name" @click="setChild"></li>`,
props: ['name'],
inject: ['biologicalParent'],
methods: {
setChild() {
this.biologicalParent.$emit('input', this);
}
}
});
new Vue({
el: '#demo',
data: () => ({
lineage: 3,
childCount: 10,
message: 'Click on a child for the associated message.',
lastChild: undefined
}),
components: {
Parent,
Child
}
});
input {
width: 4em;
}
li {
cursor: pointer;
}
.message {
background-color: beige;
border: 1px solid orange;
padding: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<table>
<tr>
<td>Child count:</td>
<td><input type="number" v-model="childCount" /></td>
</tr>
<tr>
<td>Lineage:</td>
<td><input type="number" v-model="lineage" /></td>
</tr>
</table>
<parent
v-model="lastChild"
:col-count="lineage"
:message.sync="message">
<child
v-for="(n, i) of Array.apply(null, {length: childCount})"
:key="i"
:name="`child #${i+1}`">
</child>
</parent>
<p class="message">{{ message }}</p>
</div>
这些provide
选项允许我们指定data
或methods
我们想要提供给后代组件。在上面的例子中,这就是Parent
实例。
请注意如何Child
在运行时(单击时)而不是编译时(渲染阶段)评估索引/编号。
推荐阅读
- angular - 使用 firebase 云功能向非谷歌服务器发送 GET 请求
- asp.net - 如何在同一个 localhost 实例上运行 asp.net 和 vuejs
- c# - 在 ASP.net Core 中自定义 swagger 以从 .json 文件中提取路由
- r - 使用动态名称进行因子转换
- maven-shade-plugin - 在 org.apache.maven.plugins.shade.resource.ServicesResourceTransformer 类中找不到“manifestEntries”
- google-apps-script - 如何将 Google Apps 脚本的范围缩小到特定文件
- python - 日期未在 Django 模板中呈现
- javascript - 密码验证正则表达式:要求和禁止某些字符
- flutter - 更改下拉菜单上的小部件 onchange 事件
- javascript - 如何将 JSON 转义字符串转换为纯 HTML 兼容字符串