欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3中使用defineCustomElement 定義組件詳解

 更新時(shí)間:2022年10月28日 17:04:22   作者:zkj  
這篇文章主要為大家介紹了Vue3中使用defineCustomElement 定義組件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

使用 Vue 構(gòu)建自定義元素

Web Components 是一組 web 原生 API 的統(tǒng)稱,允許開發(fā)者創(chuàng)建可復(fù)用的自定義元素 (custom elements)。

自定義元素的主要好處是,它們可以在使用任何框架,甚至是在不使用框架的場(chǎng)景下使用。當(dāng)你面向的最終用戶可能使用了不同的前端技術(shù)棧,或是當(dāng)你希望將最終的應(yīng)用與它使用的組件實(shí)現(xiàn)細(xì)節(jié)解耦時(shí),它們會(huì)是理想的選擇。

Vue 和 Web Components 是互補(bǔ)的技術(shù),Vue 為使用和創(chuàng)建自定義元素提供了出色的支持。你可以將自定義元素集成到現(xiàn)有的 Vue 應(yīng)用中,或使用 Vue 來構(gòu)建和分發(fā)自定義元素。

Vue 在 Custom Elements Everywhere 測(cè)試中取得了 100% 的分?jǐn)?shù)。在 Vue 應(yīng)用中使用自定義元素基本上與使用原生 HTML 元素的效果相同,但需要進(jìn)行一些額外的配置才能工作:

跳過組件解析

默認(rèn)情況下,Vue 會(huì)將任何非原生的 HTML 標(biāo)簽優(yōu)先當(dāng)作 Vue 組件處理,而將“渲染一個(gè)自定義元素”作為后備選項(xiàng)。這會(huì)在開發(fā)時(shí)導(dǎo)致 Vue 拋出一個(gè)“解析組件失敗”的警告。

  • 要讓 Vue 知曉特定元素應(yīng)該被視為自定義元素并跳過組件解析,我們可以指定 compilerOptions.isCustomElement 這個(gè)選項(xiàng),設(shè)置在此選項(xiàng)對(duì)象上的值將會(huì)在瀏覽器內(nèi)進(jìn)行模板編譯時(shí)使用,并會(huì)影響到所配置應(yīng)用的所有組件。
  • 另外也可以通過 compilerOptions 選項(xiàng)在每個(gè)組件的基礎(chǔ)上覆蓋這些選項(xiàng)(針對(duì)當(dāng)前組件有更高的優(yōu)先級(jí))。

因?yàn)樗且粋€(gè)編譯時(shí)選項(xiàng),構(gòu)建工具需要將配置傳遞給 @vue/compiler-dom:

  • vue-loader:通過 compilerOptions loader 的選項(xiàng)傳遞。
// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => ({
        ...options,
        compilerOptions: {
          // 將所有帶 ion- 的標(biāo)簽名都視為自定義元素
          isCustomElement: tag => tag.startsWith('ion-')
        }
      }))
  }
}
  • vite:通過 @vitejs/plugin-vue 的選項(xiàng)傳遞。
// vite.config.js
import vue from '@vitejs/plugin-vue'
export default {
  plugins: [
    vue({
      template: {
        compilerOptions: {
          // 將所有帶短橫線的標(biāo)簽名都視為自定義元素
          isCustomElement: (tag) => tag.includes('-')
        }
      }
    })
  ]
}
  • 瀏覽器內(nèi)編譯時(shí)的配置。
// src/main.js
// 僅在瀏覽器內(nèi)編譯時(shí)才會(huì)工作
const app = createApp(App)
app.config.compilerOptions.isCustomElement = (tag) => tag.includes('-')

傳遞 DOM 屬性

由于 DOM attribute 只能為字符串值,因此我們只能使用 DOM 對(duì)象的屬性來傳遞復(fù)雜數(shù)據(jù)。當(dāng)為自定義元素設(shè)置 props 時(shí),Vue 3 將通過 in 操作符自動(dòng)檢查該屬性是否已經(jīng)存在于 DOM 對(duì)象上,并且在這個(gè) key 存在時(shí),更傾向于將值設(shè)置為一個(gè) DOM 對(duì)象的屬性。這意味著,在大多數(shù)情況下,如果自定義元素遵循推薦的最佳實(shí)踐,你就不需要考慮這個(gè)問題。

然而,也會(huì)有一些特別的情況:必須將數(shù)據(jù)以一個(gè) DOM 對(duì)象屬性的方式傳遞,但該自定義元素?zé)o法正確地定義/反射這個(gè)屬性 (因?yàn)?nbsp;in 檢查失敗)。在這種情況下,你可以強(qiáng)制使用一個(gè) v-bind 綁定、通過 .prop 修飾符來設(shè)置該 DOM 對(duì)象的屬性:

