<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
第一:我們熟知的HTML標籤有 a, p, div, section, ul, li, h2, article, head, body, strong, video, audio 等等
第二:我們知道,a標籤是連結,p標籤是段落,div是塊級,h2是字型,strong 是粗體,video 可以播放視訊,標籤可以新增click等事件等等
所以,那麼顯然我們知道這些標籤的名稱,而且知道他們的預設的css樣式,而且知道他們預設的js事件
由此,我們是否可以自定義標籤呢,由我們自己規定名稱,規定預設css樣式,規定標籤預設顯示dom結構,規定預設事件呢?
答案當然是肯定的!!下面就介紹主角Web元件
class UserCard extends HTMLElement { constructor() { super(); } } window.customElements.define('user-card', UserCard);
元件的樣式應該與程式碼封裝在一起,只對自定義元素生效,不影響外部的全域性樣式,:host偽類,指代自定義元素本身
<html> <head></head> <body> <user-card name="Marty Mcfly"></user-card> <template id="userCardTemplate"> <div class="profile-picture"> <img src="marty.png" alt="Marty Mcfly" /> </div> <div class="name"></div> <style> :host { display: flex; align-items: center; width: 450px; height: 180px; background-color: #d4d4d4; border: 1px solid #d5d5d5; box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1); border-radius: 3px; overflow: hidden; padding: 10px; box-sizing: border-box; font-family: 'Poppins', sans-serif; } .image { flex: 0 0 auto; width: 160px; height: 160px; vertical-align: middle; border-radius: 5px; } </style> </template> <script> class UserCard extends HTMLElement { constructor() { super(); var templateElem = document.getElementById('userCardTemplate'); var content = templateElem.content.cloneNode(true); // 使用name引數 content.querySelector('.container>.name').innerText = this.getAttribute('name'); this.appendChild(content); } } window.customElements.define('user-card', UserCard); </script> </body> </html>
<script> class UserCard extends HTMLElement { constructor() { super(); var shadow = this.attachShadow( { mode: 'closed' } ); /******這行開啟shadow*****/ var templateElem = document.getElementById('userCardTemplate'); var content = templateElem.content.cloneNode(true); // 使用name引數 content.querySelector('.container>.name').innerText = this.getAttribute('name'); shadow.appendChild(content); /******這行template新增到shadow*****/ } } window.customElements.define('user-card', UserCard); </script>
class UserCard extends HTMLElement { // attributeChangedCallback 能監聽的屬性 static get observedAttributes() {return ['name', 'url']; } constructor() { super(); // 可以創Shadom,通過this.shadowRoot獲取 // this.attachShadow({ mode: 'open' }) } connectedCallback (){ console.log('勾點,元素append到ducument觸發') } disconnectedCallback (){ console.log('勾點,元素從document刪除觸發') } // 只有observedAttributes 中監聽的屬性name,url變化會觸發下面回撥 attributeChangedCallback (attr, oldVal, newVal){ console.log('勾點,元素屬性改變時觸發') } } window.customElements.define('user-card', UserCard);
姓名 | 何時呼叫 |
---|---|
constructor | 元素的一個範例被建立。對於初始化狀態、設定事件監聽器或建立shadow Dom。 |
connectedCallback | 每次將元素插入 DOM 時呼叫。一般主要工作程式碼寫在這裡。 |
disconnectedCallback | 每次從 DOM 中刪除元素時呼叫。一般寫清理的一些程式碼。 |
attributeChangedCallback(attrName, oldVal, newVal) | 觀察屬性在新增、刪除、更新、替換時被呼叫。只有屬性中列出的observedAttributes屬性才會收到此回撥。 |
adoptedCallback | 自定義元素已被移動到一個新的document(例如有人稱為document.adoptNode(el))。 |
html中attribute 和 類中property 是各自獨立,想要建立對映需要手動設定
getter和setter生效
<html> <head></head> <body> <user-card id="usercard" name="Marty"></user-card> <script> class UserCard extends HTMLElement { _name = null; constructor() { super(); } set name(value) { this._name = name; } get name() { return this._name; } } window.customElements.define("user-card", UserCard); </script> </body> </html>
測試
document.getElementById('usercard').name = 'jack' // 會進入setter document.getElementById('usercard').name // 會進入getter,返回jack document.getElementById('usercard').getAttribute('name') // 不會進入getter,返回Marty document.getElementById('usercard').setAttribute('name','bob') // 不會進入setter document.getElementById('usercard').getAttribute('name') // 不會進入getter,返回bob
此時,我們看到 setAttribute 和 gettAttribute 都不會觸發類中的 getter 和 setter 方法,但是可以看到如果是 .name 這樣的方式可以觸發 ,那麼改造方式如下:
方式一 重寫 setAttribute :
<html> <head></head> <body> <user-card id="usercard" name="Marty"></user-card> <user-card id="uc" name="Marty Mcfly"></user-card> <script> const rawSetAttribute = Element.prototype.setAttribute; class UserCard extends HTMLElement { _name = null; constructor() { super(); Element.prototype.setAttribute = function setAttribute(key, value) { // 特定的指定name if (key == "name") { this.name = value; // 這樣就能觸發 setter } rawSetAttribute.call(this, key, value); }; } set name(value) { debugger; this._name = name; } get name() { debugger; return this._name; } } window.customElements.define("user-card", UserCard); </script> </body> </html>
方式二 重寫 observedAttributes和attributeChangedCallback 監聽 name :
<html> <head></head> <body> <user-card id="uc" name="Marty Mcfly"></user-card> <script> class UserCard extends HTMLElement { static get observedAttributes() { return ["name"]; } _name = null; constructor() { super(); } attributeChangedCallback(attr, _oldVal, newVal) { if (attr == "name") { this.name = newVal; } } set name(value) { debugger; this._name = name; } get name() { debugger; return this._name; } } window.customElements.define("user-card", UserCard); </script> </body> </html>
由此,可以看到元件在頁面渲染時會進入setter方法,而且 setAttribute,getAttribute 均進入到setter方法
document.getElementById('usercard').setAttribute('name','bob') // 會進入setter document.getElementById('usercard').getAttribute('name') // 會進入getter,返回bob
假設您想建立一個更高階的<button>. 與其複製<button>的行為和功能,更好的選擇是使用自定義元素逐步增強現有元素。
class FancyButton extends HTMLButtonElement { constructor() { super(); this.addEventListener('click', e => this.drawRipple(e.offsetX, e.offsetY)); } drawRipple(x, y) { let div = document.createElement('div'); div.classList.add('ripple'); this.appendChild(div); div.style.top = `${y - div.clientHeight/2}px`; div.style.left = `${x - div.clientWidth/2}px`; div.style.backgroundColor = 'currentColor'; div.classList.add('run'); div.addEventListener('transitionend', e => div.remove()); } } customElements.define('fancy-button', FancyButton, {extends: 'button'});
注意:擴充套件基礎元素時,對的呼叫 define() 略有變化。必需的第三個引數告訴瀏覽器您正在擴充套件哪個標籤
<button is="fancy-button" disabled>Fancy button!</button>
let button = document.createElement('button', {is: 'fancy-button'}); button.textContent = 'Fancy button!'; button.disabled = true; document.body.appendChild(button);
let button = new FancyButton(); button.textContent = 'Fancy button!'; button.disabled = true;
以上就是微前端之Web元件自定義元素範例詳解的詳細內容,更多關於微前端Web元件自定義元素的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45