先说说插槽的使用:(才疏学浅,白话表述)可以把插槽理解为组件B中留下的一个坑,谁用这个坑谁就可以往里面填放东西,同时呢,谁也就要认组件B做儿子-----组件B也就成了这个来填坑的组件的子组件。

插槽不单单是可以让父组件用它填充东西,也可以引用子组件的数据,而父组件用坑的时候也就可以用子组件传过来的数据。

单个插槽(默认插槽、匿名插槽)

子组件:(slotdemoson.vue)

<template>
    <div>
        <h2>子组件</h2>
        <slot>
           <h3> 匿名插槽(●ˇ∀ˇ●)</h3>
        </slot>
    </div>
</template>
<script>
export default {
  name: 'slotdemoson',
}
</script>

 父组件:(slotdemo.vue)---既然使用子组件的插槽就的先import引入子组件

<template>
  <div>
    <h2>我是爸爸~</h2>
     <!--使用子组件-->
    <slotdemoson></slotdemoson>
  </div>
</template>

<script>
import slotdemoson from './Slotdemoson.vue'
export default {
  components: { slotdemoson },
}
</script>

只引用了子组件,但是没有使用子组件的插槽,那么插槽中如果有内容会默认显示出来

使用子组件的插槽,父组件要填坑了(给子组件里面加<template>来使用插槽),子组件不变,父组件修改代码如下:

<template>
  <div>
    <h2>我是爸爸~</h2>
    <!--使用子组件-->
    <slotdemoson>
      <template>
          <h4>--------给我儿子填坑--------</h4>
      </template>
    </slotdemoson>
  </div>
</template>

会发现:子组件代码不变,父组件使用给<template>中加入了一段文字,这段文字直接把子组件中的<slot>插槽中的文字替换了。——如果子组件有插槽而父组件使用子组件但不使用插槽,插槽内容默认展示;如果父组件使用了插槽,以父组件的填充内容为主。

提示:匿名插槽由于没有任何自身标识,所以建议子组件中只使用一次,如果使用多次,当父组件写了一个<template>***</template>的时候,将会给子组件中所有的匿名插槽都填充为***。


具名插槽(有具体名字,有标识的插槽)可以根据名字来有针对性的使用插槽

子组件:(slotdemoson.vue)

<template>
    <div>
        <h2>子组件</h2>
        <slot name="slot-fruits">
           <h3>这儿放水果!</h3>
        </slot>
        <hr>
        <slot name="slot-foods">
           <h3>这儿放美食!</h3>
        </slot>
    </div>
</template>

父组件:(只更新了template部分,省略了子组件的引入等代码)

<template>
  <div>
    <h2>我是爸爸~</h2>
    <slotdemoson>
        <div slot="slot-fruits">
            <p>葡萄柚</p>
            <p>猕猴桃</p>
        </div>
        <div slot="slot-foods">
            <h5>饺子</h5>
            <h5>意大利面</h5>
        </div>
        <!--注意:Vue3中要用v-slot去指向插槽名:<div v-slot=slot-foods> -->
    </slotdemoson>
  </div>
</template>

可以看到只是在使用子组件时,向其内部的结构标签div中加上了slot属性并指向了子组件中定义的插槽的插槽名,就把这个div按照对应的插槽名替换成子组件中的插槽了

如果把多个结构都指向了同一个插槽名,那么会把这些数据都渲染出来,后面的不会覆盖前面的 


作用域插槽(可视为携带数据的匿名插槽)没名,但可以携子组件的数据带给父组件

子组件:(通过 :数据别名=“数据” 来给到插槽,将数据绑定给这个插槽)

<template>
  <div>
    <h2>子组件</h2>
    <slot :fruits="Fruits"> 水果来啦! </slot>
  </div>
</template>

<script>
export default {
  name: 'slotdemoson',
   data() {
    return {
      Fruits: {
        'warmFruit':[
          ['红果','草莓', '红心火龙果', '红皮苹果', '圣女果'],
          ['黄果','香蕉', '菠萝', '黄桃', '葡萄柚', '柠檬'],
          ['橙果','橙子', '沙糖桔', '橘子'],
        ],
        'coolFruit':[
          ['黑果','东北冻梨', '黑枣'],
          ['蓝果','蓝莓', '蓝靛果'],
          ['紫果','飓风葡萄', '西梅', '桑葚', '黑布林李子'],
        ],
      },
    }
  },
}
</script>

<style>
</style>

父组件:(通过给template加 slot-scope 属性)

这里会将slot-scope属性的属性值作为一个对象-----用于保存子组件插槽中绑定的数据

这个用于保存插槽数据的slot-scope的属性值要通过子组件插槽定义的数据别名来访问数据

