Vue插槽詳解 | 什么是插槽?


file

作者 | Jeskson

來源 | 達達前端小酒館

什么是插槽?插槽的指令為v-slot,它目前取代了slot和slot-scope,插槽內容,vue實例一套內容分發的api,將slot元素作為承載分發內容的出口。

組件的書寫:

<my-link url="/profile">
dada
</my-link>

運用組件模板,可以在里面書寫:

<a v-bind:href="url" class="css-link">
<slot></slot>
</a>

<slot></slot>會替換dada

插槽內可以寫任何模板代碼:

<my-link url="/profile">
<span class=“weixin"> </span>
dada
</my-link>
<my-link url="/profile">
<my-icon name="user"></my-icon>
dada
<my-link>
// 添加圖標組件

如果my-link沒有包含一個slot元素,之間的任何內容都會消失。

什么是插槽,它是vue提出的一個概念,插槽用於決定將所攜帶的內容,插入到指定的某個位置,使得模塊分塊,具有模塊化特質。

插槽怎么用?

// 父組件
<template>
<div>
我是父組件
<slotda>
<p style="color:red">我是父組件得插槽內容</p>
</slotda>
<div>
</template>

在父組件中引用子組件中寫入想要得顯示內容

子組件slotda

<template>
<div class="slotda">
 <div>我是slotda組件</div>
 <slot></slot>
 </idv>
</template>

在子組件中寫入slot,所在位置就是父組件要顯示得內容

// 父組件
<template>
<div>
我是父組件
<slotda>
<p style="color:red">我是父組件插槽內容</p>
<slotdd></slotdd>
</div>
</template>

子組件

<template>
<div class="slotdd">
我是slotdd組件
</div>
</template>

具名插槽

<template>
<div class="slotdadada">
 <div>slotdadada</div>
 <slot name="header"></slot>
 <slot></slot>
 <slot name="footer"></slot>
</div>
</template>

子組件

父組件

<template>
<div>
我是父組件
<slotdadada>
 <p>dada</p>
 <template slot="header">
 <p>da</p>
 </template>
 <p slot="footer">我是footer</p>
</slotdadada>
</div>
</template>

插槽默認內容

// 父組件
<template>
<div>
我是父組件
<slotdd></slotdd>
</div>
</template>

子組件

<template>
<div class="slotdd">
 <slot>ddd</slot>
 </div>
</template>

作用域

<template>
<div>
我是父組件
<slot-d>
<p>{{name}}</p>
</slot-d>
</div>
</template>

<script>
export default {
 data() {
  return {
   name: 'dada'
  }
}}
</script>

子組件

<template>
<div class="slot-d">
<slot></slot>
</div>
</template>

插槽可以是任意內容:

插槽就是Vue實現的一套內容分發的API,將 元素作為承載分發內容的出口。

沒有插槽的情況下,在組件標簽內些一些內容是不起任何作用的,當我在組件中聲明了slot元素后,在組件元素內寫的內容就會跑到它這里了!

<div id="app">
<child-component></child-component>
</div>

</script>
Vue.component('child-component', {
 template: `
 <div>Hello,World!</div>
 `
 })
 let vm = new Vue({
 el: '#app',
 data:{
 }
})
</script>

file

<child-component>你好</child-component>

組件之間得內容沒有顯示,使用插槽就有顯示了,看看如何用:

Vue.component('child-component',{
        template:`
            <div>
            Hello,World!
            <slot></slot>
            </div>
        `
    })

file

具名插槽,就是給這個插槽起個名字,slot屬性對應的內容都會和組件中name一一對應。

child-component,沒有名字得就是默認得。

<div id="app">
    <child-component>
        <template slot="girl">
            購物、逛街
        </template>
        <template slot="boy">
            帥氣
        </template>
        <div>
            我是人
            我是默認的插槽
        </div>
    </child-component>
</div>
<script>
    Vue.component('child-component',{
        template:`
            <div>
            <h4>這個世界有男人和女人</h4>

            <slot name="girl"></slot>

            <div style="height:1px;background-color:red;"></div>

            <slot name="boy"></slot>

            <div style="height:1px;background-color:red;"></div>

            <slot></slot>
            </div>
        `
    })
    let vm = new Vue({
        el:'#app',
        data:{
        }
    })
</script>

作用域插槽,在組件上的屬性,可以在組件元素內使用!

在template元素上添加屬性slot-scope

<div id="app">
    <child>
        <template slot-scope="a">
      <!-- {"say":"你好"} -->
            {{a}}
        </template>
    </child>
</div>
Vue.component('child',{
        template:`
            <div>
                <slot say="你好"></slot>
            </div>
        `
    })
<div id="app">
    <child :lists="nameList">
        <template slot-scope="a">
            {{a}}
        </template>
    </child>
</div>
Vue.component('child',{
        props:['lists'],
        template:`
            <div>
                <ul>
                    <li v-for="list in lists">
                        <slot :bbbbb="list"></slot>
                    </li>
                </ul>
            </div>
        `
    })

在一個組件中使用 標簽,就是定義一個插槽。

如果組件中沒包含 任何被傳入的東西都會被拋棄。

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
<base-layout>
  <template slot="header">
    <h1>d</h1>
  </template>

  <p>dd.</p>
  <p>dd.</p>

  <template slot="footer">
    <p> ddd </p>
  </template>
