会在dom中加入一个#shadow-root(open)进行css之间的隔离,里面的样式不会影响到外面,微前端样式隔离用到的就是这个
原声web componts 写法
<!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>Document</title>
<script src="./btns.js"></script>
</head>
<body>
<yx-btn></yx-btn>
</body>
</html>
- 需要用到得btns.js 文件, 也是写隔离shadowDom得地方
class Btns extends HTMLElement {
constructor(){
super()
const shadowDom = this.attachShadow({mode:'open'})
this.p = this.h('p')
this.p.innerText = 'yx'
this.p.setAttribute('style','width:100px;height:100px;color:red;border:1px solid #CCC')
shadowDom.appendChild(this.p)
}
h (el){
return document.createElement(el)
}
}
window.customElements.define('yx-btn',Btns)
- Btns.js中 写template 文本方式, template需要通过获取content方式渲染数据
class Btns extends HTMLElement {
constructor(){
super()
const shadowDom = this.attachShadow({mode:'open'})
this.template = this.h('template')
this.template.innerHTML = `
<style>
div{
width:100px;
height:100px;
border:1px solid #CCC;
}
</style>
<div>this is a test</div>
`
shadowDom.appendChild(this.template.content.cloneNode(true))
}
h (el){
return document.createElement(el)
}
}
window.customElements.define('yx-btn',Btns)
结合vue 使用
plugins: [
vue({
template:{
compilerOptions:{
isCustomElement: (tag:any)=> tag.includes('yx-')
}
}
})
]
- vue中web component 的文件命名需是****.ce.vue结尾。 此文件命名为custom-vue.ce.vue
<template>
<div>web components</div>
</template>
<script setup lang='ts'>
const props = defineProps<{
obj:any
}>()
console.log(JSON.parse(props.obj))
</script>
- App.vue 引用自定义的web component
<template>
<yx-btn :obj="obj"></yx-btn>
</template>
<script setup lang="ts">
import { defineCustomElement } from 'vue'
import customVueCeVue from './custom-vue.ce.vue'
const Btn = defineCustomElement(customVueCeVue)
window.customElements.define('yx-btn',Btn)
const obj = JSON.stringify({name:12})
</script>