<template>
  <div>
    <h2>看看儿子给我带什么来了~</h2>
    <slotdemoson>
      <!--通过slot-scope来定义一个对象scope(名字可以随便起)来接收子组件传递过来的数据-->
      <template slot-scope="scope">
        <!--使用插值表达式直接把接收到的插槽数据渲染到页面(scope保存数据,所以真正的数据在scope的下一层)-->
        {{ scope.fruits }}
      </template>
    </slotdemoson>
  </div>
</template>

<script>
import slotdemoson from './Slotdemoson.vue'
export default {
  components: { slotdemoson },
}
</script>

<style>
</style>

scope.fruits实际可以拿到子组件的数据:Fruits 

父组件对插槽带来的数据进行遍历,并将数组元素渲染到页面上;

<template>
  <div>
    <h2>看看儿子给我带什么来了~</h2>
    <slotdemoson>
      <template slot-scope="scope">
        <!--通过层层对象指定获取到目标数据-->
        <p v-for="(warmItem,index) in scope.fruits.warmFruit" :key="index">
            <span v-for="(item,index) in warmItem" :key="index">{{item}}、</span>
        </p>
        <hr>
         <p v-for="(coolItem,index) in scope.fruits.coolFruit" :key="index">
            <span v-for="(item,index) in coolItem" :key="index">{{item}}、</span>
        </p>
      </template>
    </slotdemoson>
  </div>
</template>

        数据在组件本身上,通过插槽将数据做以绑定共享,数据要在什么结构中怎样使用就看使用者(父组件)了。


这几天在用Vue+ElementUI完成一个项目时,用到了作用域插槽。

场景就是:需要根据服务器响应来的数据渲染成一个表格到页面上,而表格中每一行的后面都有个操作列,可以对这一行的数据进行修改、删除等。一提到对这一行的数据进行修改、删除就必然得获取到这一行数据中的唯一标识(俗话说就是ID),那在ElementUI中就给table-column赋予了一项技能,就是使用插槽,ElementUI预设了三个参数(row, column, $index)。

可以通过插槽中定义的接收数据的对象来调用,调用row也就可以获取到这一行的数据,再从中提取id也就拿到了这一行数据所对应的id值,也就可以根据id向服务器发起修改或删除的请求了。

这里做以简化,假设Fruits就是服务器响应的数据,并将其绑定给el-table,ElementUI提供了一个很nice的功能:给表<el-table>的列<el-table-column>使用作用域插槽,可以通过slot-scope的属性值来调用row获取这一行的数据。

组件template 代码:

<template>
  <div>
    <el-table border stripe :data="Fruits">
      <el-table-column
        label="颜色"
        prop="fcolor"
        width="100px"
      ></el-table-column>
      <el-table-column
        label="描述"
        prop="finfo"
        width="150px"
      ></el-table-column>
      <el-table-column label="行信息集" width="350px">
        <!--重点来啦!这里使用作用域插槽,ElementUI有内置的功能,接收数据的对象调用row就可以获取这一行的数据-->
        <template slot-scope="scope">
          {{ scope.row }}
        </template>
      </el-table-column>
      <el-table-column label="例举">
        <template slot-scope="scop">
          <el-tag
            :type="scop.row.id == 1 ? 'danger' : scop.row.id == 2 ? 'info' : ''"
            v-for="(item, index2) in scop.row.flist"
            :key="index2"
            >{{ item }}
          </el-tag>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

组件script 代码:(这里Fruits的数据格式要参考ElementUI中的表格引用的数据格式)

<script>
export default {
  data() {
    return {
      Fruits: [
        {
          id: 1,
          fcolor: '红果',
          finfo: '红红的果实',
          flist: ['草莓', '红心火龙果', '红皮苹果', '圣女果'],
        },
        {
          id: 2,
          fcolor: '紫果',
          finfo: '紫不溜球儿的果实',
          flist: ['飓风葡萄', '西梅', '桑葚', '黑布林李子'],
        },
        {
          id: 3,
          fcolor: '蓝果',
          finfo: '湛蓝湛蓝的果实',
          flist: ['蓝莓', '蓝靛果'],
        },
      ],
    }
  },
}
</script>

 组件style 代码:

<style scoped>
.el-tag {
  margin-right: 10px;
}
</style>

页面渲染效果:

(可见这一行的数据都可以拿到,当涉及通过ID对这一行数据进行删改时,ID的获取不是事儿) 

ElementUI-table官方文档 最下面有这个插槽功能的解释 ↓:

如果是scope.column会得到这一列的信息:

 如果是scope.$index会得到这一行是第几行(索引):

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