scoped slots(作用域插槽深入理解)$scopedSlots


vue中插槽作用是什么?就是子組件寫一個<slot>標簽占一個坑,父組件在使用這個子組件的時候,在子組件標簽中加入一些內容,這些內容將在占坑的地方出現

作用域插槽是什么?父組件通過在子組件中使用插槽填充內容的時候,可以通過slot-scope屬性獲取 子組件中<slot>標簽 通過屬性 傳遞過來的子組件的作用域 的值。

//parent.vue
<child :data="data">
	//這個scope隨意起名,代表的就是子組件slot標簽所有屬性組成的對象
    <span slot-scope="scope">{{ scope.name }}</span>
</child>

//child.vue
<div>
	子組件{{data}}
	<slot :name="name"></slot>
</div>

 

想象第一個場景:一個商品列表,點擊每個商品跳轉到詳情頁知道了什么意思,以及用法,那他的應用場景是什么呢?

 

 

首先將商品卡片寫成一個組件GoodsCard.vue,在GoodsList.vue中一個v-for循環商品card

<goods-card v-for="(item,index) in goodsList" @clickGoods="onGoodsClick"></goods-card>

 


第一個場景實現了,沒啥問題,現在想象第二個場景,比如,淘寶網站上,有兩組商品列表子組件只需要在點擊商品的時候觸發this.$emmit("clickGoods",item),將數據傳給父組件進行跳轉

 

 

此時GoodsList.vue就需要抽成組件了,在商品GoodsPage中v-for調用GoodsList.vue,產生多個商品列表

這樣跳轉詳情頁的話,如果還用this.$emit就需要三層傳遞click,card->goodsList->goodspage,那這樣子組件跟業務扯上關系,顯得不純粹,這個時候就用上了作用於插槽

<el-row :gutter="20">
        //columnList 存儲多個商品列表
        <el-col :span="12" v-for="(column, index) in columnList" :key="index">
                <goods-list :goodsList="column.goodsList">
                    <template slot-scope="scope">
                        <!-- 這里只需要給GoodsCard組件傳入數據,響應GoodsCard組件的onGoodsClick事件即可。
                        事件不必攜帶參數,完全符合父到子的數據流向,而不會發生子組件又給父組件反向發數據的情況 -->
                        <goods-card @click="onGoodsClick(scope.row)"></goods-card>
                    </template>
                </goods-list>
        </el-col>
</el-row>
<el-row :gutter="20">
        <el-col :span="8" v-for="(item, index) in goodsList" :key="index">
            <slot :row="item"></slot>
        </el-col>
</el-row>

 

 

GoodsList.vue應該是這樣的,<slot>設置屬性item,這樣父組件就可以通過作用域插槽訪問到點擊的項,而無需觸發this.$emit

知道了作用域插槽使用場景,但是這就是作用域插槽的全部嗎?不是

官方提供了兩個API,分別是this.$slots和this.$scopedSlots,並且官方提示:vm.$slots和vm.$scopedSlots在使用渲染函數開發一個組件時特別有用。

首先看一下這兩個在使用的時候輸出什么

<template>
  <test>
    <div slot="header">slot: header</div>
    <div slot-scope="scope">slot: {{scope}}</div>
    <div slot="footer">slot: footer</div>
  </test>
</template>

<script>
import Test from './test.vue'
export default {
  components: {
    Test
  }
}
</script>
<template>
  <div>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script>
export default {
  data () {
    return {
      test: {
        name: 'default'
      }
    }
  },
  mounted () {
    console.log(this.$slots, '$slots')
    console.log(this.$scopedSlots, '$scopedSlots')
  }
}
</script>

 

 

在這里插入圖片描述 

可以看出是否是$scopedSlots,就是使用插槽時是否有slot-scope特性

!!!通過控制台打印結果,明晰this.$slots和this.$scopedSlots[name](),結果是vnode,相當於<slot>作用

我們用jsx寫一個例子看一下:

 

<script>
export default {
  props: {
    data: {
      type: Array,
      default () {
        return []
      }
    }
  },


  data () {
    return {
    }
  },
    
  render (h, vm) {
    return (
      <ul>
        {this.data.map(item => (
          <li>
            //傳遞給作用域對象                插槽內容               父級傳過來的數據
            {this.$scopedSlots.default(item)|| this.$slots.default || item.name}
            //意思就是告訴父組件你插槽內容是哪一項
          </li>
        ))}
      </ul>
    )
  }
}
</script>

 

<template>
  <test :data="data">
    //scope就是this.$scopedSlots.default(item)傳遞過來的item
    <span slot-scope="scope">{{scope.name}} | vm.scopedSlots的使用</span>
  </test>
</template>

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

  data () {
    return {
      data: [
        { name: 111 },
        { name: 222 },
        { name: 333 }
      ]
    }
  }
}
</script>

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM