微服务-CSS隔离

115 阅读2分钟

Web Component

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

概念和使用

作为开发者,我们都知道尽可能多的重用代码是一个好主意。这对于自定义标记结构来说通常不是那么容易 — 想想复杂的 HTML(以及相关的样式和脚本),有时你不得不写代码来呈现自定义 UI 控件,并且如果你不小心的话,多次使用它们会使你的页面变得一团糟。

Web Components 旨在解决这些问题 — 它由三项主要技术组成,它们可以一起使用来创建封装功能的定制元素,可以在你喜欢的任何地方重用,不必担心代码冲突。

  • Custom element(自定义元素) :一组 JavaScript API,允许你定义 custom elements 及其行为,然后可以在你的用户界面中按照需要使用它们。
  • Shadow DOM(影子 DOM) :一组 JavaScript API,用于将封装的“影子”DOM 树附加到元素(与主文档 DOM 分开呈现)并控制其关联的功能。通过这种方式,你可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
  • HTML template(HTML 模板):  <template> 和 <slot> 元素使你可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。

手动简单实现一下

目录结构

image.png

首先实现一个类 MYWUJIE 继承 HTMLElement 然后注册一个自定义标签

    <h1>主应用</h1>
    <script>
        class MYWUJIE extends HTMLElement{
            constructor(){
                super()
            }
        }
        window.customElements.define('my-wujie-app',MYWUJIE)
    </script>

接下来就可以在dom模版中使用 类似Vue 也可以说Vue类似于人家 管他呢

    <h1>主应用</h1>
    <my-wujie-app src="http://127.0.0.1:5500/child1.html"></my-wujie-app>
    <script>
        class MYWUJIE extends HTMLElement{
            constructor(){
                super()
            }
        }
        window.customElements.define('my-wujie-app',MYWUJIE)
    </script>
接下来就是
  1. 获取src子应用地址
  2. fetch获取子应用的dom模版 解析
  3. 获取ShadowDOM 并填充子应用内容
 class MYWUJIE extends HTMLElement{
        constructor(){
            super()
        }
        //1. 获取子应用地址  也就是获取attr属性
        getAttr(name){
            return this.getAttribute(name)
        }
        //2. 获取子应用模版
        async fetchHtml(src){}
        //3. 填充内容
        injectDOM(){}
   }

// 不能写成驼峰的,html 不支持驼峰标签
window.customElements.define('my-wujie-app',MYWUJIE)

整体实现

        <h1>主应用</h1>
        <my-wujie-app src="http://127.0.0.1:5500/child1.html"></my-wujie-app>
        <script>
            class MYWUJIE extends HTMLElement {
                constructor() {
                    super()
                    this.src = this.getAttr('src')
                }
                //1. 获取子应用地址  也就是获取attr属性
                getAttr(name) {
                    return this.getAttribute(name)
                }
                //2. 获取子应用模版
                async fetchHtml(src) {
                    let html = await fetch(src)
                    let template = await html.text()
                    return template
                }
                //3. 填充内容
                injectDOM(root,html) {
                    let div = document.createElement('div')
                    div.innerHTML = html
                    root.appendChild(div)
                }
                // 挂载生命周期
                async connectedCallback() {
                    let tem = await this.fetchHtml(this.src)
                    let shadom = this.attachShadow({mode:'open'})
                    this.injectDOM(shadom,tem)
                }
                // 卸载
                disconnectedCallback() {
                    console.log('类似于 vue 的 destory')
                }
            }

            // 不能写成驼峰的,html 不支持驼峰标签
            window.customElements.define('my-wujie-app', MYWUJIE)
        </script>

运行 此时 主应用 子应用css会被隔离开 可以看到两个h1标签互不影响

image.png