当前位置:网站首页>Web Components
Web Components
2022-07-05 10:21:00 【码小龙.】
Web Components
介绍
谷歌公司掌握了Chrome浏览器, 所以一直在推动浏览器的原生组件, 也就是Web Components API
相比于第三方框架, 原生组件简单直接, 不用加载任何外部模块, 代码量小
允许创建可重用的定制元素, 并且在我们的web应用中直接使用它们
核心技术组成
Custom elements 自定义元素
一组JavaScript API, 允许定义custom elements及其行为, 然后在用户界面中按照需要使用它们
Shadow DOM 影子DOM
一组JavaScript API, 用于将封装的影子DOM树附加到元素(与主文档DOM分开呈现), 并控制其关联功能
通过这种方式, 我们可以保持元素的功能私有, 这样它们就可以被脚本化和样式化, 而不用担心与文档的其它部分发生冲突
HTML template html模板
和元素使你可以编写不在呈现页面中显示的标记模板, 然后它们可以作为自定义元素结构的基础被多次重用
生命周期函数
connectedCallback
当自定义元素第一次被连接到文档DOM时被调用
disconnectedCallback
当自定义元素与文档DOM断开连接时被调用
adoptedCallback
当自定义元素被移动到新文档时被调用
attributeChangedCallback
当自定义元素的第一个属性被增加、移除或更改时被调用
实例开发
实例1:日期组件
01.png
目录结构
|-scripts
|–date.time.js
|-index.html
开发日期组件
(() => {
// 创建模板
const template = document.createElement(‘template’)
// 标签元素里面包含了我们组件里面的具体样式和DOM
template.innerHTML = `
`
// 创建自定义datetime组件类DateTime, 只要继承HTMLElement类就可以编写自定义标签/元素
class DateTime extends HTMLElement {
/**
* constructor 生命周期函数
* @description 元素创建了, 但是没有添加到页面
* @description 一般来说需要在constructor中创建初始化状态, 事件监听和创建影子DOM
*/
constructor () {
// 调用super方法, 需要使用它来调用父级的构造方法
super()
/**
* attachShadow 影子DOM
* @param open 允许外界访问
* @param closed 关闭外界获取的途径
*/
this.attachShadow({ mode: ‘open’ })
/**
* shadowRoot 影子DOM的根节点
* @description template.content 是一个游离的文档碎片
* @description cloneNode(params) params -> boolean [true|false]
* true -> 深度遍历克隆
*/
this.shadowRoot.appendChild(template.content.cloneNode(true))
}
// 初始化时间
initDateTime () {
// 获取当前的时间对象
let date = new Date()
// 创建英文月份枚举数组
let month = [‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’, ‘December’]
// 封装配置需要使用的年月日
let dateConfig = {
date: date.getDate() >= 10 ? date.getDate() : ‘0’ + date.getDate(),
month: month[date.getMonth()],
year: date.getFullYear()
}
// console.log(dateConfig)
// datetime内容渲染显示
this.shadowRoot.querySelector(‘.datetime-box__wrap–day’).innerText = dateConfig.date
this.shadowRoot.querySelector(‘.datetime-box__wrap–month’).innerText = dateConfig.month
this.shadowRoot.querySelector(‘.datetime-box__wrap–year’).innerText = dateConfig.year
}
/**
* connectedCallback 生命周期函数
* @description 当自定义元素第一次被连接到文档DOM时被调用
* @description 元素被插入DOM的时候执行, 一般来说用来获取数据, 设置默认的显示样式或者内容
*/
connectedCallback () {
this.initDateTime()
}
}
/**
* 全局注册组件
* @description 把组件类挂载到DOM上去, 自定义标签名使用我们的组件
*/
window.customElements.define(‘date-time’, DateTime)
})()
页面引用
实例2:列表(详情)组件
02.png
目录结构
|-images
|-scripts
|–article-info.js
|–article-info-detail.js
|–article-data.js
|–script.js
|-index.html
html结构
-
- Comment
-
-
- *
-
`
class ArticleInfo extends HTMLElement {
constructor () {
super()
this.attachShadow({ mode: ‘open’ })
this.shadowRoot.appendChild(template.content.cloneNode(true))
this.initEvent()
}
/**
* 初始化事件
* @description 使用CustomEvent定义自定义事件
*/
initEvent () {
const cardInfo = this.$(‘.card-info’)
cardInfo.addEventListener(‘click’, (ev) => {
let myEventInfo = new CustomEvent(‘card-click’, {
composed: true,
bubbles: true
})
this.dispatchEvent(myEventInfo)
})
}
$(selector) {
return this.shadowRoot.querySelector(selector)
}
initRender () {
this.KaTeX parse error: Expected group after '_' at position 13: ('.card-info_̲_cover--image')…(‘.card-info__cover–title’).innerText = this.getAttribute(‘theme’)
this.KaTeX parse error: Expected group after '_' at position 13: ('.card-info_̲_avatar').src =…(‘.card-info__author’).innerText = this.getAttribute(‘author’)
this.$(‘.card-info__title’).innerText = this.getAttribute(‘title’)
}
connectedCallback () {
this.initRender()
}
}
window.customElements.define(‘arcitle-info’, ArticleInfo)
})()
开发详情组件
(() => {
const template = document.createElement(‘template’)
template.innerHTML = <img class="cover" src=""/> <span class="theme"></span> <img class="avatar" src=""/> <span class="author"></span> <span class="title"></span> <span class="comments"></span> <span class="likes"></span> <span class="shares"></span> <p class="p"></p> <button class="back">Back</button>
class ArticleInfoDetail extends HTMLElement {
constructor () {
super()
this.attachShadow({ mode: ‘open’ })
this.shadowRoot.appendChild(template.content.cloneNode(true))
this.initEvent()
}
initEvent () {
const backBtn = this.$(‘.back’)
backBtn.addEventListener(‘click’, (ev) => {
let myEvent = new CustomEvent(‘card-back-click’, {
composed: true,
bubbles: true
})
this.dispatchEvent(myEvent)
})
}
$(selector) {
return this.shadowRoot.querySelector(selector)
}
initRender () {
this. ( ′ . c o v e r ′ ) . s r c = t h i s . g e t A t t r i b u t e ( ′ c o v e r ′ ) t h i s . ('.cover').src = this.getAttribute('cover') this. (′.cover′).src=this.getAttribute(′cover′)this.(‘.theme’).innerText = this.getAttribute(‘theme’)
this. ( ′ . a v a t a r ′ ) . s r c = t h i s . g e t A t t r i b u t e ( ′ a v a t a r ′ ) t h i s . ('.avatar').src = this.getAttribute('avatar') this. (′.avatar′).src=this.getAttribute(′avatar′)this.(‘.author’).innerText = this.getAttribute(‘author’)
this. ( ′ . t i t l e ′ ) . i n n e r T e x t = t h i s . g e t A t t r i b u t e ( ′ t i t l e ′ ) t h i s . ('.title').innerText = this.getAttribute('title') this. (′.title′).innerText=this.getAttribute(′title′)this.(‘.comments’).innerText = this.getAttribute(‘comments’)
this. ( ′ . l i k e s ′ ) . i n n e r T e x t = t h i s . g e t A t t r i b u t e ( ′ l i k e s ′ ) t h i s . ('.likes').innerText = this.getAttribute('likes') this. (′.likes′).innerText=this.getAttribute(′likes′)this.(‘.shares’).innerText = this.getAttribute(‘shares’)
this.$(‘.p’).innerText = this.getAttribute(‘p’)
}
connectedCallback () {
this.initRender()
}
/**
* attributeChangedCallback生命周期函数
* @param name
* @param oldValue
* @param newValue
* @description 当自定义元素的第一个属性被增加、移除或更改时被调用
*/
attributeChangedCallback (name, oldValue, newValue) {
// console.log(name, oldValue, newValue)
this.initRender()
}
// 监听属性的变化 - 返回的每一个属性名对应的属性值发生变化, 都会触发对应的attributeChangedCallback方法
static get observedAttributes () {
return [‘id’, ‘cover’, ‘theme’, ‘avatar’, ‘author’, ‘title’, ‘comments’, ‘likes’, ‘shares’, ‘p’]
}
}
window.customElements.define(‘arcitle-info-detail’, ArticleInfoDetail)
})()
scripts.js
(() => {
let container = document.querySelector(‘.container’)
let str = ‘’
// 遍历获取所有的文章信息
cardData.forEach(item => {
str += <arcitle-info id="${item.id}" cover="${item.cover}" theme="${item.theme}" avatar="${item.avatar}" author="${item.author}" title="${item.title}"> <span slot="comments">${item.comments}</span> <span slot="likes">${item.likes}</span> <span slot="shares">${item.shares}</span> </arcitle-info>
})
// append到container中
container.innerHTML = str
document.body.addEventListener(‘card-click’, (ev) => {
let id = ev.target.id
let detailWrap = document.querySelector(‘.container-detail-wrap’)
let cardDetail = document.querySelector(‘arcitle-info-detail’)
// get arcitle data from id
let articleSelectData = cardData.filter(v => v.id === id)[0]
Object.keys(articleSelectData).forEach(key => {
cardDetail.setAttribute(key, articleSelectData[key])
})
// 动画显示文章详情页
detailWrap.style.left = 0;
detailWrap.style.opacity = 1;
})
document.body.addEventListener(‘card-back-click’, (ev) => {
let detailWrap = document.querySelector(‘.container-detail-wrap’)
// 动画显示文章详情页
detailWrap.style.left = ‘100%’;
detailWrap.style.opacity = 0;
})
})()
边栏推荐
- Completion report of communication software development and Application
- Have you learned to make money in Dingding, enterprise micro and Feishu?
- 2022年化工自动化控制仪表考试试题及在线模拟考试
- Node の MongoDB Driver
- 字符串、、
- Learning note 4 -- Key Technologies of high-precision map (Part 2)
- [paper reading] kgat: knowledge graph attention network for recommendation
- Golang应用专题 - channel
- 微信小程序触底加载与下拉刷新的实现
- 伪类元素--before和after
猜你喜欢
What is the origin of the domain knowledge network that drives the new idea of manufacturing industry upgrading?
Ad20 make logo
[observation] with the rise of the "independent station" model of cross-border e-commerce, how to seize the next dividend explosion era?
How to write high-quality code?
2022年危险化学品经营单位主要负责人特种作业证考试题库及答案
How to judge that the thread pool has completed all tasks?
Workmanager learning 1
"Everyday Mathematics" serial 58: February 27
ModuleNotFoundError: No module named ‘scrapy‘ 终极解决方式
[dark horse morning post] Luo Yonghao responded to ridicule Oriental selection; Dong Qing's husband Mi Chunlei was executed for more than 700million; Geely officially acquired Meizu; Huawei releases M
随机推荐
微信核酸检测预约小程序系统毕业设计毕设(7)中期检查报告
Secteur non technique, comment participer à devops?
Customize the left sliding button in the line in the applet, which is similar to the QQ and Wx message interface
How to write high-quality code?
5G NR系统架构
SLAM 01.人类识别环境&路径的模型建立
SqlServer定时备份数据库和定时杀死数据库死锁解决
Glide conclusion
Redis如何实现多可用区?
LSTM应用于MNIST数据集分类(与CNN做对比)
字符串、、
Have the bosses ever encountered such problems in the implementation of flinksql by Flink CDC mongdb?
2022年危险化学品生产单位安全生产管理人员特种作业证考试题库模拟考试平台操作
变量///
Lepton 无损压缩原理及性能分析
Idea create a new sprintboot project
WorkManager学习一
【SWT组件】内容滚动组件 ScrolledComposite
Flink CDC cannot monitor MySQL logs. Have you ever encountered this problem?
Node の MongoDB Driver