文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

WebComponent如何使用

2023-07-05 05:46

关注

本篇内容介绍了“WebComponent如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

正文

WebComponent 是官方定义的自定义组件实现方式,它可以让开发者不依赖任何第三方框架(如Vue,React)来实现自定义页面组件;达到组件复用效果

一个简单例子,让页面显示 hello world:

<body>  <!-- 使用组件的方式 -->  <my-text />  <script>    class MyText extends HTMLElement {      constructor() {        super();        this.append("hello world");      }    }    window.customElements.define("my-text", MyText);  </script></body>

三项主要技术

1、Custom elements (自定义元素)

分为两种形式:

自主定制元素:是独立的元素,它不继承其他内建的 HTML 元素,可以直接把它们写成 HTML 标签的形式,来在页面上使用,例如我们刚才自定义的 <my-text>

自定义内置元素:继承自内置的 HTML 元素。指定所需扩展的元素

<!-- 自定义内置元素 使用 is--><body>  <!-- 使用组件的方式 -->  <p is="color-p" color="green">云牧</p>  <script>    class ColorP extends HTMLParagraphElement {      constructor() {        super();        this.style.color = this.getAttribute("color");      }    }    window.customElements.define("color-p", ColorP, { extends: "p" });  </script></body>

推荐在 connectedCallback 生命周期函数,处理节点操作

<!-- 自主定制元素--><body>  <my-text />  <script>    class MyText extends HTMLElement {      constructor() {        super();      }      connectedCallback() {        this.append("hello world");      }    }    window.customElements.define("my-text", MyText);  </script></body>

生命周期函数

connectedCallback:插入文档时,可能被多次触发,比如删除后又添加到文档

disconnectedCallback:从文档删除时,可配置做清理工作

adoptedCallback:被移动新文档时

attributeChangedCallback:属性变化时

不同操作触发的生命周期函数:

WebComponent如何使用

例子:

