很多人知道插槽分为三种,但是实际到elementui当中为什么这么用,就一脸懵逼,接下来就跟大家聊一聊插槽在elementui中的应用,并且自己写一个类似el-table的组件
vue的slot分为三种::匿名插槽,具名插槽, 作用域插槽,主要作用:让父组件可以向子组件指定位置插入 html 结构,也是一种组件间通信的方式,适用于父组件=>子组件
匿名组件相当于一个占位符,将父组件的数据传入子组件的slot标签内
父组件:
<template> <ChildSlot>父组件调用</ChildSlot> </template> <script> import ChildSlot from "@/components/ChildSlot"; export default { components:{ ChildSlot } } </script>
子组件:
<template> <h1>我是子组件</h1> <slot></slot> </template> <script> export default { name: "ChildSlot" } </script>
运行结果如下:
此时父组件中的“父组件调用”这段内容就传递到了子组件,并填入了slot挖的坑当中
具名插槽相当于给插槽添加了一个名字(给插槽加入name属性就是具名插槽)
父组件:
<template> <child-slot> <template v-slot:username>我是父组件传递的用户姓名</template> </child-slot> <child-slot> <template v-slot:age>我是父组件传递的年龄</template> </child-slot> </template> <script> import ChildSlot from "@/components/ChildSlot"; export default { components:{ ChildSlot } } </script>
子组件:
<template> <h1>我是子组件</h1> <slot name="username"></slot> <slot name="age"></slot> </template> <script> export default { name: "ChildSlot" } </script>
运行结果如下:
此时父组件中的根据slot的name,将内容填入了slot挖的坑当中,一个萝卜一个坑
与前两者的不同 slot自定义:name="值" 子组件可向父组件传递信息
父组件:
<template> <child-slot> <template v-slot="{username}">我是子组件传递的用户姓名:{{username}}</template> </child-slot> </template> <script> import ChildSlot from "@/components/ChildSlot"; export default { components:{ ChildSlot } } </script>
子组件:
<template> <h1>我是子组件</h1> <slot :username="username"></slot> </template> <script> export default { name: "ChildSlot", data(){ return{ username:'java', } } } </script>
运行结果如下:
通过作用域插槽,我们可以将子组件中的值传入到父组件,在父组件进行数据处理后,填坑到子组件
先看一个el-table的例子,当需要对一行中的某一个单元格的内容进行处理的时候,需要用到slot插槽,例如下面的姓名name的处理
<template> <el-table :data="tableData" style="width: 100%"> <el-table-column label="姓名" width="180"> <template slot-scope="scope"> <el-popover trigger="hover" placement="top"> <p>姓名: {{ scope.row.name }}</p> <p>住址: {{ scope.row.address }}</p> <div slot="reference" class="name-wrapper"> <el-tag size="medium">{{ scope.row.name }}</el-tag> </div> </el-popover> </template> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </template>
参照el-table,实现我们自己的table组件,讲解下为什么需要用插槽,用了哪些插槽
<el-table
:data="tableData"
style="width: 100%">
<template> <div> <slot></slot> </div> </template> <script> export default { name: "MyTable" } </script>
<template> <div> <div> <!--通过传递label标签,展示表头--> <span v-if="label">{{ label }}</span> </div> <!--获取主页面的data值:$parent.$parent.$data.tableList--> <div v-for="(user,index) in $parent.$parent.$data.tableList" :key="index"> <!--当传递prop属性的时候,就取user用户的数据--> <div v-if="prop">{{user[prop]}}</div> <!--当不传递prop属性的时候,将用户的数据通过row属性,传递到父组件当中,也就是app.vue--> <slot v-else :row="user"></slot> </div> </div> </template> <script> export default { name: "MyTableColumn", props: { prop: {type: String}, label: {type: String} } } </script>
我们通过my-table标签,将内容my-table和my-table-column放置到my-table的匿名插槽中,并通过子组件的props属性,接收prop和label。如同elementui一样,如果prop为空,子附件将父组件的user通过作用域插槽传递到父组件,并在父组件进行处理
<template> <div> <my-table :data="tableList" style="display: flex; flex-direction: row;"> <my-table-column prop="name" label="姓名"></my-table-column> <my-table-column prop="sex" label="性别"></my-table-column> <my-table-column label="地址"> <template v-slot="scope"> <span style="background-color: deepskyblue">{{scope.row.address}}</span> </template> </my-table-column> </my-table> </div> </template> <script> import MyTable from "@/components/MyTable"; import MyTableColumn from "@/components/MyTableColumn"; export default { name: 'App', components:{ MyTableColumn, MyTable }, data(){ return{ tableList:[ { name: 'java大师1', sex: '男', address: '西藏1' }, { name: 'java大师2', sex: '男', address: '西藏2' }, { name: 'java大师3', sex: '男', address: '西藏3' }, { name: 'java大师4', sex: '男', address: '西藏4' } ] } } } </script>
展示结果如下: