溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Web?Components如何實(shí)現(xiàn)類Element?UI中的Card卡片

發(fā)布時(shí)間:2022-07-08 09:30:41 來源:億速云 閱讀:211 作者:iii 欄目:開發(fā)技術(shù)

這篇“Web Components如何實(shí)現(xiàn)類Element UI中的Card卡片”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Web Components如何實(shí)現(xiàn)類Element UI中的Card卡片”文章吧。

    Web Components 核心組成

    • 自定義元素(custom element),使用 window.customElements.define API注冊

    • Shadow DOM隔離,影藏標(biāo)記結(jié)構(gòu)、樣式和行為

    • 可以在<template>中定義標(biāo)記結(jié)構(gòu)、樣式,多次重用。利用 slot 插槽、命名插槽,可以傳入定制化的結(jié)構(gòu)UI,使用上類似 Vue 中的 slot 插槽

    1. Custom Elements

    自定義的 HTML 標(biāo)簽,稱為自定義元素(custom element)。根據(jù)規(guī)范,自定義元素的名稱必須包含連詞線-,用與區(qū)別原生的 HTML 元素。所以,<com-card>不能寫成<comcard>。

    <div id="custom-card" class="com-card">
      <div class="com-card-head">
        <slot name="head"></slot>
      </div>
      <div class="com-card-body">
        <slot></slot>
        <div class="link-wrap">
          <a class="link" href="" title=" rel="external nofollow"  rel="external nofollow" "></a>
        </div>
      </div>
    </div>
    <script>
      class ComCard extends HTMLElement {
        constructor() {
          super()
          var tplEle = document.getElementById('custom-card')
          this.append(tplEle)
        }
      }
      window.customElements.define('com-card', ComCard)
    </script>

    這樣就注冊了瀏覽器可識(shí)別渲染的一個(gè)自定義元素標(biāo)簽。

    2. Shadow DOM

    Shadow DOM 是對DOM的一個(gè)封裝??梢詫?biāo)記結(jié)構(gòu)、樣式和行為隱藏起來,并與頁面上的其他代碼相隔離,保證不同的部分不會(huì)混在一起,可使代碼更加干凈、整潔。
    使用自定義元素的 this.attachShadow() 方法可以開啟 Shadow DOM。

    class ComCard extends HTMLElement {
      constructor() {
        super()
        var shadow = this.attachShadow({mode: 'closed'})  // open
        var tplEle = document.getElementById('custom-card')
        shadow.appendChild(tplEle)
      }
    }
    window.customElements.define('com-card', ComCard);

    其中參數(shù){ mode: 'closed' },表示 Shadow DOM 是封閉的,不允許外部訪問。

    3. templates 和 slots

    因?yàn)榻M件的樣式應(yīng)該與代碼封裝在一起,只對自定義元素生效,不影響外部的全局樣式。所以,可以把樣式寫在<template>里面,這樣作為自定義元素結(jié)構(gòu)的基礎(chǔ)可以被多次重用。

    <template id="custom-card-template">
      <style>
        .com-card {
        }
      </style>
      <div class="com-card">
      </div>
    </template>
    <script>
      class ComCard extends HTMLElement {
        constructor() {
          super();
          var shadow = this.attachShadow({mode: 'closed'})  // open
          var tplEle = document.getElementById('custom-card-template')
          var content = tplEle.content.cloneNode(true)
          shadow.appendChild(content)
        }
      }
      window.customElements.define('com-card', ComCard);
    </script>

    完整代碼

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8">
      <title>Web Component</title>
      <style>
        * {
            box-sizing: border-box;
        }
        body {
            font-size: 14px;
        }
        .box {
            padding: 5px 0 30px;
        }
        .box .caption {
            display: none;
        }
        .box h2 {
            text-align: center;
        }
        .box li {
            color: #666;
            font-size: 14px;
            line-height: 1.8;
            margin-top: 15px;
        }
        .img {
            display: block;
            width: 80%;
            margin: 0 !important;
        }
        .card-head {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .card-title {
            color: #333;
            font-size: 16px;
        }
        .card-head-btn {
            color: #409eff;
            cursor: pointer;
            text-decoration: none !important;
        }
        .card-head-btn:hover {
            text-decoration: none;
        }
      </style>
    </head>
    <body>
    <div class="box">
      <h2>Web Component</h2>
      <com-card data-show-head="0" data-url="https://tiven.cn" data-title="天問博客">
        <div slot="head" class="card-head">
          <div class="card-title">卡片名稱</div>
          <a class="card-head-btn">操作按鈕</a>
        </div>
        <img class="img" src="https://tiven.cn/static/img/kpl-sunwukong-a3Lt-ed2NG9r4NFDm_9DA.jpg" alt="天問">
      </com-card>
      <br>
      <br>
      <com-card data-show-head="1" data-url="https://tiven.cn/p/de241e23/" data-title="Vite+Vue3+Vant快速構(gòu)建項(xiàng)目">
        <div slot="head" class="card-head">
          <div class="card-title">卡片名稱</div>
          <a class="card-head-btn" onclick="hello()">操作按鈕</a>
        </div>
        <img class="img" src="https://tiven.cn/static/img/kpl-xuance-JqX71qH7aTflHV_gqvhIc.jpg" alt="天問">
        <ol>
          <li>君不見黃河之水天上來,奔流到海不復(fù)回。</li>
          <li>君不見高堂明鏡悲白發(fā),朝如青絲暮成雪。</li>
          <li>天生我材必有用,千金散盡還復(fù)來。</li>
        </ol>
      </com-card>
    </div>
    <template id="custom-card-template">
      <style>
        .com-card {
            min-width: 200px;
            min-height: 100px;
            border-radius: 4px;
            border: 1px solid #ebeef5;
            background-color: #fff;
            overflow: hidden;
            color: #303133;
            transition: .3s;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
        }
        .com-card-head {
            padding: 10px 20px;
            border-bottom: 1px solid #ebeef5;
            box-sizing: border-box;
        }
        .com-card-body {
            padding: 20px;
        }
        .link-wrap {
            text-align: left;
            padding-top: 20px;
        }
        .link {
            display: inline-block;
            height: 42px;
            line-height: 43px;
            padding: 0 30px;
            text-align: center;
            cursor: pointer;
            color: #fff;
            background-color: #409eff;
            border-color: #409eff;
            -webkit-appearance: none;
            box-sizing: border-box;
            outline: none;
            transition: .1s;
            font-weight: 500;
            -moz-user-select: none;
            -webkit-user-select: none;
            -ms-user-select: none;
            font-size: 14px;
            border-radius: 4px;
            text-decoration: none !important;
        }
      </style>
      <div class="com-card">
        <div class="com-card-head">
          <slot name="head"></slot>
        </div>
        <div class="com-card-body">
          <slot></slot>
          <div class="link-wrap">
            <a class="link" href="" title=" rel="external nofollow"  rel="external nofollow" "></a>
          </div>
        </div>
      </div>
    </template>
    <script>
      class ComCard extends HTMLElement {
        constructor() {
          super();
          var shadow = this.attachShadow({mode: 'closed'})  // open
          var tplEle = document.getElementById('custom-card-template')
          var content = tplEle.content.cloneNode(true)
          var attrList = Array.from(this.attributes);
          var props = attrList.reduce((prev, item)=>{
            prev[item.name] = item.value
            return prev
          }, {})
          if (props['data-show-head']!=='1') {
            var head = content.querySelector('.com-card-head')
            head.remove()
          }
          var urlEle = content.querySelector('.link')
          if (props['data-url'] && props['data-title']) {
            urlEle.href = props['data-url']
            urlEle.title = props['data-title']
            urlEle.innerText = props['data-title']
          } else {
            urlEle.remove()
          }
          shadow.appendChild(content)
        }
        connectedCallback(){
          //在這里發(fā)送數(shù)據(jù)請求(Ajax)
          console.log('connectedCallback')
        }
        //被從文檔DOM中刪除時(shí)調(diào)用
        disconnectedCallback(){
          console.log('disconnectedCallback')
        }
        //被移動(dòng)到新的文檔時(shí)調(diào)用
        adoptedCallback(){
          console.log('adoptedCallback')
        }
        //當(dāng)增加、刪除、修改自身的屬性時(shí)被調(diào)用
        attributeChangedCallback(){
          console.log('attributeChangedCallback')
        }
      }
      window.customElements.define('com-card', ComCard);
      function hello() {
        alert('Hello,Web Component')
      }
    </script>
    </body>
    </html>

    最終效果如上圖所示

    Web Components vs Vue Components

    Vue ComponentWeb Component
    data實(shí)例屬性
    propsattributes
    watchobservedAttributes、attributeChangedCallback
    computedgetters
    methodsclass methods
    mountedconnectedCallback
    destroyeddisconnectedCallback
    style scopedtemplate中的style
    templatetemplate

    Web Components 生命周期回調(diào)函數(shù)

    connectedCallback:當(dāng) custom element首次被插入文檔DOM時(shí),被調(diào)用。

    disconnectedCallback:當(dāng) custom element從文檔DOM中刪除時(shí),被調(diào)用。

    adoptedCallback:當(dāng) custom element被移動(dòng)到新的文檔時(shí),被調(diào)用。

    attributeChangedCallback: 當(dāng) custom element增加、刪除、修改自身屬性時(shí),被調(diào)用。

    優(yōu)點(diǎn) and 缺點(diǎn)

    優(yōu)點(diǎn):

    • 瀏覽器原生支持,不需要引入額外的第三方庫

    • 語義化

    • 復(fù)用性,移植性高

    • 不同團(tuán)隊(duì)不同項(xiàng)目可以共用組件

    缺點(diǎn):

    • 需要操作DOM

    • 目前瀏覽器兼容性、性能方面不夠友好

    • 和外部css交互比較難

    七、基于web components的框架

    LitElement 是一個(gè)快速、輕量級的 Web UI 框架。使用 lit-html 來渲染元素。

    Polymer 是一款實(shí)用、基于事件驅(qū)動(dòng)、封裝性和交互性強(qiáng)的 Web UI 框架。

    Omi 是基于 Web 組件的跨框架跨平臺(tái)框架 。移動(dòng)端 & 桌面 & 小程序。

    以上就是關(guān)于“Web Components如何實(shí)現(xiàn)類Element UI中的Card卡片”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI