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

什么插槽

官网说明:

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>

参考链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 【2019-3-4更新】Vue 2.6+修改了部分语法,对插槽的使用有了较多的更新。在本文中笔者在相应位置给出了更...
    果汁凉茶丶阅读 10,225评论 2 36
  • 什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装...
    youins阅读 9,449评论 0 13
  • 最近忙着写一些组件,关于插槽这一块自己还是用着 slot 和 slot-scope,然后看了一下文档的更新,于是又...
    费莱姆阅读 926评论 0 7
  • 深入理解vue中的slot与slot-scope 写在前面 vue中关于插槽的文档说明很短,语言又写的很凝练,再加...
    SentMes阅读 42,487评论 14 55
  • 消息推送对产品的作用归结到底可能就是增加与用户的关联,进而刺激引导用户对产品的使用。简单的说一说个人对于如何平衡消...
    皮皮酱ye阅读 287评论 0 0