<my-element :user.prop="{ name: 'jack' }"></my-element>
<!-- 等價(jià)簡(jiǎn)寫 -->
<my-element .user="{ name: 'jack' }"></my-element>

defineCustomElement()

Vue 提供了一個(gè)和定義一般 Vue 組件幾乎完全一致的 defineCustomElement 方法來支持創(chuàng)建自定義元素。這個(gè)方法接收的參數(shù)和 defineComponent 完全相同。但它會(huì)返回一個(gè)繼承自 HTMLElement 的原生自定義元素類的構(gòu)造器(可以通過 customElements.define() 注冊(cè))。

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

除了常規(guī)的組件選項(xiàng),defineCustomElement() 還支持一個(gè)特別的選項(xiàng) styles,它是一個(gè)內(nèi)聯(lián) CSS 字符串的數(shù)組,所提供的 CSS 會(huì)被注入到該元素的 ShadowRoot 上。

<my-vue-element></my-vue-element>
import { defineCustomElement } from 'vue'
const MyVueElement = defineCustomElement({
  // 這里是同平常一樣的 Vue 組件選項(xiàng)
  props: {},
  emits: {},
  template: `...`,
  // defineCustomElement 特有的:注入進(jìn) ShadowRoot 的 CSS
  styles: [`/* css */`]
})
// 注冊(cè)自定義元素之后,所有此頁面中的 `<my-vue-element>` 標(biāo)簽都會(huì)被升級(jí)
customElements.define('my-vue-element', MyVueElement)
// 也可以在注冊(cè)之后實(shí)例化元素:
document.body.appendChild(
  new MyVueElement({
    // 初始化 props(可選)
  })
)

如果這時(shí)控制臺(tái)報(bào)錯(cuò):\color{red}{如果這時(shí)控制臺(tái)報(bào)錯(cuò):}如果這時(shí)控制臺(tái)報(bào)錯(cuò):Component provided template option but runtime compilation is not supported,在 vite.config.js 中添加以下配置:

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

生命周期

  • 當(dāng)該元素的 connectedCallback 初次調(diào)用時(shí),一個(gè) Vue 自定義元素會(huì)在內(nèi)部掛載一個(gè) Vue 組件實(shí)例到它的 ShadowRoot 上。
  • 當(dāng)此元素的 disconnectedCallback 被調(diào)用時(shí),Vue 會(huì)在一個(gè)微任務(wù)后檢查元素是否還留在文檔中。
    • 如果元素仍然在文檔中,那么說明它是一次移動(dòng)操作,組件實(shí)例將被保留;
    • 如果該元素不再存在于文檔中,那么說明這是一次移除操作,組件實(shí)例將被銷毀。

Props

  • 所有使用 props 選項(xiàng)聲明了的 props 都會(huì)作為屬性定義在該自定義元素上。Vue 會(huì)自動(dòng)地、恰當(dāng)?shù)靥幚砥渥鳛?attribute 還是屬性的反射。
  • attribute 總是根據(jù)需要反射為相應(yīng)的屬性類型?;A(chǔ)類型的屬性值 (string,boolean 或 number) 會(huì)被反射為 attribute。
  • 當(dāng)它們被設(shè)為 attribute 時(shí) (永遠(yuǎn)是字符串),Vue 也會(huì)自動(dòng)將以 Boolean 或 Number 類型聲明的 prop 轉(zhuǎn)換為所期望的類型。比如下面這樣的 props 聲明:
props: {
  selected: Boolean,
  index: Number
}

并以下面這樣的方式使用自定義元素:

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

在組件中,selected 會(huì)被轉(zhuǎn)換為 true (boolean 類型值) 而 index 會(huì)被轉(zhuǎn)換為 1 (number 類型值)。

事件

  • emit 觸發(fā)的事件都會(huì)通過以 CustomEvents 的形式從自定義元素上派發(fā)。
  • 額外的事件參數(shù) (payload) 將會(huì)被暴露為 CustomEvent 對(duì)象上的一個(gè) detail 數(shù)組。

插槽

  • 在一個(gè)組件中,插槽將會(huì)照常使用 渲染。然而,當(dāng)使用最終的元素時(shí),它只接受原生插槽的語法,而不支持作用域插槽。
  • 當(dāng)傳遞具名插槽時(shí),應(yīng)使用 slot attribute 而不是 v-slot 指令:
<my-element>
  <div slot="named">hello</div>
</my-element>

