您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax |

详解vue3.2新增的defineCustomElement底层原理

51自学网 2022-05-02 21:33:19
  javascript

Web Components

Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们。

相当于是浏览器原生的定义组件的方式,不用通过vue或者react这些框架实现组件的定义

customElements

概述

customElements 是Window对象上的一个只读属性,接口返回一个CustomElementRegistry 对象的引用,可用于注册新的 custom elements,或者获取之前定义过的自定义元素的信息。

HTMLTemplateElement 内容模板元素

概述

HTML内容模板(<template>)元素是一种用于保存客户端内容机制,该内容在加载页面时不会呈现,但随后可以(原文为 may be)在运行时使用JavaScript实例化。
将模板视为一个可存储在文档中以便后续使用的内容片段。虽然解析器在加载页面时确实会处理<template>元素的内容,但这样做只是为了确保这些内容有效;但元素内容不会被渲染。

常用属性

content 获取DocumentFragment 元素片段的内容
相当于通过document.createDocumentFragment()创建的元素片段,

  <!-- 定义template片段 -->  <template id="element-template">    <div>test-template</div>  </template>  <script>    /* 获取template片段 */    const ele = document.getElementById('element-template')    ele.content instanceof DocumentFragment  //true    /* 通过createDocumentFragment创建html片段*/    const div = document.createDocumentFragment('div')    div instanceof DocumentFragment    //true    /* 结论 */    // 定义在html上的template获取它的content相当于和通过createDocumentFragment创建的html片段是一个东西  </script>

ShadowRoot

概述

Shadow DOM API 的 ShadowRoot 接口是一个 DOM 子树的根节点, 它与文档的主 DOM 树分开渲染。
你可以通过使用一个元素的 Element.shadowRoot 属性来检索它的参考,假设它是由 Element.attachShadow() 创建的并使 mode 设置为 open.

通过 Element.attachShadow()挂载影子DOM

完整的演示代码

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title></head><body>  <test-shadow-root></test-shadow-root>  <template id="temEle">    <style>      .main{        color: #f00;      }    </style>    <div class="main">      我是template片段      <!-- 使用插槽 -->      <slot name="header"></slot>    </div>  </template>  <test-template-ele>    <!-- 定义插槽 -->    <style>      .slot{        color: rgb(87, 28, 223);      }    </style>    <div class="slot" slot="header">我是slot</div>  </test-template-ele>  <!-- 生命周期测试 -->  <div id="moveDiv">    <button id="add">添加</button>    <button id="update">更新</button>    <button id="move">移动</button>    <button id="remove">删除</button>  </div>  <!-- 通过is挂载 -->  <div is="test-is-com">    <div>AAA</div>  </div>  <script>    /* 自定义web-components */    customElements.define('test-shadow-root', class extends HTMLElement {      /* 当test-shadow-root组件被挂载到DOM上时,执行构造函数 */      constructor() {        super()        const shadowRoot = this.attachShadow({mode: 'open'}) //给指定的元素挂载影子DOM        // 当执行 this.attachShadow()方法时,shadowRoot被挂载构造函数中,可以通过this访问        // mode open shadow root元素可以从js外部访问根节点        // mode closed  拒绝从js外部访问关闭的shadow root节点        // console.log('执行', this)        const div = document.createElement('div')        div.textContent = '我是div的内容'        // shadowRoot.appendChild()        // console.log('this', this.shadowRoot)        shadowRoot.appendChild(div)        // this.shadowRoot === shadowRoot  true      }    })    /* 通过template自定义HTMLTemplateElement */    customElements.define('test-template-ele', class extends HTMLElement {      constructor() {        super()        const temEle = document.querySelector('#temEle')        const templateContent = temEle.content //获取html片段        // console.log('AA', templateContent instanceof DocumentFragment) //true        // templateContent        // 创建影子DOM,用于挂载template的片段        const shadowRoot = this.attachShadow({mode: 'open'})        // console.log('shadowRoot', shadowRoot)        shadowRoot.appendChild(templateContent)      }    })    /* 通过js创建web-组件,测试生命周期函数 */      class LifeCycle extends HTMLElement {        static get observedAttributes() {  //必须添加组件上的属性,才能触发attributeChangedCallback          return ['c', 'l'];        }        constructor() {          super()          const shadowRoot = this.attachShadow({mode: 'open'})          const div = `<div>            <heaher>我的头</header>            <div>内容</div>            <footer>尾部</footer>          </div>`          shadowRoot.innerHTML = div        }        connectedCallback() {  //添加时,执行          console.log('添加')        }        disconnectedCallback() {//删除时,执行          console.log('disconnectedCallback')        }        adoptedCallback() {          console.log('adoptedCallback')        }        attributeChangedCallback() {  //属性被改变时          console.log('attributeChangedCallback')        }      }      customElements.define('test-life-cycle', LifeCycle)      const add = document.querySelector('#add')      const update = document.querySelector('#update')      const move = document.querySelector('#move')      const remove = document.querySelector('#remove')      const moveDiv = document.querySelector('#moveDiv')      let testLifeDom = null      function random(min, max) {        return Math.floor(Math.random() * (max - min + 1) + min);      }      add.addEventListener('click', () => {        testLifeDom = document.createElement('test-life-cycle')  //创建上面定义的自定义组件        // console.log('testLifeDom', testLifeDom)        document.body.appendChild(testLifeDom);        testLifeDom.setAttribute('l', '100');        testLifeDom.setAttribute('c', 'red');        console.log('add', testLifeDom)      })      update.addEventListener('click', () => {        const div = '<div>更新后</div>'        // console.log('update', testLifeDom.shadowRoot.innerHTML)        testLifeDom.shadowRoot.innerHTML = div        testLifeDom.setAttribute('l', random(50, 200));        testLifeDom.setAttribute('c', `rgb(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)})`);      })      move.addEventListener('click', () => {        console.log('moveDiv', moveDiv)        moveDiv.appendChild(testLifeDom)      })      remove.addEventListener('click', () => {        console.log('remove')        document.body.removeChild(testLifeDom);      })      /* 通过is挂载组件 */      customElements.define('test-is-com', class extends HTMLDivElement {        constructor() {          super()          console.log('挂载', this.innerHTML)          // 通过挂载,this,就是当前被挂载的元素实例,通过这种方式,可以实现一些操作        }      }, {extends: 'div'})  </script></body></html>

到此这篇关于详解vue3.2新增的defineCustomElement底层原理的文章就介绍到这了,更多相关vue3.2 defineCustomElement内容请搜索wanshiok.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持wanshiok.com!


利用JS判断数据类型的四种方法
Element 头像上传的实战
51自学网,即我要自学网,自学EXCEL、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。
京ICP备13026421号-1