美文网首页
Vue 插槽slot和作用域插槽slot-scope

Vue 插槽slot和作用域插槽slot-scope

作者: 全球顶尖伪极客 | 来源:发表于2019-12-18 16:52 被阅读0次

    什么插槽

    官网说明:

    2.6.0中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slotslot-scope 这两个目前已被废弃但未被移除且仍在文档中的特性。新语法的由来可查阅这份 RFC

    • 简单的概念:插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示、以及怎样显示由父组件来决定。slot最核心的是显示不显示怎样显示

    • 非插槽模板html模板:
      指的是 div、span、ul、table这些,非插槽模板的显示与隐藏以及怎样显示由插件自身控制;

    • 插槽模板slot
      它是一个空壳子,因为它显示与隐藏以及最后用什么样的html模板显示由父组件控制。但是插槽显示的位置确由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板将来就显示在哪块。

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

    • 概念:
      单个插槽是vue的官方叫法,是默认插槽,也是匿名插槽。因为它不用设置name属性。
      单个插槽, 一个组件中只能有一个该类插槽。具名插槽就可以有很多个,只要名字(name属性)不同就可以了。

    • 样例:
      如果父模板传递了值过去,则插槽占位处显示父组件传递过去的值,否则默认为子组件插槽的内容,一般情况为空。

    父模板
    
    <div class="parent">
         <h3>这里是父组件</h3>
        <alert-box>有bug发生</alert-box>
        <alert-box>有一个警告</alert-box>
        <alert-box></alert-box>
    </div>
    
    子组件
      Vue.component('alert-box', {
          template: `
            <div> <strong>ERROR:</strong>
            <slot>子组件插槽默认内容</slot>
        </div>
        `
        });
    展示结果:
    ERROR: 有bug发生
    ERROR: 有一个警告
    ERROR: 子组件插槽默认内容
    
    
    <template>
        <div class="parent">
            <h3>这里是父组件</h3>
            <child>
                <h4>这里是子组件中插槽占位处要展示的内容</h4>
                <div class="tmpl">
                  <span>菜单1</span>
                  <span>菜单2</span> 
                </div>
            </child>
        </div>
    </template>
    
    
    子组件
    <template>
        <div class="child">
            <h3>这里是子组件</h3>
            <slot></slot>
        </div>
    </template>
    

    具名插槽

    • 概念:
      插槽加了name属性,具名插槽可以在一个组件中出现N次。出现在不同的位置。总之,存在多个具名插槽的情况下,只需要找准该slot="name"下的slot即可,将对应的父组件内容传递到子组件slot占位处。父组件通过html模板上的slot属性关联具名插槽。没有slot属性的html模板默认关联匿名插槽。
    • 样例:
    父组件
    <base-layout>
          <p slot='header'>标题信息</p>
          <p>主要内容1</p>
          <p>主要内容2</p>
          <p slot='footer'>底部信息</p>
    </base-layout>
    
    子组件:
      Vue.component('base-layout', {
          template: `
          <div>
              有name的插槽可以在该组件中存在多次
              <header><slot name='header'></slot></header>
              <main> <slot></slot></main>
              <footer><slot name='footer'></slot></footer>
          </div>
          `
        });
    
    展示结果:
    标题信息
    主要内容1
    主要内容2
    底部信息
    

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

    作用域插槽:在slot上面绑定数据。自 2.6.0 起有所更新。已废弃的使用 slot-scope特性的语法。官网介绍新版
    slot-scope 声明了被接收的prop对象会作为 slotProps变量存在于 <template>作用域中。你可以像命名JavaScript函数参数一样随意命名 slotProps

     <fruit-list :list='list'>
          <template slot-scope='slotProps'>
            <strong v-if='slotProps.info.id==3' class="current">
              {{slotProps.info.name}}
            </strong>
          </template>
    </fruit-list>
     Vue.component('fruit-list', {
          props: ['list'],
          template: `
         <div>
          <li :key='item.id' v-for='item in list'>
              <slot :info='item'>{{item.name}}</slot>
          </li>
         </div>
          `
    });
    var vm = new Vue({
          el: '#app',
          data: {
            list: [{
                id: '1',
                name: 'apple'
              }, {
                id: '2',
                name: 'orange'
              }, {
                id: '3',
                name: 'banana'
              }
    
            ]
          }
        });
    结果:
    apple
    orange
    banana
    
    image.png

    2.6.0+官网写法

    将包含所有插槽prop的对象命名为 slotProps名字任意取。

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

    注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:

    <!-- 无效,会导致警告 -->
    <current-user v-slot="slotProps">
      {{ slotProps.user.firstName }}
      <template v-slot:other="otherSlotProps">
        slotProps is NOT available here
      </template>
    </current-user>
    
    • 只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template> 的语法:
    <current-user>
      <template v-slot:default="slotProps">
        {{ slotProps.user.firstName }}
      </template>
    
      <template v-slot:other="otherSlotProps">
        ...
      </template>
    </current-user
    

    解构插槽Prop

    • 作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里,这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。
    function (slotProps) {
      // 插槽内容
    }
    <current-user v-slot="{ user }">
      {{ user.firstName }}
    </current-user>
    重命名
    <current-user v-slot="{ user: person }">
      {{ person.firstName }}
    </current-user>
    
    具名插槽

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

    <base-layout>
      <template #header>
        <h1>Here might be a page title</h1>
      </template>
    
      <p>A paragraph for the main content.</p>
      <p>And another one.</p>
    
      <template #footer>
        <p>Here's some contact info</p>
      </template>
    </base-layout>
    
    • 然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:
    <!-- 这样会触发一个警告 -->
    <current-user #="{ user }">
      {{ user.firstName }}
    </current-user>
    
    • 如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:
    <current-user #default="{ user }">
      {{ user.firstName }}
    </current-user>
    

    参考链接

    相关文章

      网友评论

          本文标题:Vue 插槽slot和作用域插槽slot-scope

          本文链接:https://www.haomeiwen.com/subject/eflunctx.html