innerHTML outerHTML textContent innerText 區別
<div id="test">
<span>sdsdsdsd <span>555</span></span>
bbbb
</div>
- innerHTML
從物件的起始位置到終止位置的全部內容,包括Html標籤
<span>sdsdsdsd <span>555</span></span>bbbb
-
innerText
從起始位置到終點位置的內容,去掉HTML內容,並且如果裡面有多個標籤或者迭代子代都是去除標籤的
sdsdsdsd 555 bbb
-
outerHTML
除了包含innerHTML的全部內容外,還包含物件標籤本身
-
textContent
跟innerText 返回的結果一樣
重要
根據W3C標籤,儘量用innerHTML,textContent,而少用innerText,outerHTML
動態訪問DOM
方法 | 描述 |
---|---|
document.createElement(``tag) |
建立並返回一個HTML標籤tag 。 |
element.appendChild(``child) |
新增的元素child 裡面element 。 |
element.insertAdjacentHTML(``pos,``html) |
將程式碼插入html 中element 。 |
element.insertAdjacentElement(``pos,``node) |
將元素node 插入element |
正常情況下我們使用的時候
class AppElement extends HTMLElement {
name = this.getAttribute("name") || "Desconocido";
connectedCallback() {
const element = document.createElement("div");
element.className = "element";
this.appendChild(element);
const innerElement = document.createElement("div");
innerElement.textContent = this.name;
element.appendChild(innerElement);
}
}
資料型別 | 特定型別 | 標籤 | 描述 |
---|---|---|---|
HTMLElement |
HTMLDivElement |
<div> |
看不見的分隔層(塊中)。 |
HTMLElement |
HTMLSpanElement |
<span> |
不可見的分隔層(線上)。 |
HTMLElement |
HTMLImageElement |
<img> |
圖片。 |
HTMLElement |
HTMLAudioElement |
<audio> |
音訊容器。 |
inserAdjacentHTML
element.insertAdjacentHTML(position, text);
position
插入內容的位置
'beforebegin'
:元素自身的前面。'afterbegin'
:插入元素內部的第一個子節點之前。'beforeend'
:插入元素內部的最後一個子節點之後。'afterend'
:元素自身的後面。
text
- 解析為html,並插入到DOM樹上,字串型別
// 原為 <div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// 此時,新結構變成:
// <div id="one">one</div><div id="two">two</div>
insertAdjacentElement(position, element);
個人覺得這個用的比較多
position
DOMString 表示相對於該元素的位置;必須是以下字串之一:
- 'beforebegin': 在該元素本身的前面.
- 'afterbegin':只在該元素當中, 在該元素第一個子孩子前面.
- 'beforeend':只在該元素當中, 在該元素最後一個子孩子後面.
- 'afterend': 在該元素本身的後面.
<div id="one">one</div>
<script>
let span = document.createElement('span');
span.textContent='3333';
let one=document.querySelector('#one');
one.insertAdjacentElement('beforebegin',span)
</script>
content.cloneNode(deep)
deep為 true 的時候,就是建立一個深層克隆,為false就是淺拷貝
我們要目標這個適用於自定義元素
// 建立一個自定義元件
const template = document.createElement("template");
template.innerHTML = `
<div class="element">
<div class="name"></div>
</div>`;
// 講自定義元件拷貝到AppElement 裡面
class AppElement extends HTMLElement {
name = this.getAttribute("name") || "Desconocido";
connectedCallback() {
const markup = template.content.cloneNode((true));
markup.querySelector(".name").textContent = this.name;
this.appendChild(markup);
}
}
shadow DOM
影子DOM
在javascript不同框架出現後,他們設計了Virstual DOM
: 頁面DOM的記憶體中副本,可以直接管理更改,以便後面轉換為文件的真實DOM,目的是加快優化頁面的DOM更改
例如:react 引入虛擬DOM,已檢測更改(樹之間的差異), 更新受影響的節點,然後再將其傳遞給真實的dom
語法
const div = document.createElement("div");
const shadow = div.attachShadow({ mode: "open" });
div.shadowRoot === shadow; // true
mode
定義了shadow DOM的封裝模式,建立shadow Dom元素將具有一個屬性,通過.shadowRoot
訪問
封裝css
我們知道css具有全域性特性,Shadow DOM
中css不會影響文件的css,也不會使全域性css傳遞到shaDow DOM
的css,就是具有沙箱形式
<style>
h1{
color:red;
}
</style>
<app-element></app-element>
<span>33233</span>
<script>
customElements.define("app-element", class App extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.shadowRoot.innerHTML = `
<style>
span {
background: steelblue;
padding: 5px;
color: white;
}
</style>
<div>
<span>CSS</span>
<h1>3333</h1>
</div>
`;
}
});
</script>
<h1>h1</h1>
我們發現,css被完全隔離開了
自定義元素
<app-element></app-element>
<script>
customElements.define("app-element", class extends HTMLElement {
connectedCallback() {
this.innerHTML = "<div>Hello, friend!</div>";
}
});
</script>
在自定義元素裡面插入 shadow DOM
<app-element>
<div class="container">Contenido previo del elemento</div>
</app-element>
<script>
customElements.define("app-element", class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.shadowRoot.innerHTML = "<div>Hello, friend!</div>";
}
});
</script>
我們發現建立頁面上的Shadow DOM
後,頁面上.container
的dom被隱藏了
換句話說當我們附加shadow DOM
時,它將隱藏Light DOM
,但是儘管Light DOM
被隱藏了,但是可以通過瀏覽器查詢到程式碼
<app-element>
#shadow-root (open)
<div>Hello, friend!</div>
<div class="container">Contenido previo del elemento</div>
</app-element>
我們this.shadowRoot.innerHTML
用於修改Shadow DOM。如果使用,我們將this.innerHTML
只修改Light DOM
。
插槽
<slot>
插槽中插入我們放置的Light DOM
connectedCallback() {
this.shadowRoot.innerHTML = "<div>Hello, friend! <slot>預設插槽</slot></div>";
}
我們發現預設插槽會被填充.container
的內容,當<app-element>
裡面為空的話,會填充預設的插槽
命名插槽
<app-element>
<h2 slot="name">Manz</h2>
<span slot="role">Developer</span>
<p slot="description">I hate Internet Explorer.</p>
</app-element>
<script>
customElements.define("app-element", class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.shadowRoot.innerHTML = `
<div class="card">
<slot name="name"></slot>
<slot name="description"></slot>
<slot name="role"></slot>
</div>
`;
}
});
</script>
通過在外部定義css,修改插槽中的css,通過我們給出<slot></slot>
給出一個預設資訊
::sloted 偽類
connectedCallback() {
this.shadowRoot.innerHTML = `
<style>
::slotted(h2) { color: blue; }
</style>
<div class="card">
<slot name="name"></slot>
<slot name="description"></slot>
<slot name="role"></slot>
</div>
`;
}
會優先考慮全域性css,但是如果有!important
會考慮優先順序進行替換
正常情況下,全域性的css大於自身的
::slotted(h2) { color: blue; }
插槽的事件檢測
事件 | 描述 |
---|---|
slotchange |
當它檢測到插槽元素關聯已更改時,將觸發該事件。 |
們將像處理任何事件一樣使用.addEventListener()
該事件,使用有<slot>
問題的事件來監聽它並檢測它何時被觸發,並執行關聯的功能
const slot = this.shadowRoot.querySelector("slot");
slot.addEventListener("slotchange", () => console.log("¡El slot ha cambiado!"));
例子,能監控到變化
element.setAttribute('slot', slotName);
// element.assignedSlot = $slot
element.removeAttribute('slot');
// element.assignedSlot = null
提地寫了一個完整的demo,方便理解
<app-element>
<button onClick="add()">++</button>
<h1>xxxx</h1>
</app-element>
js部分
class AppElement extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"});
}
slot;
connectedCallback() {
// 新增到頁面上
this.shadowRoot.innerHTML = `<slot></slot>`;
// 查詢到slot,並且監控屬性的變化
this.slot = document.querySelector('app-element').shadowRoot.querySelector('slot');
this.slot.addEventListener('slotchange',e=>{
console.log('觸發');
})
}
}
customElements.define("app-element", AppElement)
// 點選的時候修改屬性
function add() {
let slot = document.querySelector('app-element').shadowRoot.querySelector('slot');
slot.setAttribute('name','333')
}