文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Vue3中如何使用defineCustomElement定义组件

2023-07-04 11:52

关注

本篇内容主要讲解“Vue3中如何使用defineCustomElement定义组件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue3中如何使用defineCustomElement定义组件”吧!

使用 Vue 构建自定义元素

Web Components 是一组 web 原生 API 的统称,允许开发者创建可复用的自定义元素 (custom elements)。

自定义元素的主要好处是,它们可以在使用任何框架,甚至是在不使用框架的场景下使用。当你面向的最终用户可能使用了不同的前端技术栈,或是当你希望将最终的应用与它使用的组件实现细节解耦时,它们会是理想的选择。

Vue 和 Web Components 是互补的技术,Vue 为使用和创建自定义元素提供了出色的支持。你可以将自定义元素集成到现有的 Vue 应用中,或使用 Vue 来构建和分发自定义元素。

Vue 在 Custom Elements Everywhere 测试中取得了 100% 的分数。在 Vue 应用中使用自定义元素基本上与使用原生 HTML 元素的效果相同,但需要进行一些额外的配置才能工作:

跳过组件解析

默认情况下,Vue 会将任何非原生的 HTML 标签优先当作 Vue 组件处理,而将“渲染一个自定义元素”作为后备选项。这会在开发时导致 Vue 抛出一个“解析组件失败”的警告。

因为它是一个编译时选项,构建工具需要将配置传递给 @vue/compiler-dom:

// vue.config.jsmodule.exports = {  chainWebpack: config => {    config.module      .rule('vue')      .use('vue-loader')      .tap(options => ({        ...options,        compilerOptions: {          // 将所有带 ion- 的标签名都视为自定义元素          isCustomElement: tag => tag.startsWith('ion-')        }      }))  }}
// vite.config.jsimport vue from '@vitejs/plugin-vue'export default {  plugins: [    vue({      template: {        compilerOptions: {          // 将所有带短横线的标签名都视为自定义元素          isCustomElement: (tag) => tag.includes('-')        }      }    })  ]}
// src/main.js// 仅在浏览器内编译时才会工作const app = createApp(App)app.config.compilerOptions.isCustomElement = (tag) => tag.includes('-')

传递 DOM 属性

由于 DOM attribute 只能为字符串值,因此我们只能使用 DOM 对象的属性来传递复杂数据。当为自定义元素设置 props 时,Vue 3 将通过 in 操作符自动检查该属性是否已经存在于 DOM 对象上,并且在这个 key 存在时,更倾向于将值设置为一个 DOM 对象的属性。这意味着,在大多数情况下,如果自定义元素遵循推荐的最佳实践,你就不需要考虑这个问题。

然而,也会有一些特别的情况:必须将数据以一个 DOM 对象属性的方式传递,但该自定义元素无法正确地定义/反射这个属性 (因为 in 检查失败)。在这种情况下,你可以强制使用一个 v-bind 绑定、通过 .prop 修饰符来设置该 DOM 对象的属性:

<my-element :user.prop="{ name: 'jack' }"></my-element><!-- 等价简写 --><my-element .user="{ name: 'jack' }"></my-element>

defineCustomElement()

Vue 提供了一个和定义一般 Vue 组件几乎完全一致的 defineCustomElement 方法来支持创建自定义元素。这个方法接收的参数和 defineComponent 完全相同。但它会返回一个继承自 HTMLElement 的原生自定义元素类的构造器(可以通过 customElements.define() 注册)。

function defineCustomElement(  component:    | (ComponentOptions & { styles?: string[] })    | ComponentOptions['setup']): {  new (props?: object): HTMLElement}

除了常规的组件选项,defineCustomElement() 还支持一个特别的选项 styles,它是一个内联 CSS 字符串的数组,所提供的 CSS 会被注入到该元素的 ShadowRoot 上。

