当前位置:网站首页>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;
})
})()
边栏推荐
- 九度 1480:最大上升子序列和(动态规划思想求最值)
- C function returns multiple value methods
- Livedata interview question bank and answers -- 7 consecutive questions in livedata interview~
- 2022年危险化学品经营单位主要负责人特种作业证考试题库及答案
- How did automated specification inspection software develop?
- 《通信软件开发与应用》课程结业报告
- mongoDB副本集
- WorkManager學習一
- flink cdc不能监听mysql日志,大家遇到过这个问题吧?
- Interview: how does the list duplicate according to the attributes of the object?
猜你喜欢
> Could not create task ‘:app:MyTest. main()‘. > SourceSet with name ‘main‘ not found. Problem repair
《天天数学》连载58:二月二十七日
2022年危险化学品经营单位主要负责人特种作业证考试题库及答案
2022年流动式起重机司机考试题库及模拟考试
非技術部門,如何參與 DevOps?
2022鹏城杯web
重磅:国产IDE发布,由阿里研发,完全开源!
[vite] 1371 - develop vite plug-ins by hand
【js学习笔记五十四】BFC方式
What is the origin of the domain knowledge network that drives the new idea of manufacturing industry upgrading?
随机推荐
Activity enter exit animation
LDAP概述
SLAM 01.人类识别环境&路径的模型建立
How did automated specification inspection software develop?
DDOS攻击原理,被ddos攻击的现象
各位大佬,我测试起了3条线程同时往3个mysql表中写入,每条线程分别写入100000条数据,用了f
微信小程序中,从一个页面跳转到另一个页面后,在返回后发现页面同步滚动了
想请教一下,十大券商有哪些?在线开户是安全么?
Today in history: the first e-book came out; The inventor of magnetic stripe card was born; The pioneer of handheld computer was born
Glide Mastery
Learning Note 6 - satellite positioning technology (Part 1)
伪类元素--before和after
Error: module not found: error: can't resolve 'xxx' in 'XXXX‘
《通信软件开发与应用》课程结业报告
In wechat applet, after jumping from one page to another, I found that the page scrolled synchronously after returning
Interview: how does the list duplicate according to the attributes of the object?
[vite] 1371 - develop vite plug-ins by hand
Write double click event
@Jsonadapter annotation usage
2022年流动式起重机司机考试题库及模拟考试