Vue3 中插槽(slot)的用法

摘要:
Profile Vue3引入了一条新的指令v-slot,以表示命名槽和默认槽的基本示例˂˂divclass=“footer”Javascript表达式,这些表达式定义了中的参数。因此,在支持的环境中,您还可以使用ES2015解构来导入特定的插槽道具,如下所示:Messagefromheaderslot:{{msg}}v-slot可以直接用于组件。如果没有参数,则表示默认作用域槽。传递给默认槽的属性应在其属性值中声明为变量--New--˃{msg}}包含DOM节点的默认槽˂!

概要

Vue3(其实从2.6开始)中引入了一个新的指令v-slot,用来表示具名插槽和默认插槽

基础示例

<!-- default slot -->
<foo v-slot="{ msg }">
    {{ msg }}
</foo>

<!-- named slot -->
<foo>
    <template v-slot:one="{msg}">
        {{ msg }}
    </template> 
</foo>

为什么要这么做

在v2.5中介绍了slot-scope,可以直接在插槽元素上使用。

<foo>
    <div slot-scope="{ msg }">
        {{ msg }}
    </div>
</foo>

同样的,我们也可以在组件上这样使用。

<foo>
    <bar slot-scope="{ msg }">
        {{ msg }}
    </bar>
</foo>

然而,上面的示例会导致一个问题:slot-scope的位置不能清晰的反映出这个作用域变量是哪一个 组件提供的。上面例子中slot-scope是写在<bar>组件上,但是实际上这个作用域变量的定义是有<foo>组件的默认插槽提供的。
当嵌套的层级越深,情况就会变得越糟。

<foo>
  <bar slot-scope="foo">
    <baz slot-scope="bar">
      <div slot-scope="baz">
        {{ foo }} {{ bar }} {{ baz }}
      </div>
    </baz>
  </bar>
</foo>

像上面这种情况,我们无法立即分辨出模板上作用域变量是由那一个组件提供的。

细节设计

引入一个新的指令v-slot

我们可以在slot容器<template>上使用v-slot来表示一个传入组件的插槽,通过指令参数来表示插槽的名称。

<foo>
    <template v-slot:header>
        <div class="header"></div>
    </template>
    <template v-slot:body>
        <div class="body"></div>
    </template>
    <template v-slot:footer>
        <div class="footer"></div>
    </template>
</foo>

作用域插槽的内部工作原理是将插槽的内容包裹在一个函数里

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

这就意味着v-slot的值实际上可以是任何能够作为函数定义中的参数的Javascript表达式,所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop,如下:

<foo>
    <template v-slot:header="{ msg }">
        <div class="header">
            Message from header slot: {{ msg }}
        </div>
    </template>
</foo>

v-slot可以直接用在组件上,如果没有参数,则表示默认的作用域插槽,传递给默认插槽的属性应该作为变量在其属性值声明。

<foo v-slot="{ msg }">
    {{ msg }}
</foo>

新旧语法对比

  • 对于常用的场景(只有一个默认的作用域插槽)

    <foo v-slot="{msg}">{{msg}}</foo>
    
  • 作用域变量与组件之间的联系更加的清晰

    <!-- old -->
    <foo>
      <bar slot-scope="foo">
        <baz slot-scope="bar">
          <div slot-scope="baz">
            {{ foo }} {{ bar }} {{ baz }}
          </div>
        </baz>
      </bar>
    </foo>
    

    使用新语法也可以达到同样的效果

    <foo v-slot="foo">
      <bar v-slot="bar">
        <baz v-slot="baz">
          {{ foo }} {{ bar }} {{ baz }}
        </baz>
      </bar>
    </foo>
    

注意:组件提供的作用域变量依然声明在当前组件上,新的语法更清晰的展示出组件与作用域变量的关系。(父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。)

动态插槽名

动态指令参数也可以用在 v-slot 上,来定义动态的插槽名:

<foo>
    <template v-slot:[slotName]>
        ...
    </template>
</foo>

插槽指令的缩写

v-bindv-on相似,缩写只有在存在参数时才生效,这就意味着v-slot没有参数时不能使用#=,对于默认插槽,可以使用#default来代替v-slot

<!-- full syntax -->
<foo>
  <template v-slot:header="{ msg }">
    Message from header: {{ msg }}
  </template>

   <template v-slot:footer>
    A static footer
  </template>
</foo>

<!-- shorthand -->
<foo>
  <template #header="{ msg }">
    Message from header: {{ msg }}
  </template>

   <template #footer>
    A static footer
  </template>
