vue-slot與slot-scope詳解


一,思考,element-UI <el-table>中如何獲取當前行數據?

<el-table-column prop label="操作">
                <template slot-scope="scope">
                  <span class="edit"></span>
                  <span class="delete" @click.prevent="deleteRow(scope.row.alarmModelId,0)"></span>
                </template>
 </el-table-column>

用到的就是插槽

二,什么是插槽?

插槽就是子組件中的提供給父組件使用的一個占位符,用<slot></slot> 表示,父組件可以在這個占位符中填充任何模板代碼,如 HTML、組件等,填充的內容會替換子組件的<slot></slot>標簽。

三,單個插槽(匿名插槽)

單個插槽可以放置在組件的任意位置,但是就像它的名字一樣,一個組件中只能有一個該類插槽。

1) 匿名的方式,就是指把在引用組件的時候,里面傳的內容,全部一起傳送到組件頁面中 <slot></slot> 所在的位置。

2) 只要組件中有 <slot></slot> ,並且不管有多少個,都會全部渲染為傳過來的內容。

3) <slot></slot>里面也可以設置內容,這個內容是保證引入組件的時候,有個默認值。當然,<slot></slot>里面不設置內容也可以,這樣只是沒有默認值,是不會報錯的。

4) 傳遞的內容,也可以是動態的,如同上面一樣。但是要注意的是,這個內容不能是 引用組件的時候組件上的內容,要注意作用域。可以查看官網 插槽編譯作用域。

5) 如果傳遞的內容,沒有slot 來接收,那么,傳遞的內容就會被拋棄掉,不會起作用。

例子:

父組件:

<template>
  <div class="parent">
   <h3>我是父組件</h3>
    <child>  <!--子組件 -->
       <ul>  <!--因為在child子組件中定義了一個<slot></slot> ul中的內容就會顯示到插槽中 -->
        <li>選項一</li>
        <li>選項二</li>
        <li>選項三</li>
        </ul>
    </child> 
  </div>
</template>

<script>
import child from './child.vue'
export default {
  name: 'parent',
  data() { 
    return {

    }
  },
  components:{
      child
  }
 }
</script> 
<style scoped>
.parent{
    margin-left: 100px;
    width: 200px;
    background: lightblue;
    margin-top: 20px;
}
</style>

  

子組件:

<template>
  <div class="child">
    <h3>這里是子組件</h3>
    <slot></slot>  <!--插槽-->
  </div>
</template>

<script>
export default {
  name: 'child',
  data() { 
    return {

    }
  }
 }
</script>

<style scoped>

</style>

  

渲染結果:

 

 

四,具名插槽

就是帶有名字的插槽,有一個name屬性,具名的插槽可以在組件中出現多次,而之前的匿名插槽只能出現一次,畢竟存在多個插槽,頁面也不知道自己的正確顯示位置應該在哪里。

1) 引入組件的頁面,如果是多個內容,需要用template 包裹起來,並且添加 slot 屬性和 自定義值 。

2) slot 的值 需要和 組件中 <slot name='xxx'></slot> name的值相對應。

3) 如果剩下的內容沒有包裹起來並制定值的話,那么這些內容會被渲染到 組件中 所有的 <slot></slot> 所在的位置。

4) 如果 slot 設置為default 和 name 設置為default,那就和沒設置slot與name是一樣的。

例子:

父組件:

<template>
  <div class="parent">
   <h3>我是父組件</h3>
    <child>  <!--子組件 -->
       <ul slot="first">  <!--名為first的插槽 -->
        <li>選項一</li>
        <li>選項二</li>
        <li>選項三</li>
        </ul>
         <ul slot="second">  <!--名為second的插槽-->
        <li>選項四</li>
        <li>選項五</li>
        <li>選項六</li>
        </ul>
    </child> 
  </div>
</template>

<script>
import child from './child.vue'
export default {
  name: 'parent',
  data() { 
    return {

    }
  },
  components:{
      child
  }
 }
</script> 
<style scoped>
.parent{
    margin-left: 100px;
    width: 200px;
    background: lightblue;
    margin-top: 20px;
}
</style>

  

子組件:

<template>
  <div class="child">
    <h3>名為first的具名插槽</h3>
    <slot name="first"></slot>  <!--名為first的具名插槽-->
    <h3>名為second的具名插槽</h3>
    <slot name="second"></slot>  <!--名為second的具名插槽-->
  </div>
</template>

