web component 组件 跨技术思路

29 阅读1分钟

以vue3起始开发

创建SFC单文件index.ce.vue

<script setup lang="ts">
</script>
<template>
  <div class="header">
    <slot name="header">默认顶部插槽</slot>
  </div>
  <div class="body">
    <slot name="body">默认内容插槽</slot>
  </div>
</template>
<style lang="scss" scoped>
.header {
  background: red;
}

.body {
  background-color: yellow;
}
</style>

vue中使用

<script setup lang="ts">
import { register } from './index'
register('custom-radio')
</script>
<template>
  <custom-radio>
    <div slot="header">头部</div>
    <div slot="body">内容插槽</div>
  </custom-radio>
</template>
<style lang="scss" scoped>
</style>

index.html或者react 中使用该组件

  1. 创建index.ts
import { defineCustomElement } from 'vue';
import CustomRadio from './index.ce.vue';
const CustomRadioSFC = defineCustomElement(CustomRadio);
const register = (name: string = 'custom-radio') => {
    customElements.define(name, CustomRadioSFC)
    return CustomRadioSFC
}
export {
    register
}
  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'
import ElementPlus from 'unplugin-element-plus/vite'

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag: any) => tag.includes('custom-')
        }
      }
    }),
   ...
  ],
  resolve: {
    alias: {
      'vue': 'vue/dist/vue.esm-bundler.js',       // web components
      ...
    }
  },
  define: {
    'process.env': process.env
  },
  build: {
    lib: {
      entry: 'src/components/Custom-Radio/index.ts',
      formats: ['es'],
      fileName: () => 'custom-radio.js'
    }
  },
  ...
})

  1. rollup打包成custom-radio.js,执行npm run build
  2. 创建index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script type="module">
      import { register } from './custom-radio.js'
      register('custom-radio')
    </script>
  </head>
  <body>
    <custom-radio>
      <div slot="header">头部</div>
      <div slot="body">内容插槽</div>
    </custom-radio>
  </body>
</html>
  1. react中使用
...
const Index = (props) => {
  ...
  return (
    ...
        <custom-radio>
          <div slot="header">头部</div>
          <div slot="body">内容插槽</div>
        </custom-radio>
      ...
  );
};

export default Index;