Vue.js插槽slot和作用域插槽slot-scope學習小結


一般來說,在Vue項目中使用父子組建時,都是把通用的HTML結構提取出來寫成一個子組件,需要動態展示的數據用過prop屬性傳遞,不過有時候我們可能想給子組件傳遞一個HTML代碼,這個時候用prop不太適用,Vue給我們提供了slot(插槽)可以實現這種應用場景.下面是自己學習后總結的幾種插槽使用方式
1. 普通使用方式
子組件
<template>
  <div>
    <!-- 如果有多個插槽,可以通過name命名 -->
    <div style="background-color: yellowgreen">
      <slot name="header"></slot>
    </div>
    <!-- 父組件傳遞過來的值會展示在slot標簽中 --> 
    <slot></slot>
    <ul v-if="todo">
      <li>姓名: {{todo.name}}</li>
      <li>年齡: {{todo.age}}</li>
      <li>愛好: {{todo.hobby}}</li>
    </ul>
    <div style="color: gold">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: 'child',
  props: {
    todo: Object
  },

  data () {
    return {
    }
  },

  created () {
    console.log(this.todo, 'todo')
  }
}

</script>

// 父組件
<template>
  <div>
  <!-- 引入子組件 -->
    <child :todo="list">
      <!-- 這里的內容會渲染到子組件name為header的標簽中 -->
      <template slot="header">
        <p>放在頭部的內容</p>
      </template>
      <!-- 子組件雙標簽中的內容會被渲染到子組件的slot標簽里 -->
      <h3>插槽標題</h3>
      <!-- 這里的內容會渲染到子組件name為footer的標簽中 -->
      <template slot="footer">
        <p>放在底部的內容</p>
      </template>
    </child>
  </div>
</template>

<script>
import child from './child'
export default {
  name: 'parent',
  components: {child},

  data () {
    return {
      list: {
        name: '靈夢', 
        age: 18, 
        text: '熱愛學習', 
        hobby: '踢足球'
      }
    }
  }

}
</script>  

渲染效果:

 

2. 作用域插槽
如果你希望從子組件獲取數據,進行其他數據展示,這個時候你可以使用作用域插槽
子組件
<template>
  <div>
    <ul v-if="todo.length" v-for="item in todo" :key="item.id">
      <li>姓名: {{item.name}}</li>
      <li>年齡: {{item.age}}</li>
      <li>愛好: {{item.hobby}}</li>
    </ul>
  </div>
</template>
<script>
export default {
  name: 'child',
  props: {
    todo: Array
  }

</script>

// 父組件
<template>
  <div>
  <!-- 引入子組件 -->
    <child :todo="list">
    </child>
  </div>
</template>

<script>
import child from './child'
export default {
  name: 'parent',
  components: {child},

  data () {
    return {
      list: [
        {name: '靈夢', age: 18, text: '熱愛學習', hobby: '踢足球', id: 1},
        {name: '李明', age: 13, text: '畫畫很棒', hobby: '畫畫', id: 2},
        {name: '韓梅梅', age: 25, text: '性格文靜', hobby: '做手工', id: 3}
      ]
    }
  }

}
</script> 
普通調用,渲染出來的數據就是這樣,但是如果我們想在第二項渲染中把hobby改成text,這時候就需要子組件把數據傳過來,父組件改變渲染方式了
 
// 子組件
<template>
  <div>
    <ul v-if="todo.length" v-for="(item,index) in todo" :key="item.id">
      <li>姓名: {{item.name}}</li>
      <li>年齡: {{item.age}}</li>
      <!-- 如果是第二項,就使用作用域插槽,重新展示 -->
      <li v-if="index === 1">
        <!-- 定義了content把item傳遞到父組件,定義的名字可以隨意取,需要傳遞的數據寫在后面 -->
        <slot :content="item"></slot>
      </li>
      <li v-else>愛好: {{item.hobby}}</li>
    </ul>
  </div>
</template>
<script>
export default {
  name: 'child',
  props: {
    todo: Array
  }

</script>

// 父組件
<template>
  <div>
  <!-- 引入子組件 -->
    <child :todo="list">
      <!-- 在子組件用slot-scope結收傳遞過來的數據,接收的名字可以隨意取 -->
      <template slot-scope="scope">
      <!-- scope后接的就是你在子組件定義的傳遞值的名稱,scope.content就拿到了傳遞過來的值,在這里可以直接使用 -->
          描述: {{scope.content.text}}
      </template>
    </child>
  </div>
</template>

<script>
import child from './child'
export default {
  name: 'parent',
  components: {child},

  data () {
    return {
      list: [
        {name: '靈夢', age: 18, text: '熱愛學習', hobby: '踢足球', id: 1},
        {name: '李明', age: 13, text: '畫畫很棒', hobby: '畫畫', id: 2},
        {name: '韓梅梅', age: 25, text: '性格文靜', hobby: '做手工', id: 3}
      ]
    }
  }

}
</script>

 

渲染出來的效果是這樣,第二項李明的展示內容就改變了
 
在很多Vue的插件中也有使用作用域插槽的,比如element-ui的table組件,它就可以通過添加作用域插槽改變渲染的原始數據


免責聲明!

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



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