vue作用域插槽

官网有说明作用域插槽的使用方法,对照例子写了下,跑是跑成功了,但是还是有点不知道这东西存在的意义,父组件操作子组件数据,直接$emit不就行了,于是搜到了这个大神的文章,恍然大悟!作用域插槽使用场景就是有三个及以上层级的组件时,想要处理底层组件的数据,如果要分离业务设计,肯定是希望最高层级的父组件去处理,那就有跨层级处理的问题了,这个时候如果都使用$emit处理,那么中间层的组件就耦合了业务,这个时候就可以考虑使用作用域插槽

四层级组件举例

组件关系如图:
在这里插入图片描述
总共有四层关系,第一层想要操作第四层的组件数据。
这个时候代码可以这样写(如下伪代码),中心思想是把需要操纵数据的子组件一层层暴露给最顶层的父组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script src="../../js/vue.js"></script>
<div id="app">
  <comp-2-level :comp-2-level-data="parentData">
    <template slot-scope="comp2SlotScope">
      <comp-3-level :comp-3-level-data="comp2SlotScope.comp2Row">
        <template slot-scope="comp3SlotScope">
          <comp-4-level :comp-4-level-data="comp3SlotScope.row" @parent-click="itemClick"></comp-4-level>
        </template>
      </comp-3-level>
    </template>

  </comp-2-level>
</div>
<template id="comp2Level">
  <div>
    <div class="row">
        <slot :comp2Row="comp2LevelData"></slot>
    </div>
    <div class="row">
      <!--其他信息 -->
    </div>
  </div>
</template>
<template id="comp3Level">
  <div>
    <div>
      <!--这里正常情况是要写comp4Level的组件引用的,但是因为要做操comp4Level的数据,所以这里写了一个作用域插槽,你也可以
      在这插槽里面写上默认的代码,组件被使用的时候就有默认功能-->
      <slot :row="comp3LevelData"></slot>
    </div>
  </div>
</template>
<template id="comp4Level">
  <div>
     <!--此处省略一万行代码.....-->
      <a @click="comp4levelMeth(comp4LevelData)">{{comp4LevelData}}</a>
  </div>
</template>
<script>
  const comp2Level= {
    template: '#comp2Level',
    props: {comp2LevelData:Object}
  }
  const comp3Level={
    template: '#comp3Level',
    props:{comp3LevelData: Object}
  }
  const comp4Level = {
    template: '#comp4Level',
    props:{comp4LevelData: Object},
    methods: {
      comp4levelMeth(data){
        this.$emit('parent-click', data)
      }
    }
  }

  const app = new Vue({
    el: '#app',
    data: {
      parentData: {....},
    },
    components: {
      comp2Level,
      comp3Level,
      comp4Level
    },
    methods: {
      itemClick(item){
        console.log('图片点击了', item)
      }
    }
  })

</script>

</body>
</html>

上面伪代码如果看不懂,直接运行下面的真代码吧,vue.js自己导入就可以了:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
  <title>Title</title>
</head>
<body>
<script src="../../js/vue.js"></script>
<div id="app">
  <see-see :column-list="columnList">
    <template slot-scope="seeSlotScope">
        <commodity-list :commodity-list="seeSlotScope.seerow">
          <template slot-scope="slotScope">
            <commodity :commodity="slotScope.row" @parent-click="itemClick"></commodity>
          </template>
        </commodity-list>
    </template>

  </see-see>
</div>
<template id="seeSee">
  <div>
    <div class="row">
      <div v-for="item in columnList">
        <div>{{item.columnName}}</div>
        <!-- 填充commodityList-->
        <slot :seeRow="item.commodityList"></slot>
      </div>

    </div>
    <div class="row">
      seeSee圈footer
    </div>
  </div>
</template>
<template id="commodityList">
  <div>
    <div v-for="item in commodityList" class="col-md-4">
      <slot :row="item">{{item}}</slot>
    </div>
  </div>
</template>
<template id="commodity">
  <div>
    <img style="height:100px":src="commodity.pic"></img>
    <div>
      <a @click="onCommodityClick(commodity)">{{commodity.desc}}</a>
    </div>
  </div>
</template>
<script>
  const seeSee= {
    template: '#seeSee',
    props: {columnList:Array}
  }
  const commodityList={
    template: '#commodityList',
    props:{commodityList: Array}
  }
  const commodity = {
    template: '#commodity',
    props:{commodity: Object},
    methods: {
      onCommodityClick(commodity){
        this.$emit('parent-click', commodity)
      }
    }
  }

  const app = new Vue({
    el: '#app',
    data: {
      message: '你好',
      columnList: [
        {columnName: '有好货', commodityList:
                [
                  {pic:'1.jpg',url:'http://1.jpg',desc:'第一张图片'},
                  {pic:'2.jpg',url:'http://2.jpg',desc:'第二张图片'},
                  {pic:'5.jpg', ur:'http://5.jpg',desc:'第五张图片'}
                ]
        },
        {columnName: '爱逛街', commodityList:
                [
                  {pic:'3.jpg',url:'http://3.jpg',desc:'第三张图片'},
                  {pic:'4.jpg',url:'http://4.jpg',desc:'第四张图片'},
                  {pic:'6.jpg',url:'http://6.jpg',desc:'第六张图片'}
                ]
        }
      ]
    },
    components: {
      commodity,
      commodityList,
      seeSee
    },
    methods: {
      itemClick(item){
        console.log('图片点击了', item)
      }
    }
  })

</script>

</body>
</html>

上面大神的文章的完整代码我也撸了一遍,有需要的拿走:作用域插槽三级例子

应用场景举例

现有的elementui的table,如果想要实现对列编辑、删除等功能,就使用了作用域插槽:https://element.eleme.cn/#/zh-CN/component/table

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值