在Vue 3中使用Web Components可以通过多种方式实现。Web Components是一组允许你创建可重用、封装良好的自定义元素的标准技术。它们包括Custom Elements、Shadow DOM、HTML Templates等。
Vue3 支持原生模式,可以让单个文件的js,css,html以html为界限的局部环境中,不影响到全局,组件之间也不会相互影响。
封装原生的webcomponents,由三部分组成的。
1、Custom elements(自定义元素)
JavaScriptAPI,允许定义custom elements及其行为,然后可以在我们的用户界面中按照需要使用它们。
2、Shadow Dom(影子Dom)
JavaScriptAPI,用于将封装的“影子”DOM树附加到元素(与主文档DOM分开呈现)并控制其关联的功能。通过这种方式,开发者可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
3、HTML templates(Html模版)
和元素使开发者可以编写与HTML结构类似的组件和样式。然后它们可以作为自定义元素结构的基础被多次重用。
btn.js
class Btn extends HTMLElement{
constructor(){//初始化类的实例,必须调用父类构造函数。
super(); //在子类中用于调用父类的构造函数,确保父类的初始化逻辑正常执行。
//编写自己的功能
const shaDom = this.attachShadow({mode:"open"})
this.p = this.h('p') //相当于 this.p = document.createElement('p')
this.p.innerText = '绿曼巴'
this.p.setAttribute('style','width:200px; height:200px;border:1px solid black')
shaDom.appendChild(this.p)
}
h(el){
return document.createElement(el)
}
}
// 挂载
window.customElements.define('lmb-btn',Btn)
//有四个生命周期
//当自定义元素第一次被连接到文档 DOM 时被调用。
connectedCallback() {
console.log('我已经插入了')
}
//当自定义元素与文档 DOM 断开连接时被调用。
disconnectedCallback() {
console.log('我已经断开了')
}
//当自定义元素被移动到新文档时被调用
adoptedCallback() {
console.log('我被移动了')
}
//当自定义元素的一个属性被增加、移除或更改时被调用
attributeChangedCallback() {
console.log('我被改变了')
}
class Btn extends HTMLElement{
constructor(){//初始化类的实例,必须调用父类构造函数。
super(); //在子类中用于调用父类的构造函数,确保父类的初始化逻辑正常执行。
//编写自己的功能
const shaDom = this.attachShadow({mode:"open"})
this.template = this.h('template')
this.template.innerHTML = `
<!--
这里的样式只局限在这里使用,和外界隔离
-->
<style>
div{
width:200px;
height:200px;
border:1px solid black;
}
</style>
<div>绿曼巴1</div>
`
shaDom.appendChild(this.template.content.cloneNode(true))
}
h(el){
return document.createElement(el)
}
}
// 挂载
window.customElements.define('lmb-btn',Btn)
<lmb-btn></lmb-btn>
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue({
//----------------------------增加部分--------------------------------
template:{
compilerOptions:{
//去匹配lmb-开头的都会跳过组件的检测,把它识别成CustomElement
//要开启这个模式,只需要将你的组件文件以 .ce.vue 结尾即可
isCustomElement:(tag)=>tag.includes('lmb-')
}
}
//----------------------------增加部分结束-------------------------------
}),
vueJsx(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
建立文件:src/components/custom-vue.ce.vue
在App.vue 中
<template>
<div>
<!--传递参数 如果是对象需要JSON.stringify序列化-->
<lmb-btn :obj="JSON.stringify(obj)"></lmb-btn>
</div>
</template>
<script setup lang='ts'>
import { ref,reactive,defineCustomElement } from 'vue'
import customVueCe from './components/custom-vue.ce.vue';
/*
用于将 Vue 组件转换为自定义元素(Web Components),
从而能够在非 Vue 环境中使用。它让 Vue 组件直接注册为浏览器原生的自定义 HTML 元素,
使其可以在任何前端项目中以自定义标签的方式使用。
1、跨框架兼容性:转换后的自定义元素不依赖 Vue 框架,因此可以在各种框架中自由使用。
2、组件隔离:Web Components(自定义元素)具有 Shadow DOM 隔离特性,样式和功能不会影响页面中的其他元素,适合独立封装和复用。
3、数据传递和事件监听:转换后的组件仍然可以使用 props 和 emit 来接受数据和传递事件,适用于复杂交互的组件。
*/
const Btn = defineCustomElement(customVueCe)
//注册自定义元素
window.customElements.define('lmb-btn',Btn)
const obj = {name:"zhangsan"}
</script>
<template>
<div>lvmanba {{obj}}</div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
defineProps<{
obj:any
}>()
</script>
传递的参数,会自动添加到标签上。