<body>  <div id="container">    <p is="my-text" text="云牧" id="myText"></p>  </div>  <button id="btnUpdateText">更新属性</button>  <button id="btnRemove">删除节点</button>  <button id="btnRestore">恢复节点</button>  <button id="btnAdopt">移动节点</button>  <iframe src="./ifr.html" id="ifr"></iframe>  <script>    class MyText extends HTMLParagraphElement {      constructor() {        super();      }      connectedCallback() {        console.log("生命周期:connectedCallback");        this.append("你好:" + this.getAttribute("text"));      }      disconnectedCallback() {        console.log("生命周期:disconnectedCallback");        this.innerHTML = "";      }      // 监测的属性      static get observedAttributes() {        return ["text"];      }      attributeChangedCallback(name, oldValue, newValue) {        console.log("生命周期:attributeChangedCallback", name, oldValue, newValue);        // 最先触发是此函数,判断是不是第一次触发,第一次的话,只由 connectedCallback 处理        if (oldValue != null) {          this.replaceChildren("你好:" + newValue);        }      }      adoptedCallback() {        console.log("生命周期:adoptedCallback");      }    }    window.customElements.define("my-text", MyText, { extends: "p" });    const myText = document.getElementById("myText");    btnUpdateText.addEventListener("click", function (e) {      myText.setAttribute("text", "黛玉");    });    btnRemove.addEventListener("click", function (e) {      myText.remove();    });    btnRestore.addEventListener("click", function (e) {      container.appendChild(myText);    });    btnAdopt.addEventListener("click", () => {      const textNode = ifr.contentWindow.document.getElementById("myText");      container.appendChild(document.adoptNode(textNode));    });  </script></body>

2、HTML templates(HTML 模板)

<body>  <product-item    name="关东煮"    img="//img10.360buyimg.com/seckillcms/s200x200_jfs/t1/121953/18/20515/175357/61e7dc79Ee0acbf20/4f4f56abd2ea2f75.jpg!cc_200x200.webp"    price="49.8"  ></product-item>  <script>    class ProductItem extends HTMLElement {      constructor() {        super();      }      connectedCallback() {        const content = `                  <img class="img" src="https://misc.360buyimg.com/lib/skin/e/i/error-jd.gif" />                  <div class="name"></div>                  <div class="price"></div>              `;        this.innerHTML = content;        this.querySelector(".img").src = this.getAttribute("img");        this.querySelector(".name").innerText = this.getAttribute("name");        this.querySelector(".price").innerText = this.getAttribute("price");      }    }    window.customElements.define("product-item", ProductItem);  </script></body>

template 方式

<body>  <!-- template -->  <template id="tpl-product-item">    <img class="img" src="https://misc.360buyimg.com/lib/skin/e/i/error-jd.gif" />    <div class="name"></div>    <div class="price"></div>  </template>  <product-item    name="关东煮"    img="//img10.360buyimg.com/seckillcms/s200x200_jfs/t1/121953/18/20515/175357/61e7dc79Ee0acbf20/4f4f56abd2ea2f75.jpg!cc_200x200.webp"    price="49.8"  ></product-item>  <script>    class ProductItem extends HTMLElement {      constructor() {        super();      }      connectedCallback() {        const content = document.getElementById("tpl-product-item").content.cloneNode(true);        // 插入克隆的模板内容        this.append(content);        this.querySelector(".img").src = this.getAttribute("img");        this.querySelector(".name").innerText = this.getAttribute("name");        this.querySelector(".price").innerText = this.getAttribute("price");      }    }    window.customElements.define("product-item", ProductItem);  </script></body>

slot

<body>  <template id="tpl-test">    <style>      .title {        color: green;      }    </style>    <div class="title">标题</div>    <slot name="slot-des">默认内容</slot>  </template>  <test-item>    <div slot="slot-des">不是默认内容</div>  </test-item>  <script>    class TestItem extends HTMLElement {      constructor() {        super();      }      connectedCallback() {        const content = document.getElementById("tpl-test").content.cloneNode(true);        const shadow = this.attachShadow({ mode: "open" });        shadow.append(content);      }    }    window.customElements.define("test-item", TestItem);  </script></body>

3、Shadow DOM(影子 DOM)

WebComponent如何使用

影子DOM,其内部样式不共享

<body>  <!--  不受外部 .container.container 的颜色影响 -->  <my-item-s></my-item-s>  <div class="container">My item</div>  <style>    .container.container {      color: green;    }  </style>  <template id="tpl">    <style>      .container {        color: pink;      }    </style>    <div class="container">My Item</div>  </template>  <script>    class MyItemShadow extends HTMLElement {      constructor() {        super();      }      connectedCallback() {        const content = document.getElementById("tpl").content.cloneNode(true);        const shadow = this.attachShadow({ mode: "open" });        shadow.append(content);      }    }    window.customElements.define("my-item-s", MyItemShadow);  </script></body>

影子DOM,其内部元素不可以直接被访问到

有一个重要的参数 mode

<body>  <template id="tpl">    <div class="title"></div>    <div class="des"></div>  </template>  <note-item class="note-item" title="标题" des="内容"></note-item>  <script>    class NoteItem extends HTMLElement {      constructor() {        super();      }      connectedCallback() {        const content = document.getElementById("tpl").content.cloneNode(true);        const shadow = this.attachShadow({ mode: "open" });        shadow.append(content);        // 如果是 open 则可以继续访问操作内部 dom        // console.log(document.querySelector(".note-item").shadowRoot.querySelector(".title"));        shadow.querySelector(".title").textContent = this.getAttribute("title");        shadow.querySelector(".des").textContent = this.getAttribute("des");      }    }    window.customElements.define("note-item", NoteItem);  </script></body>

引入外部样式:

<body>  <template id="tpl">    <!-- 方式一: -->    <link rel="stylesheet" href="index.css" rel="external nofollow"  />    <div>My Item</div>  </template>  <my-item></my-item>  <script>    class MyItem extends HTMLElement {      constructor() {        super();      }      connectedCallback() {        const content = document.getElementById("tpl").content.cloneNode(true);        const shadow = this.attachShadow({ mode: "open" });        shadow.append(content);        // 方式二:        const linkEl = document.createElement("link");        linkEl.setAttribute("rel", "stylesheet");        linkEl.setAttribute("href", "index.css");        shadow.appendChild(linkEl);      }    }    window.customElements.define("my-item", MyItem);  </script></body>

动态创建 webComponent 组件例子

<body>  <div id="product-list" ></div>  <template id="product-item">    <style>      .product-item {        margin-left: 15px;        cursor: pointer;      }      .img {        width: 100px;      }      .name {        text-align: center;      }      .price {        color: #999;        text-align: center;      }    </style>    <div class="product-item">      <img class="img" src="https://misc.360buyimg.com/lib/skin/e/i/error-jd.gif" />      <div class="name"></div>      <div class="price"></div>    </div>  </template>  <script>    class ProductItemElement extends HTMLElement {      constructor(props) {        super(props);        this.addEventListener("click", () => {          window.open(`https://item.jd.com/${this.id}.html`);        });      }      connectedCallback() {        const shadow = this.attachShadow({ mode: "open" });        const content = document.getElementById("product-item").content.cloneNode(true);        content.querySelector(".img").src = this.img;        content.querySelector(".name").innerText = this.name;        content.querySelector(".price").innerText = this.price;        shadow.appendChild(content);      }    }    window.customElements.define("product-item", ProductItemElement);  </script>  <script>    const products = [      {        name: "关东煮",        img: "//img10.360buyimg.com/seckillcms/s200x200_jfs/t1/121953/18/20515/175357/61e7dc79Ee0acbf20/4f4f56abd2ea2f75.jpg!cc_200x200.webp",        id: "10026249568453",        price: 49.8      },      {        name: "土鸡蛋",        img: "//img11.360buyimg.com/seckillcms/s200x200_jfs/t1/172777/32/27438/130981/61fbd2e0E236000e0/7f5284367e2f5da6.jpg!cc_200x200.webp",        id: "10024773802639",        price: 49.8      },      {        name: "东北蜜枣粽子",        img: "//img20.360buyimg.com/seckillcms/s200x200_jfs/t1/129546/31/19459/110768/60b1f4b4Efd47366c/3a5b80c5193bc6ce.jpg!cc_200x200.webp",        id: "10035808728318",        price: 15      }    ];    const productList = document.getElementById("product-list");    const elList = products.map(product => {      // 创建组件      const el = document.createElement("product-item");      el.img = product.img;      el.name = product.name;      el.price = product.price;      el.id = product.id;      return el;    });    productList.append.apply(productList, elList);  </script></body>

“WebComponent如何使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