</foo>
<foo v-slot="{ msg }">
  {{ msg }}
</foo>

<foo #default="{ msg }">
  {{ msg }}
</foo>

更多的用例对比

默认的文本作用域插槽

<!-- old -->
<foo>
    <template slot-scope="{ msg }">
        {{ msg }}
    </template>
</foo>

<!-- new -->
<foo v-slot="{ msg }">
    {{ msg }}
</foo>

默认的含DOM节点的插槽

<!-- old -->
<foo>
    <div slot-scope="{msg}">
        {{msg}}
    </div>
</foo>

<!-- new -->
<foo v-slot="{msg}">
    <div>
        {{msg}}
    </div>
</foo>

嵌套的默认插槽

<!-- old -->
<foo>
    <bar slot-scope="foo">
        <baz slot-scope="bar"> 
            <template slot-scope="baz">
                {{ foo }} {{ bar }} {{ baz }}
            </template>
        </baz>
    </bar>
</foo>

<!-- new -->

<foo v-slot="foo">
    <bar v-slot="bar">
        <baz v-slot="baz">
            {{ foo }} {{ bar }} {{ baz }}
        </baz>
    </bar>
</foo>

命名插槽

<!-- old -->
<foo>
    <template slot="one" slot-scope="{ msg }">
        text slot: {{ msg }}
    </template>
    <div slot="two" slot-scope="{ msg }">
        element slot: {{ msg }}
    </div>
</foo>

<!-- new -->
<foo>
    <template v-slot:one="{ msg }">
        text slot:{{msg}}
    </template>
    <template v-slot:two="{msg}">
        <div>
            element slot: {{msg}}
        </div>
    </template>
</foo>

嵌套 & 命名 / 默认

<!-- old -->
<foo>
  <bar slot="one" slot-scope="one">
    <div slot-scope="bar">
      {{ one }} {{ bar }}
    </div>
  </bar>

  <bar slot="two" slot-scope="two">
    <div slot-scope="bar">
      {{ two }} {{ bar }}
    </div>
  </bar>
</foo>

<!-- new -->
<foo>
  <template v-slot:one="one">
    <bar v-slot="bar">
      <div>{{ one }} {{ bar }}</div>
    </bar>
  </template>

  <template v-slot:two="two">
    <bar v-slot="bar">
      <div>{{ two }} {{ bar }}</div>
    </bar>
  </template>
</foo>

免责声明:文章转载自《Vue3 中插槽(slot)的用法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MSSQL锁定3.死锁与阻塞(myBased)Vue 返回上一页,记住上一页的数据下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Spring学习(四)Spring IOC

Spring 学习目录 Spring学习(一)Spring初识 Spring学习(二)Spring框架结构 Spring学习(三)第一个Spring程序 Spring学习(四)Spring IOC Spring学习(五)Spring 基于注解装配Bean Spring学习(六)Spring AOP Spring学习(七)Spring JdbcTempl...

深入 CommonJs 与 ES6 Module

目前主流的模块规范 UMD CommonJs es6 module umd 模块(通用模块) (function (global, factory) { typeof exports === 'object' &amp;&amp; typeof module !== 'undefined' ? module.exports =...

Blocks学习笔记总结

  本文是对Apple的《Blocks Progromming Gude》学习的笔记总结。   对象时C级别的语法和运行时特性。和标准C函数很类似,但除了可执行代码外,还可能包含了变量自动绑定(栈)或内存托管(堆)。所以一个block维护一个状态集(数据),可以在执行的时候用来影响程序行为。Block用来作为回调特别有用。   你可以在MAC OS 10....

JSP(二)

JSP九个内置对象(四大作用域对象): 1.内置对象称为隐式对象由tomcat容器创建 : appliction:全局上下文对象 session:会话对象 request:请求对象 pageContext:当前页面对象 response:响应对象 config:配置文件对象 out:输出对象 execption:异常对象 pageContext.getEx...

arale-cookie 使用

https://www.npmjs.com/package/arale-cookiearale-cookie 使用 define(function() { var Cookie = require('cookie'); Cookie.set('foo', 3); Cookie.set('bar', 4, {...

彻底理解setTimeout()

  之前在网上看了很多关于setTimeout的文章,但我感觉都只是点到为止,并没有较深入的去剖析,也可能是我脑袋瓜笨,不容易被点解。后面看了《你不知道的javascript-上卷》一书,决定重新再来理一次。这次我觉得我应该整明白了。于是分享给大家,文中解释有错误的部分还希望大家留言指正。 首先我们还是来看那道大家再熟悉不过的前端面试题: for (va...