<script>
export default {
  name: 'child',
  data() { 
    return {

    }
  }
 }
</script>

<style scoped>

</style>

  

渲染結果:

 

 

 

五,作用域插槽

1) 作用域插槽主要是 使用子組件的任何數據 來達到自定義顯示內容的目的

2) 作用域插槽最最最最最重要的一步,即是在<slot></slot> 上綁定數據 ,如果沒有綁定數據,則父組件收到的,只是一個空對象{ }。

3) 作用域插槽中 <slot></slot> 上綁定數據,可以是寫死的,也可以是動態綁定的。如果是動態綁定的,則也需要 v-bind:xxx

4) 作用域插槽中 <slot></slot> 上綁定的數據 也可以傳一個定義好的有返回值的 mthods 方法。比如我定義了 <slot what='say()'></slot> ,然后say方法為: say:function(){ return '我說了' } 。最后得到的結果就是 “我說了”,當然,動態綁定一定要加 v-bind:xxx。

5) 當 綁定上數據之后,引用組件的地方 中 發送的內容就能通過 slot-scope 來獲取。獲取到的內容,就是一個對象,比如 <slot name='sayWhat' said='message'></slot> 我這里綁定 said='message' 之后, 那邊接收到的就是 { said:"xxxx"} 一個對象。

6) slot-scope 可以接收任何有效的可以出現在函數定義的參數位置上的 JavaScript 表達式

例子:

父組件:

<template>
  <div class="parent">
   <h3>我是父組件</h3>
    <child>  <!--子組件 -->
      <!-- 2.5以下必須使用template -->
      <template slot-scope="scoped">
        <ul>
            <li v-for="(item, index) in scoped.data" :key="index">{{item}}</li>
        </ul>
      </template>
    </child> 
  </div>
</template>

<script>
import child from './child.vue'
export default {
  name: 'parent',
  data() { 
    return {

    }
  },
  components:{
      child
  }
 }
</script> 
<style scoped>
.parent{
    margin-left: 100px;
    width: 200px;
    background: lightblue;
    margin-top: 20px;
}
</style>

  

子組件:

<template>
  <div class="child">
   <slot :data="pLanguage">
   </slot>
  </div>
</template>

<script>
export default {
  name: 'child',
  data() { 
    return {
      pLanguage:['JavaScript','Java','C++','C']
    }
  }
 }
</script>

<style scoped>

</style>

  

渲染結果:

 

 

 六,2.6版本之后新用法

vue 在 2.6.0 中,具名插槽和作用域插槽引入了一個新的統一的語法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 這兩個目前已被廢棄但未被移除且仍有用的特性。但是將會在vue 3 中,被廢棄的這兩個,不會被支持即無效。

1,具名插槽的變化

<testSlot>
    <!--2.6.0以前的寫法-->
    <template  slot='header'>
        <p>------------header----------------</p>
        <h3>這是header1的內容</h3>
        <p>這是header2的內容</p>
    </template>


    <!--2.6.0之后的寫法-->
    <template v-slot:header>
        <p>------------header----------------</p>
        <h3>這是header1的內容</h3>
        <p>這是header2的內容</p>
    </template>
</testSlot>

  

1) slot=' xxx ' 改成了 v-slot : xxx 並且冒號后面這個名稱不能打引號

2) 組件頁面中slot的內容沒有變化

3) 2.6.0 之后 具名插槽 v-slot:header 可以縮寫為 #header

 

2,作用域插槽的變化

<slotScope :message='msg'>
    <!--2.6.0之前的寫法-->
    <div slot='sayWhat' slot-scope='thing'>說了:{{thing.said}}</div>
    
    <template slot='listbox' slot-scope='value'>
        <p>{{value.send.text}}</p>
    </template>

    <!--2.6.0之后的寫法,不能單獨用在html標簽上-->
    <template v-slot:sayWhat='thing'>
      <div>說了:{{thing.said}}</div>
    </template>
    <template v-slot:listbox='value'>
        <p>{{value.send.text}}</p>
    </template>
</slotScope>

  

1) 兩個屬性合並成了一個 v-slot : 插槽名稱 = ' 傳過來的值 ' 。

2) 組件頁面中slot的內容沒有變化 。

3) v-slot 不能用在 html 標簽上 。

4) 如果是默認插槽 可以寫成 v-slot='xxx'

5) 還增加了 可以解構插槽props 和 設置默認值的內容,具體的可以查看官網 解構插槽


免責聲明!

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



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