vue作用域插槽

发布时间:2023-12-23 09:00

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

四层级组件举例

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

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
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>
      
      <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>Titletitle>
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>
        
        <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

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号