彻底搞懂 Vue slot 插槽用法 (V2.6.0前后两个版本及其对比)

插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

值得注意的是:在 Vue 2.6.0 中,为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。

1.默认插槽/匿名插槽

子组件:

// Child.vue
<template>
  <div>
     <div class="test">
       <slot></slot>
     </div>
  </div>
</template>

父组件:

//Parent.vue
<template>
  <div id="app">
   <Child>
   Your Profile
  </Child>
  </div>
</template>

当组件渲染的时候,<slot></slot> 将会被替换为“Your Profile”。插槽内可以包含任何模板代码,包括 HTML甚至其它的组件。

如果 <Child/> 的 template 中没有包含一个 <slot> 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。

2. 具名插槽

具名插槽,顾名思义,也就是给插槽起名字。 匿名插槽只能有一个,而具名插槽可以有n多个,当需要多个插槽时,可以使用<slot>的特性:name。这个特性可以用来定义额外的插槽

子组件:

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

第一种:在 <template> 上使用特殊的 slot 属性,可以将内容从父级传给具名插槽

父组件:

//Parent.vue
<template>
  <div id="app">
   <Child>
    <template slot="header">
      <h1>Here might be a page title</h1>
    </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

   <template slot="footer">
    <p>Here's some contact info</p>
   </template>
   </Child>
  </div>
</template>

第二种: 直接把 slot 属性用在一个普通元素上:

父组件:

//Parent.vue
<template>
  <div id="app">
   <Child>
      <h1 slot="header">Here might be a page title</h1>

      <p>A paragraph for the main content.</p>
      <p>And another one.</p>

      <p slot="footer">Here's some contact info</p>
   </Child>
  </div>
</template>

与第一种结果一致 。 

注意到这里其实还有一个未命名插槽,也就是默认插槽,捕获所有未被匹配的内容。

V2.6.0之后的更新: 

子组件不变,父组件改用v-slot属性。在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

父组件:

<template>
  <div id="app">
   <Child>
      <template v-slot:header>
       <h1>Here might be a page title</h1>
      </template>

     <p>A paragraph for the main content.</p>
     <p>And another one.</p>

     <template v-slot:footer>
     <p>Here's some contact info</p>
     </template>
   </Child>
  </div>
</template>

就是这么简单,插槽的名字现在通过 v-slot:slotName 这种形式来使用。

现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header

值得注意的是: v-slot 只能添加在 <template> 上 ,这一点和已经废弃的 slot 属性不同,default情况在此不做赘述。

3. 作用域插槽

子组件中数据默认在父组件中是不能访问的,为了让子组件的数据在父级的插槽内容中可用,我们可以将数据作为 <slot> 元素的一个 属性绑定上去:

子组件:

<template>
<div>
<slot :data="data"></slot>
</div>
</template>
<script>
 export default {
    data: function(){
      return {
        data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
    },
}
</script>

在 <template> 上使用的 slot-scope 属性,可以接收传递给插槽的 prop 

父组件: 

//Parent.vue
<template>
  <div id="app">
   <Child>
       <template slot-scope="slotProps">
         {
   
   {slotProps}}
          <br/>
         {
   
   {slotProps.data}}
      </template>
   </Child>
  </div>
</template>

这里的 slot-scope 声明了被接收的 prop 对象会作为 slotProps 变量存在于 <template> 作用域中。你可以像命名 JavaScript 函数参数一样随意命名 slotProps

结果如下:

可以看出slotProps中存储的是所以子组件传递过来的数据组成的对象。

同样地,slot-scope属性也可以直接用于非 <template> 元素 (包括组件):

父组件:

//Parent.vue
<template>
  <div id="app">
   <Child>
       <div slot-scope="slotProps">
         <ul>
          <li v-for="item in slotProps.data">{
   
   {item}}</li>
         </ul>
        </div>
   </Child>
  </div>
</template>

结果如下:

V2.6.0之后的更新: 

子组件不变,父组件改用v-slot属性。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字 

父组件:

//Parent.vue
<template>
  <div id="app">
   <Child>
      <template v-slot="slotProps">
     {
   
   { slotProps.data }}
     </template>
    
   </Child>
  </div>
</template>

 结果不变。

小结: 

1. 简单理解 ,默认插槽和具名插槽是父组件既提供样式又提供模板,作用域插槽是数据是子组件自带的 父组件只提供样式

2. V2.6.0之后任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容,即v-slot不能再用于普通元素

猜你喜欢

转载自blog.csdn.net/a1059526327/article/details/107912580