Web Components详解-Shadow DOM基础

这篇具有很好参考价值的文章主要介绍了Web Components详解-Shadow DOM基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

引言

概念

基本用法

attachShadow函数

mode(模式)

delegatesFocus(委托聚焦)

Custom Elements+Shadow DOM

基本用法

样式及属性隔离

写在最后

相关代码

参考文章


引言

上篇文章的自定义标签中,我们使用customElements对象对原生标签进行拓展,达到组件的拓展性与复用性的效果,那么如何保证组件的属性、结构及样式的封装隔离便是本篇文章将要分享的内容,本篇文章不仅仅会介绍Shadow DOM的基本用法,还会对前面说到的Custom Elements做一个使用场景的拓展

概念

在JS作用域一文中,我们提到全局作用域和局部作用域的概念,如果全局作用域没有处理好可能会导致作用域污染,出现问题。如果单纯的使用Custom Elements实现自定义组件的功能可能会存在样式冲突,Dom干扰,组件中的类名或者ID冲突,复用性复杂等问题,这会导致组件的可靠性和可维护性降低,此时一个独立的Dom容器就显得非常重要了。

影子Dom(Shadow DOM),可以理解为DOM中的DOM,它是前端组件的核心之一,它提供了一套将标签与DOM树隔离的机制,大大提升了自定义标签或者普通标签的封装性,可重用性和可维护性。

shadowdom,Web Components,JavaScript,面试文档,前端,javascript,面试,开发语言,原力计划  

在使用Shadow DOM前,我们先了解一些专有名词

Shadow Host(影子宿主):Shadow DOM的容器。它是普通DOM中的一个元素,可以称为宿主元素。宿主元素可以是自定义的Web组件,例如一个自定义的标签、视频标签或任何其他的自定义元素。

Shadow Tree(影子的树):Shadow DOM内部的DOM树。在Shadow Host内部,开发者可以定义一个独立的DOM子树,其中包含组件的样式和结构,这个内部DOM树就是Shadow Tree。

Shadow Root(影子的根节点):Shadow Tree的根节点。通过使用Shadow Root,我们可以将Shadow Tree连接到Shadow Host上。影子根是Shadow DOM的入口点,通过Shadow Root我们可以访问Shadow Tree中的内容。

Shadow Boundary(影子的边界):Shadow DOM的隔离边界。Shadow DOM结束的地方,也是常规DOM开始的地方。这个边界将Shadow DOM和外部DOM分隔开来,防止它们互相干扰。外部DOM无法直接访问Shadow Tree的内容,只能访问到Shadow Host。

基本用法

使用element.attachShadow函数在宿主(Host)标签上创建根(Root)元素

<body>
    <div id="host"></div>
    <script>
        const hostEle = document.querySelector("#host")
        const treeEle = document.createElement("span")// 影子的树或后代节点
        treeEle.textContent = "treeEle"
        const rootEle = hostEle.attachShadow({ mode: 'open' });// 创建Shadow Root
        rootEle.appendChild(treeEle)// 将树添加到root标签
    </script>
</body>

attachShadow函数

attachShadow函数可以传入一个ShadowRootInit类型的参数,它有三个属性,分别是:mode,delegatesFocus,slotAssignment。

mode(模式)

mode是必传的值,代表是否允许外部访问和修改ShadowRoot的属性,open表示开放(允许),closed表示关闭(不允许)。

const hostEle = document.querySelector("#host")
const treeEle = document.createElement("span")
treeEle.textContent = "treeEle"
const rootEle = hostEle.attachShadow({ mode: 'closed' });// 不允许外部访问
rootEle.appendChild(treeEle)
console.log(hostEle.shadowRoot);// null

delegatesFocus(委托聚焦)

delegatesFocus可选,传入布尔值,表示是否减轻自定义元素的聚焦性能问题。当我们定义自定义标签时,标签可能不支持聚焦,此时让第一个可聚焦的部分成为焦点, 并且shadow host将提供所有可用的 :focus样式。怎么理解这句话?参考了许多网上的文章,做个总结,思考下面的代码:

