Web Components 是一种使用原生的js、html、css创建自定义组件的技术。相比于其他组件化框架,比如 Vue、React等,它具有体积小、不用加载其他外部模块的优势。
class Btn extends HTMLElement {
constructor () {
super()
}
}
class Btn extends HTMLElement {
constructor () {
super()
// 使用 shadow Dom 将组件隔离,防止样式穿透
const shadowDom = this.attachShadow({ mode: "open" })
this.p = this.h('button')
this.p.innerText = '自定义按钮'
this.p.setAttribute('style', 'border: none; background-color: pink; height:30px;')
shadowDom.appendChild(this.p)
}
h(el) {
return document.createElement(el)
}
}
window.customElements.define('my-btn', Btn)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>webComponents</title>
<script src="./btn.js"></script>
</head>
<body>
<my-btn></my-btn>
</body>
</html>
如果觉得上面的写法比较麻烦,我们可以使用template来声明自定义组件:
class templateBtn extends HTMLElement {
constructor () {
super()
const shadowDom = this.attachShadow({ mode: "open" })
this.template = this.h('template')
this.template.innerHTML = `
<button>自定义template风格按钮</button>
<style>
button{
border: none;
background-color: khaki;
height: 30px;
margin: 5px;
border-radius: 6px;
}
</style>
`
shadowDom.appendChild(this.template.content.cloneNode(true))
}
h(el) {
return document.createElement(el)
}
}
window.customElements.define('temp-btn', templateBtn)
web components 定义的组件有以下几个生命周期钩子:
// webComponents 生命周期
// 挂载后
connectedCallback () {
console.log('挂载了');
}
// 断开后
disconnectedCallback () {
console.log('断开了');
}
// 被移动到新文档时
adoptedCallback () {
console.log('被移动了');
}
// 自定义元素的属性被增加、修改、删除时
attributeChangedCallback () {
console.log('属性改变了');
}
自定义组件可以像原生html元素那样使用 DOM attribute,由于 DOM attribute 只能为字符串类型的值,所以设置复杂类型的值时,需要使用 JSON.stringify() 将引用类型的值转为字符串,使用的时候再 JSON.parse() 转为引用类型。
<body>
<my-btn></my-btn>
<br>
<temp-btn a="123"></temp-btn>
<br>
<button>原生btn</button>
<script>
const tempBtn = document.getElementsByTagName('temp-btn')[0]
const a = {abc: 1}
tempBtn.setAttribute('obj', JSON.stringify(a))
const obj = tempBtn.getAttribute('obj')
console.log(JSON.parse(obj).abc); // 1
</script>
</body>
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag:any) => tag.includes('my-')
}
}
})
]
})
<template>
<button>
自定义按钮
</button>
</template>
<script setup lang='ts'>
const props = defineProps<{
obj: any
}>()
console.log(props.obj);
</script>
<style scoped>
button{
height: 30px;
background-color: skyblue;
border: 1px solid #ccc;
border-radius: 10px;
}
</style>
<template>
<div>
<my-btn :obj="obj"></my-btn>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, defineCustomElement} from 'vue'
import customVueCeVue from './components/custom-vue.ce.vue'
const Btn = defineCustomElement(customVueCeVue)
window.customElements.define('my-btn', Btn)
const obj = {name: '张三'}
</script>
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务