</base-layout>
<base-layout>
  <h1 slot="header">H</h1>

  <p>A.</p>
  <p>A.</p>

  <p slot="footer">H</p>
</base-layout>

在沒有指定slot屬性的時候 都會放在slot沒有name屬性的插槽當中。

編譯作用域

插槽中的內容不能訪問父級作用域

<navigation-link url="/profile">
  Logged in as {{ user.name }}
</navigation-link>
// 部分不能訪問 url

父組件模板的所有東西都會在父級作用域內編譯;子組件模板的所有東西都會在子級作用域內編譯。

<ul>
  <li
    v-for="todo in todos"
    v-bind:key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>

合成組件:

<div id="app1">
  <navigation-link url="/profile">
    Your Profile
  </navigation-link>
</div>

然后你在 <navigation-link> 的模板中可能會寫為:

Vue.component('navigation-link', {
    template: `
      <a
        v-bind:href="url" rel="external nofollow"
        class="nav-link"
      >
      <slot></slot>
      </a>
    `
  });

當組件渲染的時候,這個 元素將會被替換為“Your Profile”。

file

插槽內可以包含任何模板代碼

<navigation-link url="/profile">
 <!-- 添加一個 Font Awesome 圖標 -->
 <span class="fa fa-user"></span>
 Your Profile
</navigation-link>

也可以是組件:

<navigation-link url="/profile">
 <!-- 添加一個圖標的組件 -->
 <font-awesome-icon name="user"></font-awesome-icon>
 Your Profile
</navigation-link>

但是如果在navigation-link中沒有包含一個slot元素,都會讓之間得內容都消失得。

具名插槽

需要多個插槽

<div class="container">
 <header>
  <!-- 我們希望把頁頭放這里 -->
 </header>
 <main>
  <!-- 我們希望把主要內容放這里 -->
 </main>
 <footer>
  <!-- 我們希望把頁腳放這里 -->
 </footer>
</div>

<div class="container">
 <header>
  <slot name="header"></slot>
 </header>
 <main>
  <slot></slot>
 </main>
 <footer>
  <slot name="footer"></slot>
 </footer>
</div>

<base-layout>
 <template slot="header">
  <h1></h1>
 </template>
 <p></p>
 <p></p>
 <template slot="footer">
  <p></p>
 </template>
</base-layout>

作用域插槽


Vue.component('todo-list',{
    template:`
    <ul>
      <li
        v-for="todo in todos"
        v-bind:key="todo.id">
        {{ todo.text }}
      </li>
    </ul>
    `
  });
  
  <ul>
 <li
  v-for="todo in todos"
  v-bind:key="todo.id"
 >
  <!-- 我們為每個 todo 准備了一個插槽,-->
  <!-- 將 `todo` 對象作為一個插槽的 prop 傳入。-->
  <slot v-bind:todo="todo">
   <!-- 回退的內容 -->
   {{ todo.text }}
  </slot>
 </li>
</ul>

看代碼后,插槽內容基本了解。對於編譯作用域:

<navigation-link url="/profile">
  Logged in as {{ user.name }}
</navigation-link>

該插槽和模板得其他地方一樣都可以訪問相同的實例屬性,就是相同的”作用域“,但不能訪問navigation-link標簽的作用域。

<navigation-link url="/profile">
  Clicking here will send you to: {{ url }}
  <!--
  這里的 `url` 會是 undefined,因為 "/profile" 是
  _傳遞給_ <navigation-link> 的而不是
  在 <navigation-link> 組件*內部*定義的。
  -->
</navigation-link>

我了解了呢。
后備內容

<button type="submit">
  <slot></slot>
</button>
<button type="submit">
  <slot>Submit</slot>
</button>
<submit-button></submit-button>

<button type="submit">
  Submit
</button>

作用域插槽

<span>
  <slot>{{ user.lastName }}</slot>
</span>

<current-user>
  {{ user.firstName }}
</current-user>

然而上述代碼不會正常工作,因為只有 <current-user> 
組件可以訪問到 user 而我們提供的內容是在父級渲染的。

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

綁定在 元素上的特性被稱為插槽 prop

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>
<current-user v-slot:default="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

默認插槽的縮寫語法不能和具名插槽混用

<!-- 無效,會導致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

多個插槽的寫法:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>

  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>

解構插槽 Prop

function (slotProps) {
  // 插槽內容
}

<current-user v-slot="{ user }">
  {{ user.firstName }}
</current-user>

<current-user v-slot="{ user: person }">
  {{ person.firstName }}
</current-user>

動態插槽名

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>

❤️ 不要忘記留下你學習的腳印 [點贊 + 收藏 + 評論]

作者Info:

【作者】:Jeskson
【原創公眾號】:達達前端小酒館。
【福利】:公眾號回復 “資料” 送自學資料大禮包(進群分享,想要啥就說哈,看我有沒有)!
【轉載說明】:轉載請說明出處,謝謝合作!~

大前端開發,定位前端開發技術棧博客,PHP后台知識點,web全棧技術領域,數據結構與算法、網絡原理等通俗易懂的呈現給小伙伴。謝謝支持,承蒙厚愛!!!


若本號內容有做得不到位的地方(比如:涉及版權或其他問題),請及時聯系我們進行整改即可,會在第一時間進行處理。


請點贊!因為你們的贊同/鼓勵是我寫作的最大動力!

歡迎關注達達的CSDN!

這是一個有質量,有態度的博客

前端技術棧


免責聲明!

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



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