vue3 中使用web components

发布于:2024-04-04 ⋅ 阅读:(146) ⋅ 点赞:(0)

会在dom中加入一个#shadow-root(open)进行css之间的隔离,里面的样式不会影响到外面,微前端样式隔离用到的就是这个

原声web componts 写法

  • index.html 文件
<!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 使用

  • 需在vite.config.ts 中进行配置
/* * */
plugins: [
    vue({
      template:{
        compilerOptions:{
        // 检测到包含yx-开头的组件,vue不进行校验,使用自身定义的web component
          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
}>()

// 传递的参数是object,因此需要转换
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'

// 使用vue 提供的defineCustomElement, 将其变成web component
const Btn = defineCustomElement(customVueCeVue)

window.customElements.define('yx-btn',Btn)

// 引用类型传参,需要使用JSON.stringify
const obj = JSON.stringify({name:12})

</script>


网站公告

今日签到

点亮在社区的每一天
去签到