0

0

深入理解Vue中的插槽、内容分发、具名插槽

青灯夜游

青灯夜游

发布时间:2022-10-12 19:43:32

|

2367人浏览过

|

来源于掘金社区

转载

本篇文章给大家分享vue进阶技巧,深入理解下vue中的插槽、内容分发、具名插槽,希望对大家有所帮助。

深入理解Vue中的插槽、内容分发、具名插槽

插槽 Slots简介

Vue中组件的数据可以通过props进行传递,或者通过事件的方式进行获取传递,但当需要接收模板内容(任意合法的模板内容,代码片段、Vue组件)时,就需要使用插槽来实现了。当然也可以通过函数式编程间接实现;【相关推荐:vuejs视频教程】

1.png

  • 可以将插槽理解为js中的函数进行编译
// 父元素传入插槽内容
FancyButton('Click me!')

// FancyButton 在自己的模板中渲染插槽内容
function FancyButton(slotContent) {
    return ``
}
  • 最好的封装方式是将共性抽取到组件中,将不同点暴露为插槽 - 抽取共性,保留不同
  • 父组件模板的所有东西都会在父组件作用域中编译,子组件模板的所有东西都会在子组件作用域内编译 - 编译作用域

slot-scope浅析

常规的slot可以用于自定义组件的模板,但只是限制于固定的模板,无法自定义内部的具体的某一项,即常规的slot无法实现对组件循环体的每一项进行不同的内容分发,此时可以通过slot-scope进行实现,本质上和slot一样,不同点在于可以进行参数传递

//普通的组件定义
  • {{ book.name }}
//slot-scope组件定义
  • {{ book.name }}
//父组件使用

使用slot-scope时,当父组件使用该API,对应的插槽会替换模板中的slot进行展示

立即学习前端免费学习笔记(深入)”;

常用API浅析

具名插槽

在组件中定义多个插槽出口可以兼容多个不同需求的兼容性,使得多个插槽内容传入到各自的插槽出口中;当插槽中配置了name属性时,此插槽就被称为具名插槽(named slots),没有提供name的插槽会隐式命名为「default」

2.png

  • v-slot 可以简写为#,其值对应于插槽中的name对应的值;
  • 当在一个组件中同时存在默认插槽和具名插槽时,所有位于顶级的非template节点都被隐式的视为默认插槽的内容,因此可以省略默认插槽的template节点标签;

    
    
    
    
作用域插槽

普通的插槽,是无法获取其他作用域下的数据的,即父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域
但在某些情况下,插槽中的内容想要同时使用父组件和子组件内的数据,可以通过像组件传递数据props那样,让子组件在渲染时将一部分数据提供给插槽,这样在组件外部(父组件)中就可以使用子组件中的数据了-通过slot的方式

子组件传入插槽的 props 作为了 v-slot 指令的值,可以在插槽内的表达式中访问,其中name是Vue特意保留的attribute,不会作为props进行传递

  • 数据传递
//子组件
  • 数据接收
    • 默认插槽接收
    //父组件 - 使用方
    
      {{ shopInfo }} {{ userInfo }}
    
    • 具名插槽接收
    
      
    
      
    
      
    
  • 使用slot-scope时,用最后一个slot-scope替换模板中的slot

    
    
555
{{scope.name}}
{{scope}}
{{scope.name}}
{{scope.age}}
  • 使用作用域插槽时,可以实现既可以复用子组件slot,又可以使得slot的内容不一致,它允许使用者传递一个模板而不是已经渲染好的元素给插槽,所谓作用域是指模板虽然在父级作用域中渲染的,但是却可以拿到子组件的数据
  • 常规的v-bind需要携带参数key值进行传递,例如v-bind:info = '123';但是有时候会省略这个key值,直接进行传递数据,如v-bind = 'item',这种用法会将整个对象的所有属性都绑定到当前元素上,适用于需要绑定的属性过多的场景
// data: {
//     shapes: [
//         { name: 'Square', sides: 4 },
//         { name: 'Hexagon', sides: 6 },
//         { name: 'Triangle', sides: 3 }
//     ],
//     colors: [
//         { name: 'Yellow', hex: '#F4D03F', },
//         { name: 'Green', hex: '#229954' },
//         { name: 'Purple', hex: '#9B59B6' }
//     ]
// }

    


    

{{ title }}
Vue.component('my-list', { template: '#my-list', props: [ 'title', 'items' ] });
递归组件

递归组件就是指组件在模板中调用自己,由于是组件自身调用,就不能像常规组件定义一样,可以省略组件的name配置,组件的递归需要依赖于自身的name配置(name还用于遍历组件的name选项来查找组件的实例);

  • 满足条件
    • 需要给组件设置一个name属性
    • 需要有一个明确的结束条件

动态组件

有时候我们需要根据一些条件,动态的切换/选择某个组件,在函数式组件中,没有上下文的概念,常用于程序化的在多个组件中选择一个,可以间接的解决动态切换组件的需求,缺点是基于js对象进行开发,不方便开发;
Vue官方提供了一个内置组件和is的属性,用来解决上述的问题


//component 就是js import进的组件实例,其值可以是标签名、组件名、直接绑定一个对象等
  • 为了使得组件具有缓存作用,可以使用的内置组件,这样只要不离开当前页面,切换到其他组件后deforeDestory不会执行,因此组件具有了缓存功能

