您的当前位置:首页正文

Vue学习记录之二十五 Vue3中Web Componets的使用

2024-11-01 来源:个人技术集锦

一、webcomponets介绍

在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结构类似的组件和样式。然后它们可以作为自定义元素结构的基础被多次重用。

二、原生webcomponets开发实例

编辑组件

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('我被改变了')
    }

第二种用法 使用template模版

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>

三、在vue3中使用原生组件

1、在vite.config.ts 进行配置

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))
    }
  }
})

2、创建并引入组件

建立文件: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>

3、custom-vue.ce.vue(自定义元素必须以.ce.vue结尾)

<template>
    <div>lvmanba {{obj}}</div>
</template>
<script setup lang='ts'>
import { ref,reactive } from 'vue'
defineProps<{
    obj:any
}>()
</script>

传递的参数,会自动添加到标签上。

显示全文