Vue插槽
-
作用:让父组件可以向子组件指定位置插入内容(可以是HTML结构,也可以是其他组件),这也是一种组件间通信的方式
-
分类:默认插槽、具名插槽、作用域插槽
-
理解:父组件中把子组件写成双标签形式,在双标签里面写上内容,在子组件定义插槽
<slot></slot>
后就会将该内容插入到子组件的指定位置(<slot></slot>
所在的位置),至于样式,写在父组件或子组件里都可- 样式写在父组件中:解析后的结构带着样式插入插槽
- 样式写在子组件中:解析后只把结构插入插槽,样式在子组件中控制
-
使用方式:
1. 默认插槽:
父组件中: <Child> <!-- Child为子组件标签 --> <div>html结构{{父组件中的数据}}</div> </Child> 子组件中: <template> <div> <!-- 定义插槽 父组件不传递结构时<slot></slot>中显示默认的内容--> <slot>插槽默认内容...</slot> </div> </template>
2. 具名插槽:(父组件数据给子组件)
父组件中: <Child> <!-- 写法1:slot='插槽名' 不推荐使用,好像2.6之后的版本被废弃了--> <template slot-scope="center"> <!-- 如果写多个center也不会覆盖,都会被写到插槽里 --> <div>html结构1{{父组件的数据直接使用}}</div> </template> <!-- 写法2: v-slot:插槽名 推荐使用--> <template v-slot:footer> <!-- v-slot这种写法只能写在template里,是新的api --> <div>html结构2{{父组件的数据直接使用}}</div> </template> <!--v-slot简写: #插槽名 template中的结构会放到子组件中<slot>的name属性为main的位置--> <template #main> <!-- #插槽名是 v-slot:插槽名的简单写法 --> <div>html结构2{{父组件的数据直接使用}}</div> </template> </Child> 子组件中: <template> <div> <!-- 定义插槽 name属性区分不同的插槽--> <slot name="center">插槽默认内容...</slot> <slot name="footer">插槽默认内容...</slot> <slot name="main">插槽默认内容...</slot> </div> </template>
3. 作用域插槽:(子组件数据给父组件)
-
理解:数据在子组件自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Child组件中,但使用数据所遍历出来的结构由App组件决定)把子组件数据给父组件
-
语法:
注:slot-scope是旧api(不推荐使用),v-slot是最新的
父组件中: <!-- 写法1: slot-scope='scope(这是随便取的名字)' 不推荐使用--> <Child> <template slot-scope="scope"> <!-- 或写成slot-scope="{games}解构形式也可以" --> <!-- 生成的是ul列表 --> <ul> <li v-for="g in scope.games" :key="g">{{g}}</li> </ul> </template> </Child> <!-- 写法2: v-slot=scope 推荐使用--> <Child> <template v-slot="scope"> <!-- 或写成v-slot="{games}"解构形式也可以 --> <h4 v-for="g in scope.games" :key="g">{{g}}</h4> </template> </Child> 子组件中: <template> <div> <slot :games="games"></slot> <!--可以传多个值,用的时候scope.xxx就行--> </div> </template> <script> export default { name:'Child', //数据在子组件自身 data() { return { games:['红色警戒','穿越火线','劲舞团','超级玛丽'] } }, } </script>
-
4.具名插槽和作用域插槽一起使用:
<!-- 子组件的插槽中: obj是要传递给父组件的值 name是该插槽的名字-->
<slot :obj="{a,b}" name="child">默认要显示的内容</slot>
<!-- 父组件child组件标签的template标签上: -->
<child>
<template v-slot:child="scope"> <!-- 这里如果直接写成v-slot='scope'则不会生效 页面不会展示数据!
<h2>{{ scope.obj }}</h2>
</template>
</child>
```