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) 将代码插入htmlelement
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')
}

从原生web组件到框架组件源码(二)的更多相关文章

  1. Web前端三大框架_vue源码笔记

    一.VUE 1.1 MVVM VUE也是基于MVVM模式实现的.特点就是数据双向绑定 在MVVM模式中,分成三个部分: M 模型 model V 视图 view VM 视图-模型 view-model ...

  2. DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render

    DRF框架    全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...

  3. robotlegs2.0框架实例源码带注释

    robotlegs2.0框架实例源码带注释 Robotlegs2的Starling扩展 有个老外写了robotleges2的starling扩展,地址是 https://github.com/brea ...

  4. 框架-springmvc源码分析(一)

    框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...

  5. JUC同步器框架AbstractQueuedSynchronizer源码图文分析

    JUC同步器框架AbstractQueuedSynchronizer源码图文分析 前提 Doug Lea大神在编写JUC(java.util.concurrent)包的时候引入了java.util.c ...

  6. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(2)-easyui构建前端页面框架[附源码]

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(2)-easyui构建前端页面框架[附源码] 开始,我们有了一系列的解决方案,我们将动手搭建新系统吧. 用 ...

  7. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  8. WEB前端开发学习:源码canvas 雪

    WEB前端开发学习:源码canvas 雪 双旦节要到了,程序员们为了响应气氛,特别用代码制作了动态雪花,WEB前端开发学习的初学者们一起跟着案例做一遍吧! <!DOCTYPE html> ...

  9. 如何查看JDK以及JAVA框架的源码

    如何查看JDK以及JAVA框架的源码 设置步骤如下: 1.点 “window”-> "Preferences" -> "Java" -> &q ...

  10. 高性能网络I/O框架-netmap源码分析

    from:http://blog.chinaunix.net/uid-23629988-id-3594118.html 博主这篇文章写的很好 感觉很有借签意义 值得阅读 高性能网络I/O框架-netm ...

随机推荐

  1. PageObject课程培训记录

    前言 昨晚的培训课程讲了PO设计模式,对于PO模式我们需要去了解关于为什么要使用PO,而不使用PO是什么情况?什么是PO模式?PO怎么去使用? 第一,为什么要使用PO,而不使用PO是什么情况? 我们先 ...

  2. [JZOJ]2109 清兵线 题解

    ## [JZOJ]2109 清兵线 题解 **FIRST 题目大意** 给你一些正整数,这些正整数为数轴上若干个点代表的数.现求:假设从原点出发,走m以内(包括m)的距离最多能够访问多少个点,输出m- ...

  3. NMOS和PMOS区别

    在很多电路途中会出现NMOS和PMOS管,因为不是中文那么直接,都说管压降之类的,但其实它的导通很重要以及区别,关系到你点亮电子元件> 参考: 1.https://blog.csdn.net/l ...

  4. 南方IT比赛项目

    注意: 出现以下提示点击否就可以了 导入工作台: 导入模型 安装 安装到工作台上 修改模型位置 更新工具位置 点击是 改角度 九十度 添加组件 改一下名字,方便记忆 把工具移到组件 拆除后将工具移到S ...

  5. Zookeeper基础理论

    Zookeeper是分布式开源协调服务, 主要用来解决分布式集群中应用系统的一致性问题. 本质上是分布式小文件存储系统.   特性 全局数据一致性(集群中每个服务器保存一份相同的数据副本,Client ...

  6. 结合实体框架(代码优先)、工作单元测试、Web API、ASP. net等,以存储库设计模式开发示例项目。NET MVC 5和引导

    介绍 这篇文章将帮助你理解在库模式.实体框架.Web API.SQL Server 2012.ASP中的工作单元测试的帮助下设计一个项目.净MVC应用程序.我们正在开发一个图书实体和作者专用的样例图书 ...

  7. 3-kubernetes监控与日志管理

    监控集群资源利用率 metrics-server是一个集群范围的资源使用情况的数据聚合器,作为一个应用部署在集群中 metrics-server从每个节点上kubelet API收集指标,通过kube ...

  8. VBScript 教程

    VBScript 教程 VB 不区分大小写 变量 普通变量 关键词声明 Dim.Public.Private 赋值动态创建 name = "hello" Option Explic ...

  9. 多测师讲解接口测试__mock___高级讲师肖sir

    一.关于Mock测试 1.什么是Mock测试?mock测试,源自于英文单词fake,意为假的测试实际工作中用于模拟那些无法实时连接的后端,或是没有开发出来的后端,用于获得结果反馈的一种测试方式.通过发 ...

  10. ucore操作系统学习笔记(二) ucore lab2物理内存管理分析

    一.lab2物理内存管理介绍 操作系统的一个主要职责是管理硬件资源,并向应用程序提供具有良好抽象的接口来使用这些资源. 而内存作为重要的计算机硬件资源,也必然需要被操作系统统一的管理.最初没有操作系统 ...