从原生web组件到框架组件源码(二)
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')
}
从原生web组件到框架组件源码(二)的更多相关文章
- Web前端三大框架_vue源码笔记
一.VUE 1.1 MVVM VUE也是基于MVVM模式实现的.特点就是数据双向绑定 在MVVM模式中,分成三个部分: M 模型 model V 视图 view VM 视图-模型 view-model ...
- DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render
DRF框架 全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...
- robotlegs2.0框架实例源码带注释
robotlegs2.0框架实例源码带注释 Robotlegs2的Starling扩展 有个老外写了robotleges2的starling扩展,地址是 https://github.com/brea ...
- 框架-springmvc源码分析(一)
框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...
- JUC同步器框架AbstractQueuedSynchronizer源码图文分析
JUC同步器框架AbstractQueuedSynchronizer源码图文分析 前提 Doug Lea大神在编写JUC(java.util.concurrent)包的时候引入了java.util.c ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(2)-easyui构建前端页面框架[附源码]
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(2)-easyui构建前端页面框架[附源码] 开始,我们有了一系列的解决方案,我们将动手搭建新系统吧. 用 ...
- 框架-springmvc源码分析(二)
框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...
- WEB前端开发学习:源码canvas 雪
WEB前端开发学习:源码canvas 雪 双旦节要到了,程序员们为了响应气氛,特别用代码制作了动态雪花,WEB前端开发学习的初学者们一起跟着案例做一遍吧! <!DOCTYPE html> ...
- 如何查看JDK以及JAVA框架的源码
如何查看JDK以及JAVA框架的源码 设置步骤如下: 1.点 “window”-> "Preferences" -> "Java" -> &q ...
- 高性能网络I/O框架-netmap源码分析
from:http://blog.chinaunix.net/uid-23629988-id-3594118.html 博主这篇文章写的很好 感觉很有借签意义 值得阅读 高性能网络I/O框架-netm ...
随机推荐
- Python-读写csv数据模块 csv
案例: 通过股票网站,我们获取了中国股市数据集,它以csv数据格式存储 Data,Open,High,Low,Close,Volume,Adj Close 2016-06-28,8.63,8.47,8 ...
- Webstorm破解版安装教程
Webstorm破解版: 安装包链接见:https://pan.baidu.com/s/1XJqRtM9C4M8AmH50S9dVDQ 提取码: dah3 内附安装教程, 原创文章,转载请先联系作者
- I2C 方式
转自:http://www.cnblogs.com/lucky-apple/archive/2008/07/03/1234581.html 区别: SPI:高速同步串行口.3-4线接口,收发独立.可同 ...
- farbic-sdk-java 学习部署
准备工作 1.fabric基础网络环境 2.环境准备(jdk环境.maven环境) 3.启动fabric测试网络 4.在idea中测试java-sdk 1.fabric环境准备 1.fabric基础环 ...
- RHSA-2017:2029-中危: openssh 安全和BUG修复更新(存在EXP、代码执行、本地提权)
[root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...
- Cypress系列(62)- 改造 PageObject 模式
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html PO 模式 PageObject(页面对 ...
- Mybatis老手复习文档
Mybatis学习笔记 再次学习Mybatis,日后,有时间会把这个文档更新,改的越来越好,然后,改成新手老手通用的文档 1.我的认识 Mybatis 是一个持久层框架,(之前 我虽然学了这个myba ...
- Jmeter请求之接口串联自动化测试(未完)
方案一:添加Cookie管理器,把用户的登录状态存在cookie管理器中,类似于浏览器 存储测试结果: 监听器->保存响应到文件,对结果进行存储 文件名前缀:保存到哪个地方前缀是什么D:\tes ...
- 【C语言入门学习笔记】如何把C语言程序变成可执行文件!
环境 在ANSI的任何一种实现中,存在两种不同的环境. 翻译环境:在这个环境里,源代码被转换为可执行的机器指令. 执行环境:用于实际执行代码. 翻译环境 组成一个程序的每个源文件通过编译过程分别转成目 ...
- 【UER #1】DZY Loves Graph
UOJ小清新题表 题目内容 UOJ链接 DZY开始有\(n\)个点,现在他对这\(n\)个点进行了\(m\)次操作,对于第\(i\)个操作(从\(1\)开始编号)有可能的三种情况: Add a b: ...