<body>
    <div id="host"></div>
    <script>
        const hostEle = document.querySelector("#host")// 宿主元素
        const rootEle = hostEle.attachShadow({ mode: 'open', delegatesFocus: true });// 根元素
        const styleEle = document.createElement("style")// 样式元素
        styleEle.textContent = `div {
        width: 500px;
        height: 80px;
        border: 1px solid #000;
    }

    input:focus {
        background: lightblue;
    }`
        // 内部的其他树标签
        const treeEle = `<div>
        <input type="text" />
    </div>`
        // 在Shadow DOM中添加全部元素
        rootEle.appendChild(styleEle)
        rootEle.innerHTML += treeEle

    </script>
</body>

当delegatesFocus设置为true,并点击外部的div时,内部的输入框会被聚焦,输入框是标签中可以被聚焦的元素;

shadowdom,Web Components,JavaScript,面试文档,前端,javascript,面试,开发语言,原力计划

当delegatesFocus设置为false,点击外部div就不会聚焦任何标签。

shadowdom,Web Components,JavaScript,面试文档,前端,javascript,面试,开发语言,原力计划

Custom Elements+Shadow DOM

基本用法

基于自定义标签和上面讲到的知识点,我们尝试将二者结合,实现一个简易的自定义组件,思考下面的代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ShadowDOM</title>
</head>

<body>
    <my-custom-element></my-custom-element>
    <script>
        const elemName = "my-custom-element"
        const ele = document.querySelector(elemName)
        class MyCustomElement extends HTMLElement {
            constructor() {
                super();
                this.initShadow()
            }
            // 基于当前自定义标签创建
            initShadow() {
                this.appendChild(this.attachShadow({
                    mode: "open"
                }))
                this.shadowRoot.innerHTML = "<div>hello world</div>"
            }
        }
        customElements.define(elemName, MyCustomElement)
    </script>
</body>

</html>

样式及属性隔离

思考以下代码,通过props我们可以将组件的行为及数据传入自定义标签中,通过attachShadow隔离样式,自定义标签隔离属性和行为,达到一个组件容器的效果,其中this.shadowRoot就是标签的影子根元素,即this.attachShadow的产物

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ShadowDOM</title>
    <style>
        div {
            /* 全局样式无法影响内部标签 */
            border: 1px solid black;
        }
    </style>
</head>

<body>
    <my-custom-element></my-custom-element>
    <script>
        const elemName = "my-custom-element"
        const ele = document.querySelector(elemName)
        class MyCustomElement extends HTMLElement {
            styleContent = ""// 组件局部样式
            treeEle = ""// 影子(树)子节点
            constructor() {
                super();
                this.initProps()
                this.initShadow()
            }
            // 通过props传入参数
            initProps() {
                const { ele, style } = this.props
                this.styleContent = style
                this.treeEle = ele
            }
            // 基于当前自定义标签创建
            initShadow() {
                this.appendChild(this.attachShadow({
                    mode: "open"
                }))
                const styleEle = document.createElement("style")
                styleEle.textContent = this.styleContent
                this.shadowRoot.appendChild(styleEle)
                this.shadowRoot.innerHTML += this.treeEle
            }
        }
        // 自定义标签参数
        ele.props = {
            ele: "<div>hello world</div>",
            style: `
            div {
                width: 100px;
                height: 100px;
                background: lightcoral;
            }
            `
        }
        customElements.define(elemName, MyCustomElement)
        console.log(document.querySelectorAll("div")); // []  全局无法获取shadow中的标签
        console.log(ele.shadowRoot.querySelectorAll("div")[0].textContent);// hello world    可以通过element获取shadow标签
    </script>
</body>

</html>

上述代码可以看到,全局样式与元素只在当前的shadowDOM中可以访问,与全局作用域形成了隔离关系

写在最后

本文结合Custom Elements和Shadow DOM实现了一个简易的自定义组件,通过使用props传递参数,将组件的行为及数据传入自定义标签中,并通过attachShadow隔离样式,实现了属性、结构和样式的封装隔离,从而达到组件容器的效果。那么自定义组件之间如何进行通信?组件样式及选择器如何使用?在后续的系列文章中,我会对这些知识点做个详细说明,敬请期待!

感谢你看到了最后,如果觉得文章还不错的话,还请给个三连,感谢!

相关代码

myCode: 基于js的一些小案例或者项目 - Gitee.com

参考文章

影子 DOM(Shadow DOM)