依賴注入

  • Provide / Inject API 和相應(yīng)的組合式 API 在 Vue 定義的自定義元素中都可以正常工作。
  • 但是,依賴關(guān)系只在自定義元素之間起作用。例如一個(gè) Vue 定義的自定義元素就無法注入一個(gè)由常規(guī) Vue 組件所提供的屬性。

將 SFC 編譯為自定義元素

defineCustomElement 也可以搭配 Vue 單文件組件 (SFC) 使用。但是,根據(jù)默認(rèn)的工具鏈配置,SFC 中的 <style> 在生產(chǎn)環(huán)境構(gòu)建時(shí)仍然會(huì)被抽取和合并到一個(gè)單獨(dú)的 CSS 文件中。當(dāng)正在使用 SFC 編寫自定義元素時(shí),通常需要改為注入 <style> 標(biāo)簽到自定義元素的 ShadowRoot 上。

官方的 SFC 工具鏈支持以“自定義元素模式”導(dǎo)入 SFC (需要 @vitejs/plugin-vue@^1.4.0 或 vue-loader@^16.5.0)。一個(gè)以自定義元素模式加載的 SFC 將會(huì)內(nèi)聯(lián)其 <style> 標(biāo)簽為 CSS 字符串,并將其暴露為組件的 styles 選項(xiàng)。這會(huì)被 defineCustomElement 提取使用,并在初始化時(shí)注入到元素的 ShadowRoot 上。

要開啟這個(gè)模式,將組件文件以 .ce.vue 結(jié)尾即可:

// Example.ce.vue
<template>
  <h1>Example.ce</h1>
</template>
<script>
</script>
<style>
  h1 {
    color: red;
  }
</style>
import { defineCustomElement } from 'vue'
import Example from './Example.ce.vue'
console.log(Example.styles)
// 轉(zhuǎn)換為自定義元素構(gòu)造器
const ExampleElement = defineCustomElement(Example)
// 注冊(cè)
customElements.define('my-example', ExampleElement)

基于 Vue 構(gòu)建自定義元素庫

按元素分別導(dǎo)出構(gòu)造函數(shù),以便用戶可以靈活地按需導(dǎo)入它們,還可以通過導(dǎo)出一個(gè)函數(shù)來方便用戶自動(dòng)注冊(cè)所有元素。

// 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)
// 分別導(dǎo)出元素
export { MyFoo, MyBar }
export function register() {
  customElements.define('my-foo', MyFoo)
  customElements.define('my-bar', MyBar)
}

defineComponent()

用來在定義 Vue 組件時(shí)為 TypeScript 提供類型推導(dǎo)的輔助函數(shù)。

  • 對(duì)于一個(gè) ts 文件,如果我們直接寫 export default {},無法有針對(duì)性的提示 vue 組件里應(yīng)該有哪些屬性。
  • 但是,增加一層 defineComponet 的話,export default defineComponent({}),就可以對(duì)參數(shù)進(jìn)行一些類型推導(dǎo)和屬性的提示等操作。
function defineComponent(
  component: ComponentOptions | ComponentOptions['setup']
): ComponentConstructor

參數(shù)是一個(gè)組件選項(xiàng)對(duì)象。返回值將是該選項(xiàng)對(duì)象本身,因?yàn)樵摵瘮?shù)實(shí)際上在運(yùn)行時(shí)沒有任何操作,僅用于提供類型推導(dǎo),注意返回值的類型有一點(diǎn)特別:它是一個(gè)構(gòu)造函數(shù)類型,它是根據(jù)選項(xiàng)推斷出的組件實(shí)例類型。這是為了能讓該返回值在 TSX 中用作標(biāo)簽時(shí)提供類型推導(dǎo)支持。

你可以像這樣從 defineComponent() 的返回類型中提取出一個(gè)組件的實(shí)例類型 (與其選項(xiàng)中的 this 的類型等價(jià)):

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

defineAsyncComponent()

用來定義一個(gè)異步組件。在大型項(xiàng)目中,我們可能需要拆分應(yīng)用為更小的塊,并僅在需要時(shí)再從服務(wù)器加載相關(guān)組件。defineAsyncComponent 在運(yùn)行時(shí)是懶加載的,參數(shù)可以是一個(gè)返回 Promise 的異步加載函數(shù)(resolve 回調(diào)方法應(yīng)該在從服務(wù)器獲得組件定義時(shí)調(diào)用),或是對(duì)加載行為進(jìn)行更具體定制的一個(gè)選項(xiàng)對(duì)象。