拓展

components的第二种写法

常规的组件components是直接通过引用定义好的组件进行展示的,也可以直接在当前组件内定义,然后通过配置components进行渲染

Web Component 简介

HTML的slot元素,是Web Components技术套件的一部分,是Web组件内的一个占位符,该占位符可以在后期使用自己的标记语言进行填充,这样可以创建单独的DOM树,并将其与其他的组件组合在一起 -- MDN

常见的填充Web组件的shadow DOM的模板有template和slot

  • 模板 - Templates

    • 需要在网页上重复的使用相同的标记结构时,为了避免CV的操作可以通过模板的方式进行实现
    • 需要注意的是模板 - Template 和其内部的内容是不会在DOM中呈现的,可以通过js进行访问并添加到DOM中,从而在界面上进行展示
    let template = document.getElementById('my-paragraph');
    let templateContent = template.content;
    document.body.appendChild(templateContent);
    • 可以配合Web Component一起使用,实现纯js自定义的组件
    customElements.define('my-paragraph',
      class extends HTMLElement {
        constructor() {
          super();
          let template = document.getElementById('my-paragraph');
          let templateContent = template.content;
    
          const shadowRoot = this.attachShadow({mode: 'open'})
            .appendChild(templateContent.cloneNode(true));
      }
    })
    
    // 自定义标签使用
    
    • 后续的样式逻辑也需要加在template中,方便通过后续的相关逻辑(如template.content获取到然后打入到指定的容器中)
  • Web Component简介

    AI智研社
    AI智研社

    AI智研社是一个专注于人工智能领域的综合性平台

    下载
    • Web Component的一个很重要的属性就是封装 - 可以将标记结构、样式和行为影藏起来,并于界面上的其他代码隔离开来,保证代码的独立性

    • Web Component标准非常重要的一个特性是,使得开发者可以将HTML页面的功能封住成custom elements(自定义标签)

    • customElements 接口用来实现一个对象,允许开发者注册一个custom elements的信息,返回已注册的自定义标签的信息;

    • customElements.define方法用来注册一个custom element,接收三个参数

      • 参数一:表明创建元素的名称,其注册的名称不能简单的单词,需要由短划线进行拼接

      • 参数二:用于定义元素行为的类

      • 参数三:一个包含extends属性配置的配置对象,可选,指定了所创建的自定义元素是继承于哪个内置的元素,可以继承任何内置的元素;

        customElements.define(
            'word-count', 
            WordCount, 
            { extends: 'p' }
        );

        可以使用ES2015的类实现

        class WordCount extends HTMLParagraphElement {
          constructor() {
            // 必须首先调用 super 方法
            super();
            // 元素的功能代码写在这里
            ...
          }
        }
    • 自定义标签的类型

      • 类型一:Autonomous custom elements 是独立的元素,它不继承其他内建的 HTML 元素,可以直接通过标签的方式进行HTML使用,也可以通过js的方式进行使用document.createElement("popup-info")
      • 类型二:Customized built-in elements 继承自基本的 HTML 元素。在创建时,你必须指定所需扩展的元素,使用时,需要先写出基本的元素标签,并通过 is属性指定 custom element 的名称;

        document.createElement("p", { is: "word-count" })

      参考文献 - MDN

  • shadow DOM简介

    • 图解Shandow DOM

    3.png

    • Shadow host:一个常规 DOM 节点,Shadow DOM 会被附加到这个节点上。

    • Shadow tree:Shadow DOM 内部的 DOM 树。

    • Shadow boundary:Shadow DOM 结束的地方,也是常规 DOM 开始的地方。

    • Shadow root: Shadow tree 的根节点。

    shadow DOM主要是将一个隐藏的、独立的DOM树附加到常规的DOM树上,是以shadow DOM节点为起始根节点,在这个根节点的下方,可以是任意的元素,和普通的DOM元素一致

如常见的video标签,其内部的一些控制器和按钮等都是通过Shandow DOM进行维护的,开发者可以通过这个API进行自己独立的逻辑控制

  • 基本用法

    • Element.attachShadow()方法可以将一个shadow DOM添加到任何一个元素上,接收一个配置对象参数,该对象有一个mode的属性,值可以是open - 可以通过外部js获取 Shadow DOM和closed - 外部不可以通过js进行获取 Shadow DOM
    let shadow1 = elementRef.attachShadow({mode: 'open'});
    let shadow2 = elementRef.attachShadow({mode: 'closed'});
    let myShadowDom = shadow1.shadowRoot; // 具体内容
    let myShadowDom = shadow2.shadowRoot; //null
    • 当需要将一个shadow DOM添加到自定义的标签上时,可以在自定义的构造函数中添加如下逻辑;
    let shadow = this.attachShadow({mode: 'open'});
    // 将一个shadow DOM添加到一个元素上之后就可以使用DOM API进行操作访问了

(学习视频分享:web前端开发编程基础视频

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

109

2023.09.26

define的用法
define的用法

define用法:1、定义常量;2、定义函数宏:3、定义条件编译;4、定义多行宏。更多关于define的用法的内容,大家可以阅读本专题下的文章。

338

2023.10.11

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1155

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

214

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1961

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

22

2026.01.19

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

515

2023.06.20

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue 教程
Vue 教程

共42课时 | 7.4万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号