关于vue中的slot和slot-scope

1,073 阅读3分钟

slot简言之就是插槽的意思,一般规定了一个显示的模板(规定html+css),这个模板写在父组件里(父组件里没有模板则不显示),至于显示位置等则是由子组件决定

也就是说怎么显示是由父组件决定,在哪显示则由子组件决定

在父组件中,各插槽的内容模板要写在子组件标签内部。

默认插槽/匿名插槽/单个插槽

默认插槽只能有一个,即在父组件里不定义slot的那个模板,默认插槽渲染在子组件内部不定义name的slot标签上。

具名插槽

在子组件内部可以为name插槽命名,被命名的插槽叫具名插槽,不同的具名插槽显示不同的模板

在父组件内可以通过给模板的最外层标签上添加slot属性来确认模板对应的插槽

<!--子组件内-->
<div class="container">
  <header>
    <!--name为header的具名插槽,用来显示slot为header的模板-->
    <slot name="header"></slot>
  </header>
  <main>
    <!--匿名插槽,用来显示未定义slot属性的模板-->
    <slot></slot>
  </main>
  <footer>
    <!--name为footer的具名插槽,用来显示slot为footer的模板-->
    <slot name="footer"></slot>
  </footer>  
</div>

<!--父组件内-->
<base-layout>
  <!--slot为header的模板,显示在name为header的插槽上-->
  <template slot="header">
    <h1>Here might be a page title</h1>
  </template>
  <!--以下两个p会渲染到子组件内main标签下,但是不能在两个p之间加任何具名slot,会报错-->
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
    
  <!--slot为footer的模板,显示在name为footer的插槽上-->    
  <template slot="footer">
    <p>Here's some contact info</p>
  </template>
</base-layout>

<!--相当于-->
<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main> <!--父组件内未定义slot属性的内容-->
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

作用域插槽/带数据的插槽

vue 2.1.0+ 新增了一个叫作用域插槽的东西,它允许我们在插槽上面定义数据。

作用域插槽主要是为了解决那些插槽的数据在子组件内(可由父组件传入),但是样式需要父组件确定的问题。

在子组件中的slot标签上,通过v-bind指令来绑定对应的作用域props

在父组件内部使用时通过slot-scope来获取对应的props对象。

使用实例如下

<!--子组件-->
<template>
  <div class="child">

    <h3>这里是子组件</h3>
    // 作用域插槽
    <ul>
        <li v-for="(userInfo,index) in data" :key="index>
            <slot  :userInfo="userInfo" :index="index"></slot>
        </li>    
    </ul>
  </div>
</template>

 export default {
    data: function(){
      return {
        data: [{name:'zhangsan',sex:""},{name:'lisi',sex:""},{name:'ww',sex:""},{name:'zl',sex:""},{name:'lq',sex:""}]
      }
    }
}



<!--父组件-->
<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <child>
      <!--user代表slot上的props对象,当前这个user包含userInfo和index两个属性-->
      <template slot-scope="user">
        <span>{{user.userInfo.name}}</span> 
        <span>{{user.userInfo.sex}}</span>
      </template>

    </child>

    <!--第二次使用,和第一次使用样式不同-->
    <child>
      <template slot-scope="user">
        <span>{{user.userInfo.name}}</span> 
        <span>{{user.userInfo.sex}}</span>
        <span>{{user.index}}</span>    
      </template>

    </child>
  </div>
</template>

<!--作用域插槽是带数据的插槽,用于数据在子组件内部,样式在父组件内部的-->