<my-vue-element></my-vue-element>
import { defineCustomElement } from 'vue'const MyVueElement = defineCustomElement({  // 这里是同平常一样的 Vue 组件选项  props: {},  emits: {},  template: `...`,  // defineCustomElement 特有的:注入进 ShadowRoot 的 CSS  styles: [``]})// 注册自定义元素之后,所有此页面中的 `<my-vue-element>` 标签都会被升级customElements.define('my-vue-element', MyVueElement)// 也可以在注册之后实例化元素:document.body.appendChild(  new MyVueElement({    // 初始化 props(可选)  }))

如果这时控制台报错:\color{red}{如果这时控制台报错:}如果这时控制台报错:Component provided template option but runtime compilation is not supported,在 vite.config.js 中添加以下配置:

resolve: { alias: { 'vue': 'vue/dist/vue.esm-bundler.js' } },

生命周期

Props

props: {  selected: Boolean,  index: Number}

并以下面这样的方式使用自定义元素:

<my-element selected index="1"></my-element>

在组件中,selected 会被转换为 true (boolean 类型值) 而 index 会被转换为 1 (number 类型值)。

事件

插槽

<my-element>  <div slot="named">hello</div></my-element>

依赖注入

将 SFC 编译为自定义元素

defineCustomElement 也可以搭配 Vue 单文件组件 (SFC) 使用。但是,根据默认的工具链配置,SFC 中的 <style> 在生产环境构建时仍然会被抽取和合并到一个单独的 CSS 文件中。当正在使用 SFC 编写自定义元素时,通常需要改为注入 <style> 标签到自定义元素的 ShadowRoot 上。

官方的 SFC 工具链支持以“自定义元素模式”导入 SFC (需要 @vitejs/plugin-vue@^1.4.0 或 vue-loader@^16.5.0)。一个以自定义元素模式加载的 SFC 将会内联其 <style> 标签为 CSS 字符串,并将其暴露为组件的 styles 选项。这会被 defineCustomElement 提取使用,并在初始化时注入到元素的 ShadowRoot 上。

要开启这个模式,将组件文件以 .ce.vue 结尾即可:

// Example.ce.vue<template>  <h2>Example.ce</h2></template><script></script><style>  h2 {    color: red;  }</style>
import { defineCustomElement } from 'vue'import Example from './Example.ce.vue'console.log(Example.styles)// 转换为自定义元素构造器const ExampleElement = defineCustomElement(Example)// 注册customElements.define('my-example', ExampleElement)

基于 Vue 构建自定义元素库

按元素分别导出构造函数,以便用户可以灵活地按需导入它们,还可以通过导出一个函数来方便用户自动注册所有元素。

// Vue 自定义元素库的入口文件import { defineCustomElement } from 'vue'import Foo from './MyFoo.ce.vue'import Bar from './MyBar.ce.vue'const MyFoo = defineCustomElement(Foo)const MyBar = defineCustomElement(Bar)// 分别导出元素export { MyFoo, MyBar }export function register() {  customElements.define('my-foo', MyFoo)  customElements.define('my-bar', MyBar)}

defineComponent()

用来在定义 Vue 组件时为 TypeScript 提供类型推导的辅助函数。

function defineComponent(  component: ComponentOptions | ComponentOptions['setup']): ComponentConstructor

参数是一个组件选项对象。返回值将是该选项对象本身,因为该函数实际上在运行时没有任何操作,仅用于提供类型推导,注意返回值的类型有一点特别:它是一个构造函数类型,它是根据选项推断出的组件实例类型。这是为了能让该返回值在 TSX 中用作标签时提供类型推导支持。

你可以像这样从 defineComponent() 的返回类型中提取出一个组件的实例类型 (与其选项中的 this 的类型等价):

const Foo = defineComponent()type FooInstance = InstanceType<typeof Foo>

defineAsyncComponent()

用来定义一个异步组件。在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。defineAsyncComponent 在运行时是懒加载的,参数可以是一个返回 Promise 的异步加载函数(resolve 回调方法应该在从服务器获得组件定义时调用),或是对加载行为进行更具体定制的一个选项对象。

import { defineAsyncComponent } from 'vue'const AsyncComp = defineAsyncComponent(() => {  return new Promise((resolve, reject) => {    // ...从服务器获取组件    resolve()  })})// ... 像使用其他一般组件一样使用 `AsyncComp`// 也可以使用 ES 模块动态导入const AsyncComp = defineAsyncComponent(() =>  import('./components/MyComponent.vue'))

得到的 AsyncComp 是一个外层包装过的组件,仅在页面需要它渲染时才会调用加载内部实际组件的函数。它会将接收到的 props 和插槽传给内部组件,所以你可以使用这个异步的包装组件无缝地替换原始组件,同时实现延迟加载。

与普通组件一样,异步组件可以使用 app.component() 全局注册:

app.component('MyComponent', defineAsyncComponent(() =>  import('./components/MyComponent.vue')))

也可以直接在父组件中直接定义它们:

<script setup>import { defineAsyncComponent } from 'vue'const AdminPage = defineAsyncComponent(() =>  import('./components/AdminPageComponent.vue'))</script><template>  <AdminPage /></template>

异步操作不可避免地会涉及到加载和错误状态,因此 defineAsyncComponent() 也支持在高级选项中处理这些状态:

const AsyncComp = defineAsyncComponent({  // 加载函数  loader: () => import('./Foo.vue'),  // 加载异步组件时使用的组件  loadingComponent: LoadingComponent,  // 展示加载组件前的延迟时间,默认为 200ms  delay: 200,  // 加载失败后展示的组件  errorComponent: ErrorComponent,  // 如果提供了一个时间限制,并超时了,也会显示这里配置的报错组件,默认值是:Infinity  timeout: 3000})

到此,相信大家对“Vue3中如何使用defineCustomElement定义组件”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