vue slot插槽的作用域在官方教程中有一条说明:
“父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。”
父级模版可以通过prop把参数传递给子级模版,但是反过来是不推荐的。
插槽v-slot就是用来反向传参的。
首先来看一下层级关系,一下是html页面中的dom元素实例
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Language" content="zh-cn">
<title>Template</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="components-demo" level="0">
<im-level-11 title="how are you." level="1">
{{ posts[2].title }}
<im-level-12 :name="posts[1].title" level="1">
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }} {{ posts[0].title }}
</template>
</im-level-12>
</im-level-11>
</div>
<script src="template.js"></script>
</body>
</html>
同步对照js代码如下
Vue.component('im-level-11',{
props:['title'],
data(){
return {count: 5,level:2}
},
template:`
<div>
<label> {{ title }} </label>
<button @click='count++'>
You clicked me {{ count }} times.
</button>
<slot></slot>
</div>
`
});
Vue.component('im-level-12',{
props:['name'],
data(){
return {
user:{
lastName:"AJS",
firstName:"Silvan"
},
level:2
};
},
template:`
<div>
<label> {{ name }} </label>
<slot v-bind:user="user"> {{ user.lastName }} </slot>
</div>
`
})
var vm = new Vue({
el: "#components-demo",
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
],
level:1
}
});
其中components-demo是根节点,在js中vue实例被绑定到了该节点上。
那么components-demo 作为level0
js代码中的vm Vue实例是level1
两个组件im-level-11 im-level-12 实际上是和vm实例同一级的。
在html中可以看到,im-level-11 和 im-level-12 可以直接调用vm实例中的posts数组对象,
虽然im-level-11 和 im-level-12 在html中是嵌套实现的,但是在js中是同级申明的。
在 im-level-11 和 im-level-12 组件内部,作为level2,他们各自的template模版只能直接调用组件内部的数据。
这个时候,子级给父级反向传参可以看im-level-12 的实现
im-level-12 内部有一个user对象,可以直接使用user.lastName值,
而父级level1要直接用同样的user对象则会报错。
在level2的插槽上即 im-level-12的 绑定user,把自己的user对象传去去。
在level1调用组件时直接使用 来接收传出的对象,该对象作为slotProps的属性存在,可以直接用过slotProps.user来访问。
"slotProps"只是一个自定义名称,可以随便改。
这里要吐槽官网的描述,也可能是我理解能力太差,之前一直搞混了。官网有这么一段说明:
<span>
<slot>{{ user.lastName }}</slot>
</span>
我们想让它的后备内容显示用户的名,以取代正常情况下用户的姓,如下:
<current-user>
{{ user.firstName }}
</current-user>
我一直没搞明白后备内容不是user.lastName 显示了用户的姓么,怎么又变成名了。还纠结了半天,官网指的lastName难道按照中国人的习惯是名字?
后来终于理解了,现在后备内容区域显示的是姓,要把他用组件改为名字显示。
这一下也终于搞明白,这个user是从子级组件里通过插槽slot传出来给父级组件渲染时调用的。
终于弄明白这个插槽的逻辑了,加油!