vue插槽slot的理解與使用

1、我的理解及插槽的使用場景vue

剛開始看教程個人疑惑是爲何要用插槽,它的使用場景是什麼,不少解釋都是「父組件向子組件傳遞dom時會用到插槽」,這並不能很好的解決個人疑惑。既然你用了子組件,你爲何要給它傳一些dom,直接去定義複用的子組件不就行了。後來想一想以爲一個複用的組件在不一樣的地方只有些許變化,若是去重寫子組件是很不明智的一件事,固然也能夠將不一樣之處都寫在子組件裏,而後經過父組件傳來的標識進行選擇顯示。數組

能夠這樣認爲,插槽和屬性的做用一致,用來傳遞內容的,但咱們不能經過屬性傳遞帶標籤的內容,因此就須要插槽。其實質是對子組件的擴展,經過slot插槽向組件內部指定位置傳遞內容,即將<slot></slot>元素做爲承載分發內容的出口;app

最新的理解:最近學了關於Form表單組件的設計。好比iview中的表單,在 Form 內,每一個表單域由 FormItem 組成,可包含的控件有:Input、Radio、Checkbox、Switch、Select、Slider、DatePicker、TimePicker、Cascader、Transfer、InputNumber、Rate、Upload、AutoComplete、ColorPicker。iview

之因此能夠在表單域FormItem中選擇本身須要的部分,就是在設計的時候FormItem做爲Form的子組件,其中又加入了插槽,伊以便於用戶的選擇。dom

2、用於理解的例子ide

目前項目中還沒接觸到使用插槽解決實際問題很好的例子,只能這樣去爲了理解插槽而用,可能並無很好的利用到插槽的好處。this

如下代碼書寫均爲新語法。 spa

在父組件定義想要傳入子組件做爲插槽的內容,App.vue設計


<
template> <div id="app"> <div> <input type="text" v-model="info"> <button @click="handleClick">添加</button> </div> <todolist v-for="item in list" :key="item" :message="msg"> <template v-slot:item="itemProps" > <!-- tips1:<span>即爲插槽內容,想要傳給子組件的帶標籤的內容         tips2:item是插槽的名字,爲具名插槽,可將內容對應插入到子組件中具體的插槽位置  tips3:itemProps能夠獲取到子組件(即插槽 prop)傳出來的狀態(值),    插槽 prop 的對象命名爲 itemProps,可任意命名,itemProps變量存在於 <template> 做用域中  --> <span :style="{fontSize: '20px', color: itemProps.checked ? 'red': 'blue'}">{{item}}</span> </template> </todolist> </div> </template> <script> import todolist from './components/todolist.vue'; export default { name: 'App', components: { todolist }, data(){ return { msg: '4-2-05', info: '', list: [], } }, methods: { handleClick() { // 獲取到input輸入的東西,而後加入到數組中 this.list.push(this.info); this.info = '' } }, } </script> <style> </style>

在子組件利用<slot></slot>元素做爲承載分發內容的出口,父組件的插槽內容將在其中顯示,todolist.vuecode

<template>
  <div>
    {{message}}
  <li class="item">
    <input type="checkbox" v-model="checked">
    <slot name="item" v-bind="{checked}" ></slot>
    <!--插槽內容可以訪問子組件中才有的數據是頗有用的,又由於父級模板裏的全部內容都是在父級做用域中編譯的;子模板裏的全部內容都是在子做用域中編譯的
    因此得想辦法獲取到子組件的數據。-->
    <!--給子組件綁定一個動態參數,checked做爲一個 <slot> 元素的特性綁定上去,綁定在 <slot> 元素上的特性被稱爲插槽 prop-->
  </li>
  </div>
</template>

<script>
  export default {
    props: ['item','message'],
    // 由於父組件在插槽內容裏使用item, 即此句代碼<span>{{item}}</span>
    // 至關於須要傳遞給子組件的內容,也就是一般的父子組件通訊,因此在子組件須要經過props來獲取
    data() {
      return {
        checked: false,
      }
    },
    created() {
      console.log(this.message);
    }
  }
</script>

<style scoped>
  .item {
    color: red;
  }
  li{
    list-style: none;
  }
</style>

父組件傳遞過來的span標籤內容

3、具體知識點

一、具名插槽

上面的例子中子組件裏只使用了一個slot插槽,但有時咱們在一個子組件裏可能會多處使用插槽,咱們但願在不一樣的插槽處插入不一樣的內容,此時便須要進行區分,<slot> 元素有一個特殊的特性:name。這個特性能夠用來定義插槽的名字,在向具名插槽提供內容的時候,咱們能夠在父組件一個 <template> 元素上使用v-slot 指令,並以 v-slot 的參數的形式寫出插槽的名稱,並再子組件利用name,來使其一一對應。

//新語法
<!--父組件-->
 <template v-slot:header>
        <p>title slot1</p>
        <p>title slot2</p>
 </template>
 <template v-slot:content="props">
        <p>item slot-scope {{ props }}</p>
 </template>

<!--子組件-->
<slot name="header"></slot>
<slot name="content"></slot>
<slot ></slot>
//一個不帶 name 的 <slot> 出口會帶有隱含的名字「default」。

 

//舊語法
<!--父組件-->
  <p slot="heade">title slot1</p>
  <p slot="heade">title slot2</p>
  <p slot="content" slot-scope="props">item slot-scope {{ props }}</p>

<!--子組件-->
<slot name="header"></slot>
<slot name="content"></slot>
<slot ></slot>
//一個不帶 name 的 <slot> 出口會帶有隱含的名字「default」。

二、做用域插槽

爲了使父組件的插槽內容可使用子組件的數據,能夠在 <slot> 元素上綁定想要傳遞的數據,此特性被稱爲插槽 prop。同時在父級做用域中,給 v-slot 帶一個值來定義咱們提供的插槽 prop 的名字,即可獲取到。但此內容只在 <template>做用域內可用。

4、自 2.6.0 起有所更新的語法變化

一、帶有slot特性的具名插槽

二、帶有slot-scope特性的做用域插槽

5、突發奇想的調換

由於看到一個別人寫的關於slot的帖子,他應該是寫錯了插槽在子父組件的內容,這也就至關於從子組件傳一個插槽內容給父組件。仔細想一想這思路有問題,既然都引用了子組件,父組件即可以訪問到子組件的全部內容,如今卻非要經過插槽來傳遞,畫蛇添足。
而後我就試了一下將插槽內容卸載子組件裏,果真出現了報錯,以下:
  - <template v-slot> can only appear at the root level inside the receiving the component(slot的只能出如今接受組件的根級別)
也就是隻能在父組件使用。
相關文章
相關標籤/搜索