使用 shadow DOM - Web API 接口参考 | MDN文章来源地址https://www.toymoban.com/news/detail-730411.html

到了这里,关于Web Components详解-Shadow DOM基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Web Components详解-Custom Elements

    目录 引言 演变过程 概述 使用方式 创建标签 定义标签 使用标签 获取标签 异步定义标签 升级标签 完整案例 结语 相关代码 参考文章 随着项目体量的增大,组件化和模块化的优势也愈发明显了,构建可重复使用、独立、可互操作的组件变得尤为重要,在JS中我们可以通过c

    2024年02月10日
    浏览(37)
  • 一文读懂JavaScript DOM节点操作(JavaScript DOM节点操作详解)

    一、什么是节点 DOM模型是树状结构模型,二组成这棵树的就是一个个点,在网络术语中称之为节点。 节点是一个模型中最基本的组成单位。DOM模型是由一个个节点组成的,DOM节点也有其不同的类型。 二、节点类型 DOM节点分为5种类型: 文档节点(就是整个HTML文档,也就是

    2024年01月22日
    浏览(48)
  • JavaScript 基础 DOM (二)

    事件流是对事件执行过程的描述 事件捕获 从DOM的根元素开始去执行对应的事件 (从外到里) 事件冒泡 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒 泡 addEventListener  第3个参数决定了事件是在捕获阶段触发还是在

    2024年02月05日
    浏览(29)
  • js操作shadow-root内的DOM元素

    一、背景 项目中在DOM结构里遇到了shadow-root(open),用JS方法无法直接获取其内的DOM元素 二、shadow DOM Web components 的一个重要属性是封装——可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。其中

    2024年02月15日
    浏览(39)
  • angular:HtmlElement的子节点有Shadow dom时奇怪的现象

    描述:         这样写时,会自动跳过shadow dom节点的遍历            或者使用cloneElement.childNodes.forEach遍历,也不会遍历到shadow dom节点         如果这样写:                 会在appendChild shadow dom节点报错,提示不是一个HtmlElement,无法append

    2024年02月07日
    浏览(30)
  • 前端基础自学整理|HTML + JavaScript + DOM事件

    目录 一、HTML 1、Html标签 2、Html元素 3、基本的HTML标签 二、CSS 样式 层叠样式表 三、JavaScript 使用示例 四、HTML DOM  通过可编程的对象模型,javaScript可以: window document 1、查找HTML元素 2、操作HTML元素 获取元素的属性 四、HTML DOM事件 ⚠️是DOM提供的API Html是用来描述网页的一

    2024年02月22日
    浏览(49)
  • 【JavaScript速成之路】一文带你掌握DOM基础

    📃个人主页:「小杨」的csdn博客 🔥系列专栏:【JavaScript速成之路】 🐳希望大家多多支持🥰一起进步呀! 小杨在上一篇带着大家一起学习了JavaScript中的内置对象,JavaScript基础的语法就结束了,下面我们将继续学习JavaScript中的DOM,希望大家通过阅读此文快速掌握DOM。 1.

    2023年04月26日
    浏览(39)
  • JavaScript从入门到精通系列第三十八篇:详解JavaScript中DOM的查询

    😉😉 学习交流群: ✅✅1:这是 孙哥suns 给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群: 583783824   📚📚  工作微信: BigTreeJava 拉你进微信群,免费领取! 🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

    2024年02月05日
    浏览(45)
  • 〖大前端 - 基础入门三大核心之JS篇㉟〗- JavaScript 的DOM简介

    说明:该文属于 大前端全栈架构白宝书专栏, 目前阶段免费 , 如需要项目实战或者是体系化资源,文末名片加V! 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。 荣誉: 2022年度博客之星Top4、2023年度超

    2024年02月04日
    浏览(54)
  • 【JavaScript】基于querySelector / querySelectorAll对元素的操作,为你的DOM API基础扫盲~

    目录 一、通过querySelector / querySelectorAll获取元素 1.1 单个标签选中 1.2 多个标签选中  二、基于这组DOM API,对元素进行操作 2.1 innerHTML获取/修改元素内容 2.2获取/修改元素属性 三、单标签元素属性的获取和修改 3.1 value 3.2checked 3.3 type 四、样式属性的修改和获取 4.1 fontSize行内样

    2024年01月16日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包