眾所周知 Web Components 是一個(gè)瀏覽器原生支持的組件化方案,這個(gè)能夠創(chuàng)建新的自定義、可封裝、可重用的HTML 標(biāo)記。同時(shí)也可以不用加載任何外部模塊,能夠直接在瀏覽器中查看。今天我們想講的就是如何使用 Web Components 實(shí)現(xiàn)一個(gè)類 Element UI 中的 Card 卡片組件。
先進(jìn)變成如雨后春筍,出現(xiàn)了很多優(yōu)秀的框架,如:Vue、React、Angular等等,對(duì)于開(kāi)發(fā)效益有大大提升。
其中我們知道在組件化開(kāi)發(fā)發(fā)揮了至關(guān)重要的作用,但要注意在組件化開(kāi)發(fā)都需要依賴第三方框架,編譯打包之后才能在瀏覽器正常使用。
這里給大家給提出原生組件Web Components,與之第三方框架使用起來(lái)更簡(jiǎn)單直接,符合直覺(jué),不用加載任何外部模塊,代碼量小。
Web Components 核心組成
自定義元素(custom element),使用window.customElements.defineAPI注冊(cè)
Shadow DOM隔離,影藏標(biāo)記結(jié)構(gòu)、樣式和行為
這里要說(shuō)<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>
以上就可以注冊(cè)了瀏覽器可識(shí)別渲染的一個(gè)自定義元素標(biāo)簽。
2. Shadow DOM
Shadow DOM 是對(duì)DOM的一個(gè)封裝。可以將標(biāo)記結(jié)構(gòu)、樣式和行為隱藏起來(lái),并與頁(yè)面上的其他代碼相隔離,保證不同的部分不會(huì)混在一起,可使代碼更加干凈、整潔。
使用自定義元素的this.attachShadow()方法可以開(kāi)啟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是封閉的,外部是無(wú)法訪問(wèn)的。
3. templates 和 slots
因?yàn)榻M件的樣式應(yīng)該與代碼封裝在一起,只對(duì)自定義元素生效,不影響外部的全局樣式。所以,可以把樣式寫在<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 h1 { 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"> <h1>Web Component</h1> <com-card data-show-head="0" data-url="https://tiven.cn" data-title="天問(wèn)博客"> <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="天問(wèn)"> </com-card> <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="天問(wèn)"> <ol> <li>君不見(jiàn)黃河之水天上來(lái),奔流到海不復(fù)回。</li> <li>君不見(jiàn)高堂明鏡悲白發(fā),朝如青絲暮成雪。</li> <li>天生我材必有用,千金散盡還復(fù)來(lái)。</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ù)請(qǐng)求(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 Component | Web Component |
---|---|
data | 實(shí)例屬性 |
props | attributes |
watch | observedAttributes、attributeChangedCallback |
computed | getters |
methods | class methods |
mounted | connectedCallback |
destroyed | disconnectedCallback |
style scoped | template中的style |
template | template |
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):
瀏覽器原生支持,無(wú)需第三方庫(kù)
語(yǔ)義化
復(fù)用性,移植性高
在不同的tema也可以共用組件
缺點(diǎn):
需要操作DOM
不同瀏覽器無(wú)法兼容,體驗(yàn)不好
和外部css交互比較難
基于web components的框架
LitElement是一個(gè)快速、輕量級(jí)的 Web UI 框架。使用lit-html來(lái)渲染元素。
Polymer是一款實(shí)用、基于事件驅(qū)動(dòng)、封裝性和交互性強(qiáng)的 Web UI 框架。
Omi是基于 Web 組件的跨框架跨平臺(tái)框架 。移動(dòng)端 & 桌面 & 小程序。
本篇內(nèi)容已全部講述完畢,歡迎關(guān)注更多后續(xù)精彩內(nèi)容!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/130322.html
摘要:它賦予了僅僅使用純粹的就可以創(chuàng)建可重用組件的能力。我們會(huì)用到的來(lái)創(chuàng)建我們的用戶卡片。在較早版本的瀏覽器中,我們不能使用來(lái)隔離組件。這可以部分歸咎于對(duì)的影響很大的。你可以在這里閱讀第二部分的教程使用純粹的構(gòu)建 原文鏈接:https://ayushgp.github.io/htm...譯者:阿里云 - 也樹(shù) Web Component 出現(xiàn)有一陣子了。 Google 費(fèi)了很大力氣去推動(dòng)它更...
摘要:它賦予了僅僅使用純粹的就可以創(chuàng)建可重用組件的能力。我們會(huì)用到的來(lái)創(chuàng)建我們的用戶卡片。在較早版本的瀏覽器中,我們不能使用來(lái)隔離組件。這可以部分歸咎于對(duì)的影響很大的。你可以在這里閱讀第二部分的教程使用純粹的構(gòu)建 原文鏈接:https://ayushgp.github.io/htm...譯者:阿里云 - 也樹(shù) Web Component 出現(xiàn)有一陣子了。 Google 費(fèi)了很大力氣去推動(dòng)它更...
摘要:它賦予了僅僅使用純粹的就可以創(chuàng)建可重用組件的能力。我們會(huì)用到的來(lái)創(chuàng)建我們的用戶卡片。在較早版本的瀏覽器中,我們不能使用來(lái)隔離組件。這可以部分歸咎于對(duì)的影響很大的。你可以在這里閱讀第二部分的教程使用純粹的構(gòu)建 原文鏈接:https://ayushgp.github.io/htm...譯者:阿里云 - 也樹(shù) Web Component 出現(xiàn)有一陣子了。 Google 費(fèi)了很大力氣去推動(dòng)它更...
摘要:固定塊元素的大小,其中包含我們的圖片,這使我們能夠在滿足尺寸要求的情況下,任何圖片都可用于制作成卡片。字體及其他博文鏈接利用制作精美的卡片源碼鏈接利用制作精美的卡片原文鏈接翻譯墨丶水瓶 本教程將會(huì)告訴你如何用 Html 和 Css 實(shí)現(xiàn)卡片界面。教程會(huì)重點(diǎn)使用 Css filter 屬性處理圖片,以便給它添加一些過(guò)渡效果。 第一步:確定 HTML 代碼結(jié)構(gòu) 在創(chuàng)建 HTML 代碼前,你...
閱讀 561·2023-03-27 18:33
閱讀 748·2023-03-26 17:27
閱讀 645·2023-03-26 17:14
閱讀 602·2023-03-17 21:13
閱讀 537·2023-03-17 08:28
閱讀 1822·2023-02-27 22:32
閱讀 1315·2023-02-27 22:27
閱讀 2198·2023-01-20 08:28