slot 插槽 , 是用在组件中, 向组件分发内容. 它的内容可以包含任何模板代码, 包括 html.
vue 在 2.6.0 中, 具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令). 它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍有用的特性. 但是将会在 vue 3 中, 被废弃的这两个, 不会被支持即无效.
在 2.6.0 之前, 插槽的用法:
1. 匿名插槽.
以 .vue 这种单文件模块为例
- // 创建 testSlot.vue 组件
- <template>
- <div>
- //slot 里面也可以设置内容, 这个可以设置不传内容时, slot 有个默认值替换
- <slot > 这里面是 slot 的默认值 </slot>
- <h3 > 子组件页面 </h3>
- </div>
- </template>
- <script>
- export default {
- props:[],
- data:function(){
- return {}
- }
- }
- </script>
- <style>
- </style>
- // 引用 testSlot 组件
- <template>
- <div>
- <h1 > 引用 testSlot 组件的页面 </h1>
- <testSlot>
- {{msg}}
- </testSlot>
- </div>
- </template>
- <script>
- import testSlot from '../components/testSlot'
- export default{
- data () {
- return {
- msg:'这是动态传入的 slot 的内容'
- }
- },
- components:{ testSlot }
- }
- </script>
- <style>
- </style>
结果:
注意事项:
1) 匿名的方式, 就是指把在引用组件的时候, 里面传的内容, 全部一起传送到组件页面中 <slot></slot> 所在的位置.
2) 只要组件中有 <slot></slot> , 并且不管有多少个, 都会全部渲染为传过来的内容.
3) <slot></slot > 里面也可以设置内容, 这个内容是保证引入组件的时候, 有个默认值. 当然,<slot></slot > 里面不设置内容也可以, 这样只是没有默认值, 是不会报错的.
4) 传递的内容, 也可以是动态的, 如同上面一样. 但是要注意的是, 这个内容不能是 引用组件的时候组件上的内容, 要注意作用域. 可以查看官网 插槽编译作用域.
5) 如果传递的内容, 没有 slot 来接收, 那么, 传递的内容就会被抛弃掉, 不会起作用.
5) 那这个时候, 如果我想某个 <slot></slot> 传指定的 内容呢? 那这个时候就需要具名插槽了.
2. 具名插槽, 就是给插槽指定名称, 然后 一 一对应
- // 引入组件的页面
- <testSlot>
- <template slot='header'>
- <p>------------header----------------</p>
- <h3 > 这是 header1 的内容 </h3>
- <p > 这是 header2 的内容 </p>
- </template>
- <template slot='footer'>
- <p>------------footer----------------</p>
- <h3 > 这是 footer1 的内容 </h3>
- <p > 这是 footer2 的内容 </p>
- </template>
- <p>-----------default-----------------</p>
- <p > 这是 default 剩下的内容 1</p>
- <p > 这是 default 剩下的内容 2</p>
- </testSlot>
- // 组件当前页面
- <slot>--- 默认内容 ---</slot>
- <h3>slot 组件页面 </h3>
- <slot name='header'>---header 的默认内容 ---</slot>
- <slot name='footer'>---footer 的默认内容 ---</slot>
结果:
注意事项:
1) 引入组件的页面, 如果是多个内容, 需要用 template 包裹起来, 并且添加 slot 属性和 自定义值 .
2) slot 的值 需要和 组件中 <slot name='xxx'></slot> name 的值相对应.
3) 如果剩下的内容没有包裹起来并制定值的话, 那么这些内容会被渲染到 组件中 所有的 <slot></slot> 所在的位置.
4) 如果 slot 设置为 default 和 name 设置为 default, 那就和没设置 slot 与 name 是一样的.
5) 和 vue 2.6.0 以后的具名插槽相比 template 上的 slot='xxx' 只需要 改成 v-slot : xxx 就行了, 等号改成了冒号, 并且值没有引号, 带引号反而会报错.
6) 具名插槽只需要 name 值与 slot 的值 对应 , 插槽的顺序是没有关系的.
3. slot-scope 作用域插槽.
这个的作用, 主要就是当向组件发送的内容需要和组件的 props 属性的内容有联系时, 才使用这个作用域插槽. 简单点来说就是: 可以使用 子组件的数据和 父组件传过来的 props 的值.
- // 引入组件的页面
- <template>
- <div>
- <!-- 这里向组件传入 props-->
- <slotScope :message='msg'>
- <!-- 这里的 thing 是随便取的名称, 不与任何地方对应 -->
- <div slot='sayWhat' slot-scope='thing'> 说了:{{thing.said}}</div>
- <!-- 这里的 val 也是随便取的名称, 不与任何地方对应 -->
- <template slot='listbox' slot-scope='val'>
- <p>{{val.send.text}}</p>
- </template>
- </slotScope>
- </div>
- </template>
- <script>
- import slotScope from '../components/slotScope'
- export default{
- data () {
- return {
- msg: '这是动态传入的 slot 的内容',
- }
- },
- components:{slotScope }
- }
- </script>
- <style>
- </style>
- // 组件页面
- <template>
- <div>
- <!-- 这里最重要的是 :send=value,send 也是可以随便取的, 表示要传过去的值 -->
- <slot name='listbox' v-for='value in list' :send='value'></slot>
- <!-- 这里最重要的是 :said='message',said 也是可以随便取的, 表示要传过去的值 -->
- <slot name='sayWhat' :said='message'></slot>
- <ul>
- <li v-for='item in list' :key='item.id'>{{item.text}}</li>
- </ul>
- </div>
- </template>
- <script>
- export default {
- props:['message'],
- data:function(){
- return {
- list:[{
- "id":10,
- "text":"苹果"
- },{
- "id":20,
- "text":"香蕉"
- },{
- "id":30,
- "text":"梨"
- },{
- "id":40,
- "text":"芒果"
- }]
- }
- }
- }
- </script>
- <style>
- </style>
结果:
注意事项:
1) 作用域插槽主要是 使用子组件的任何数据 来达到自定义显示内容的目的
2) 作用域插槽最最最最最重要的一步, 即是在 < slot></slot> 上绑定数据 , 如果没有绑定数据, 则父组件收到的, 只是一个空对象 { }.
3) 作用域插槽中 <slot></slot> 上绑定数据, 可以是写死的, 也可以是动态绑定的. 如果是动态绑定的, 则也需要 v-bind:xxx
4) 作用域插槽中 <slot></slot> 上绑定的数据 也可以传一个定义好的有返回值的 mthods 方法. 比如我定义了 <slot what='say()'></slot> , 然后 say 方法为: say:function(){ return '我说了' } . 最后得到的结果就是 "我说了", 当然, 动态绑定一定要加 v-bind:xxx.
5) 当 <slot></slot> 绑定上数据之后, 引用组件的地方 中 发送的内容就能通过 slot-scope 来获取. 获取到的内容, 就是一个对象, 比如 <slot name='sayWhat' said='message'></slot> 我这里绑定 said='message' 之后, 那边接收到的就是 { said:"xxxx"} 一个对象.
6) slot-scope 可以接收任何有效的可以出现在函数定义的参数位置上的 JavaScript 表达式.
vue 2.6.0 之后 v-slot 只能用在 组件 component 或者 template 上 , 用在 div 或 p 这种标签上是会报错的
1. 具名插槽的变化
- <testSlot>
- <!--2.6.0 以前的写法 -->
- <template slot='header'>
- <p>------------header----------------</p>
- <h3 > 这是 header1 的内容 </h3>
- <p > 这是 header2 的内容 </p>
- </template>
- <!--2.6.0 之后的写法 -->
- <template v-slot:header>
- <p>------------header----------------</p>
- <h3 > 这是 header1 的内容 </h3>
- <p > 这是 header2 的内容 </p>
- </template>
- </testSlot>
1) slot='xxx' 改成了 v-slot : xxx 并且冒号后面这个名称不能打引号
2) 组件页面中 slot 的内容没有变化
3) 2.6.0 之后 具名插槽 v-slot:header 可以缩写为 #header , 必须是有参数才能这样写!!! # = "xxx" 这样是不行的 #default = 'xxx' 这样才可以
2. 作用域插槽的变化
- <slotScope :message='msg'>
- <!--2.6.0 之前的写法 -->
- <div slot='sayWhat' slot-scope='thing'> 说了:{{thing.said}}</div>
- <template slot='listbox' slot-scope='value'>
- <p>{{value.send.text}}</p>
- </template>
- <!--2.6.0 之前的写法, 不能单独用在 html 标签上 -->
- <template v-slot:sayWhat='thing'>
- <div > 说了:{{thing.said}}</div>
- </template>
- <template v-slot:listbox='value'>
- <p>{{value.send.text}}</p>
- </template>
- </slotScope>
1) 两个属性合并成了一个 v-slot : 插槽名称 = '传过来的值' .
2) 组件页面中 slot 的内容没有变化 .
3)v-slot 不能用在 HTML 标签上 .
4) 如果是默认插槽 可以写成 v-slot='xxx'.
5) 还增加了 可以解构插槽 props 和 设置默认值的内容, 具体的可以查看官网 解构插槽
3. 新增的还有 动态插槽名
什么是动态插槽名? 大致就是动态指令参数也可以用在 v-slot 上, 这个就要涉及到 2.6.0 新增的 动态参数
- <template v-slot:[attrContent]='msg'>
- xxx
- </template>
这个 attrContent 会被作为一个 JavaScript 表达式进行动态求值, 求得的值将会作为最终的参数来使用. 比如这里 attrContent 最终的值为 default 则渲染出来的结果 就是 v-slot:default='msg' .
注意:
1) 单独在 [ ] 方括号中也可以使用表达式, 但是不能存在引号和空格
2) 当然 这个动态的值 可以通过 方法, 计算属性, 或者 data 数据 里面的内容. 重要的是这个动态的值 是 引用组件的 作用域. 简单点说就是父级组件的作用域.
例如, 上面 v-slot:sayWhat='thing' 可以写成:
1) v-slot:[first+sec]='thing' 注意 加号两边不能留空格
2) v-slot:[attr]='thing' 3) v-slot:[attrs]='thing' 4) v-slot:[getattr()]='thing' export default{ data () { return { msg: '这是动态传入的 slot 的内容', attr:'sayWhat', first:'say', sec:'What', } }, components:{ slotScope }, computed:{ attrs:function(){ return 'sayWhat' } }, methods:{ getattr(){ return 'sayWhat' } } }
到此, 插槽的内容就介绍完毕了.^_^ Y
来源: https://www.cnblogs.com/zjjDaily/p/10518546.html