1.个人理解的插槽
之所以使用组件,就是因为组件可以将复杂的页面分割成多个部分,每个 部分就是一个组件(也是一个vue文件)。要使用这个组件,只需要引入组件文件,并在模版中写入组件标签即可,引入了这个子组件,就相当于引入了这个组件的html模版,例如:
// App.vue
<template>
<div id="app">
<Hello />
</div>
</template>
// Hello组件
<template>
<div id="hello">
<h2>我是Hello组件</h2>
</div>
</template>
渲染之后就是
<div id="app">
<div id="hello">
<h2>我是Hello组件</h2>
</div>
</div>
父组件想要插入数据到子组件中,无非就是将数据通过属性绑定的形式,然后子组件通过props接收
// App.vue
<template>
<div id="app">
<!-- content=我是app组件传递的数据 -->
<Hello :content="content" />
</div>
</template>
// Hello组件
<template>
<div id="hello">
<h2>我是Hello组件 {{content}}</h2>
</div>
</template>
<script>
export default {
props:['content']
}
</script>
渲染结果
<h2>我是Hello组件 我是app组件传递的数据</h2>
通过上面例子,父组件可以通过props的形式传递数据给子组件,但是这种方法只能影响子组件的数据展示,无法对子组件的html模版结构产生影响,如果你想在父组件中插入一段html给子组件,显然无法做到,slot就是 为此而生的
2.slot基本用法
在原生的html中,我们经常在一个块级标签中插入n个标签,Vue中父组件给子组件插入标签也是这种写法
// App.vue
<template>
<div id="app">
<Hello>
<!-- 在子组件中插入标签 -->
<h2>我是插入的h2</h2>
</Hello>
</div>
</template>
然后在子组件中接收这个标签,子组件使用slot标签接收插入的标签,插入的标签会替换这个slot标签(slot标签的位置就是插入标签的位置)
// 子组件
<template>
<div id="hello">
<slot></slot>
<h2>我是Hello组件</h2>
</div>
</template>
渲染结果:
<div id="app">
<div id="hello">
<h2>我是插入的h2</h2>
<h2>我是Hello组件</h2>
</div>
</div>
这种插槽被称为匿名插槽,但是只能有一个(多个的话逻辑就有问题,因为不知道该由哪个插槽来替换所插入的标签元素)
2.具名插槽
如果有多个插槽,就需要为每个插槽添加一个标识,即name属性,方便对号入座
<template>
<div id="hello">
<slot name="top"></slot>
<h2>我是Hello组件</h2>
<slot name="bottom"></slot>
</div>
</template>
父组件插入标签元素时 设定slot属性 来关联对应的插槽
<template>
<div id="app">
<Hello>
<!-- 在子组件中插入标签 -->
<h2 slot="top">我是插入的h2</h2>
<h5 slot="bottom">我是插入的h5</h5>
</Hello>
</div>
</template>
插槽可以空着不用,父组件不插入标签元素,插槽就不会被渲染,利用这个特性可以控制子组件的某些空间是否展示对应的元素
插槽和props传参可以同时使用,对于必须要展示的标签可以props传参,选择性展示的标签可以使用插槽
3.插槽的默认内容
slot标签内可以写html代码,如果这个插槽没有被替换,会显示该插槽内的html内容,反之会被替换
<template>
<div id="hello">
<slot name="top">
<p>我是top插槽没使用的时候展示的内容</p>
</slot>
<h2>我是Hello组件</h2>
<slot name="bottom"></slot>
</div>
</template>
// App.vue
<template>
<div id="app">
<Hello>
<h5 slot="bottom">我是插入的h5</h5>
</Hello>
</div>
</template>
渲染结果
<div id="app">
<div id="hello">
<p>我是top插槽没使用的时候展示的内容</p>
<h2>我是Hello组件</h2>
<h5>我是插入的h5</h5>
</div>
</div>
4.slot-scope(作用域插槽) 为slot绑定数据
子组件传递给父组件的数据,子组件通过属性绑定,将相应的数据绑定到slot标签中,当父组件要使用这个slot时,就可以读取这个数据
// 子组件
<template>
<div id="hello">
<slot name="top" :list="list">
</slot>
<h2>我是Hello组件</h2>
<slot name="bottom"></slot>
</div>
</template>
<script>
export default {
data () {
return {
list: [
{
name: '乔治',
age: 4
},
{
name: '佩琪',
age: 8
}
]
}
}
}
</script>
父组件在替代slot的标签中添加 slot-scope属性,表示接受当前slot绑定的数据。slot-scope的值可以随意写,例如slot-scope="xxx"
// App.vue
<template>
<div id="app">
<Hello>
<template slot-scope="xxx" slot="top">
<p>{{xxx.list[0].name}}</p>
<p>{{xxx.list[0].age}}岁</p>
</template>
<h5 slot="bottom">我是插入的h5</h5>
</Hello>
</div>
</template>
slot-scope.png
传递的数据是包裹在对象内的,这样就可以接收多个数据。比如子组件的slot传递2个数据list和msg,接收的时候要使用xxx.list访问list,xxx.msg访问msg。获取了数据,就随你怎么使用了。
// 子组件
<slot name="top" :list="list" :msg="msg">
// 父组件
<template slot-scope="xxx" slot="top">
<p>{{xxx.list[0].name}}</p>
<p>{{xxx.list[0].age}}岁</p>
<p>{{xxx.msg}}</p>
</template>
网友评论