import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() => {
  return new Promise((resolve, reject) => {
    // ...從服務(wù)器獲取組件
    resolve(/* 獲取到的組件 */)
  })
})
// ... 像使用其他一般組件一樣使用 `AsyncComp`
// 也可以使用 ES 模塊動(dòng)態(tài)導(dǎo)入
const AsyncComp = defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
)

得到的 AsyncComp 是一個(gè)外層包裝過的組件,僅在頁面需要它渲染時(shí)才會(huì)調(diào)用加載內(nèi)部實(shí)際組件的函數(shù)。它會(huì)將接收到的 props 和插槽傳給內(nèi)部組件,所以你可以使用這個(gè)異步的包裝組件無縫地替換原始組件,同時(shí)實(shí)現(xiàn)延遲加載。

與普通組件一樣,異步組件可以使用 app.component() 全局注冊(cè):

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>

異步操作不可避免地會(huì)涉及到加載和錯(cuò)誤狀態(tài),因此 defineAsyncComponent() 也支持在高級(jí)選項(xiàng)中處理這些狀態(tài):

const AsyncComp = defineAsyncComponent({
  // 加載函數(shù)
  loader: () => import('./Foo.vue'),
  // 加載異步組件時(shí)使用的組件
  loadingComponent: LoadingComponent,
  // 展示加載組件前的延遲時(shí)間,默認(rèn)為 200ms
  delay: 200,
  // 加載失敗后展示的組件
  errorComponent: ErrorComponent,
  // 如果提供了一個(gè)時(shí)間限制,并超時(shí)了,也會(huì)顯示這里配置的報(bào)錯(cuò)組件,默認(rèn)值是:Infinity
  timeout: 3000
})

以上就是Vue3中使用defineCustomElement 定義組件詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue3 defineCustomElement定義組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于Vue的SPA動(dòng)態(tài)修改頁面title的方法(推薦)

    基于Vue的SPA動(dòng)態(tài)修改頁面title的方法(推薦)

    這篇文章主要介紹了基于Vue的SPA動(dòng)態(tài)修改頁面title的方法,需要的朋友可以參考下
    2018-01-01
  • vue如何向后臺(tái)傳遞日期

    vue如何向后臺(tái)傳遞日期

    這篇文章主要介紹了vue如何向后臺(tái)傳遞日期,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Vue寫一個(gè)簡(jiǎn)單的倒計(jì)時(shí)按鈕功能

    Vue寫一個(gè)簡(jiǎn)單的倒計(jì)時(shí)按鈕功能

    這篇文章主要介紹了基于Vue寫一個(gè)簡(jiǎn)單的倒計(jì)時(shí)按鈕功能,在項(xiàng)目開發(fā)的過程,經(jīng)常會(huì)遇到發(fā)送驗(yàn)證碼,點(diǎn)擊之后有60秒倒計(jì)時(shí)的按鈕,今天小編就給大家分享實(shí)例代碼,需要的朋友參考下吧
    2018-04-04
  • vue.js實(shí)現(xiàn)二級(jí)菜單效果

    vue.js實(shí)現(xiàn)二級(jí)菜單效果

    這篇文章主要為大家詳細(xì)介紹了vue.js實(shí)現(xiàn)二級(jí)菜單效果的具體方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • 解決element-ui庫的el-row的gutter=10間距失效問題

    解決element-ui庫的el-row的gutter=10間距失效問題

    這篇文章主要介紹了解決element-ui庫的el-row的gutter=10間距失效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • vue對(duì)枚舉值轉(zhuǎn)換方式

    vue對(duì)枚舉值轉(zhuǎn)換方式

    這篇文章主要介紹了vue對(duì)枚舉值轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue.js指令和組件詳細(xì)介紹及實(shí)例

    vue.js指令和組件詳細(xì)介紹及實(shí)例

    這篇文章主要介紹了vue.js功能介紹 - 指令,組件詳細(xì)介紹及實(shí)例,詳細(xì)的介紹了指令和組件的用法,有興趣的可以了解一下。
    2017-04-04
  • Vue如何實(shí)現(xiàn)自動(dòng)觸發(fā)功能

    Vue如何實(shí)現(xiàn)自動(dòng)觸發(fā)功能

    這篇文章主要介紹了Vue如何實(shí)現(xiàn)自動(dòng)觸發(fā)功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • vue.js表單驗(yàn)證插件(vee-validate)的使用教程詳解

    vue.js表單驗(yàn)證插件(vee-validate)的使用教程詳解

    這篇文章主要介紹了vue.js表單驗(yàn)證插件(vee-validate)的使用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-05-05
  • vue el-row中ul間距問題

    vue el-row中ul間距問題

    這篇文章主要介紹了vue el-row中ul間距問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評(píng)論