91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue3中如何使用defineCustomElement定義組件

發布時間:2022-10-31 09:55:56 來源:億速云 閱讀:425 作者:iii 欄目:開發技術

本篇內容主要講解“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 知曉特定元素應該被視為自定義元素并跳過組件解析,我們可以指定 compilerOptions.isCustomElement 這個選項,設置在此選項對象上的值將會在瀏覽器內進行模板編譯時使用,并會影響到所配置應用的所有組件。

    • 另外也可以通過 compilerOptions 選項在每個組件的基礎上覆蓋這些選項(針對當前組件有更高的優先級)。

    因為它是一個編譯時選項,構建工具需要將配置傳遞給 @vue/compiler-dom:

    • vue-loader:通過 compilerOptions loader 的選項傳遞。

    // vue.config.js
    module.exports = {
      chainWebpack: config => {
        config.module
          .rule('vue')
          .use('vue-loader')
          .tap(options => ({
            ...options,
            compilerOptions: {
              // 將所有帶 ion- 的標簽名都視為自定義元素
              isCustomElement: tag => tag.startsWith('ion-')
            }
          }))
      }
    }
    • vite:通過 @vitejs/plugin-vue 的選項傳遞。

    // vite.config.js
    import 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: [`/* css */`]
    })
    // 注冊自定義元素之后,所有此頁面中的 `<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' } },

    生命周期

    • 當該元素的 connectedCallback 初次調用時,一個 Vue 自定義元素會在內部掛載一個 Vue 組件實例到它的 ShadowRoot 上。

    • 當此元素的 disconnectedCallback 被調用時,Vue 會在一個微任務后檢查元素是否還留在文檔中。

      • 如果元素仍然在文檔中,那么說明它是一次移動操作,組件實例將被保留;

      • 如果該元素不再存在于文檔中,那么說明這是一次移除操作,組件實例將被銷毀。

    Props

    • 所有使用 props 選項聲明了的 props 都會作為屬性定義在該自定義元素上。Vue 會自動地、恰當地處理其作為 attribute 還是屬性的反射。

    • attribute 總是根據需要反射為相應的屬性類型。基礎類型的屬性值 (string,boolean 或 number) 會被反射為 attribute。

    • 當它們被設為 attribute 時 (永遠是字符串),Vue 也會自動將以 Boolean 或 Number 類型聲明的 prop 轉換為所期望的類型。比如下面這樣的 props 聲明:

    props: {
      selected: Boolean,
      index: Number
    }

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

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

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

    事件

    • emit 觸發的事件都會通過以 CustomEvents 的形式從自定義元素上派發。

    • 額外的事件參數 (payload) 將會被暴露為 CustomEvent 對象上的一個 detail 數組。

    插槽

    • 在一個組件中,插槽將會照常使用 渲染。然而,當使用最終的元素時,它只接受原生插槽的語法,而不支持作用域插槽。

    • 當傳遞具名插槽時,應使用 slot attribute 而不是 v-slot 指令:

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

    依賴注入

    • Provide / Inject API 和相應的組合式 API 在 Vue 定義的自定義元素中都可以正常工作。

    • 但是,依賴關系只在自定義元素之間起作用。例如一個 Vue 定義的自定義元素就無法注入一個由常規 Vue 組件所提供的屬性。

    將 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 提供類型推導的輔助函數。

    • 對于一個 ts 文件,如果我們直接寫 export default {},無法有針對性的提示 vue 組件里應該有哪些屬性。

    • 但是,增加一層 defineComponet 的話,export default defineComponent({}),就可以對參數進行一些類型推導和屬性的提示等操作。

    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定義組件”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    莱州市| 钟祥市| 平乡县| 简阳市| 蒙山县| 绥滨县| 合水县| 青田县| 山阴县| 婺源县| 新津县| 清徐县| 光山县| 邢台市| 大连市| 图们市| 马尔康县| 泗水县| 剑河县| 叶城县| 江门市| 白河县| 屯门区| 资阳市| 将乐县| 内黄县| 长汀县| 昌平区| 彭阳县| 贵港市| 依兰县| 扎囊县| 明溪县| 绥德县| 甘南县| 泸州市| 曲周县| 天等县| 卢龙县| 三明市| 罗定市|