如何分別在Angular、React、Preact、Vue和Svelte中使用Web元件? - netbasal
Web元件使我們能夠建立可重複使用的、可定製的元素。網路元件最大的優點是它的互操作性:由於瀏覽器原生支援,網路元件可以在任何HTML環境中使用,與任何框架一起使用,或者根本不使用框架。
網路元件的一個主要方面是封裝。你可以分離和隱藏標記結構、樣式和行為,這樣不同的頁面部分就不會發生衝突。
因此,網路元件是開發設計系統、可共享元件和嵌入式小工具的完美選擇。
讓我們來看看如何用行業內的頂級庫來使用本地Web元件。
使用 Lit 建立 Web 元件
使用純 Javascript 從頭開始構建 Web 元件很快就會變得一團糟,難以擴充套件和維護。
幸運的是,我們可以在Lit的幫助下構建快速、輕量級的 Web 元件。
Lit 的核心是一個消除樣板的元件基類,它提供反應狀態、作用域樣式和一個小巧、快速且富有表現力的宣告性模板系統。
讓我們構建一個最小的自定義select元素,看看我們如何處理原始和物件輸入值。
請注意,我們不會討論構建工具。你可以隨意使用任何你想要的東西。
讓我們從select元素開始:
import { css, html, LitElement } from 'lit'; export class SelectElement<T extends Record<string, unknown>> extends LitElement { static styles = css` button[active] { background-color: honeydew } ` @property({ type: Array }) data: T[] = []; @property({ attribute: 'id-key' }) idKey: keyof T = 'id' as keyof T; @property({ attribute: 'val-key' }) valKey: keyof T = 'label' as keyof T; @property({ state: true }) private activeItem: T | null = null; render() { return html`` } } customElements.define('ui-select', SelectElement); |
我們建立一個SelectElement元件,並定義三個輸入:data、idKey和valKey。
我們還定義了一個activeItem狀態來跟蹤當前選定的專案。
繼續加入方法功能:
import { css, html, LitElement } from 'lit'; import { repeat } from 'lit/directives/repeat.js'; export class SelectElement extends LitElement { ... selectItem(item: T) { this.activeItem = item; const event = new CustomEvent<T>('select-item', { detail: item, bubbles: true, composed: true }); this.dispatchEvent(event); } render() { return html` <p>Active: ${this.activeItem ? this.activeItem[this.valKey] : 'None' }</p> ${repeat( this.data, current => current[this.idKey], current => html` <button ?active=${this.activeItem?.[this.idKey] === current[this.idKey]} @click=${() => this.selectItem(current)}> ${current[this.valKey]} </button> `)} ` } } customElements.define('ui-select', SelectElement); |
我們加入第三方庫中的repeat指令來有效地渲染我們的元素, 它接收三個引數
- 一個collection:
- 一個keyFunction(將單個專案作為引數並返回其唯一的鍵),
- 以及一個itemTemplate(將專案和其當前索引作為引數並返回TemplateResult)。
點選一個專案會將其設定為活動專案,並派發一個自定義的事件,父級可以監聽。
我們使用Lit的一個很好的功能,叫做布林屬性表示式。活動屬性將根據表示式的結果被新增或刪除。我們用它來設計活動元素。
如果你正在尋找一個lit檔案生成器,你可能會發現這個庫很有用。
在Angular中使用Web元件
首先,我們需要使用CUSTOM_ELEMENTS_SCHEMA模式。Angular會忽略它不認識的自定義元素(用破折號命名),而不是丟擲一個錯誤。
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { TodosComponent } from './todos.component'; @NgModule({ declarations: [TodosComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class TodosModule {} |
現在我們可以在TodosComponent元件內使用我們的ui-select網路元件。
import '@org/ui/lib/select'; import { Component } from '@angular/core'; import { Todo, randTodo } from '@ngneat/falso'; @Component({ selector: 'app-todos', template: ` <button (click)="replace()">Replace</button> <ui-select [data]="todos" (select-item)="onSelect($event)" val-key="title"> </ui-select> ` }) export class TodosComponent { todos: Todo[] = randTodo({ length: 3 }); replace() { this.todos = randTodo({ length: 3 }); } onSelect(e: CustomEvent<Todo>) { console.log(e.detail); } } |
我們需要做的不多。Angular與自定義元素的整合是開箱即用的。
- 它將todos元件屬性與ui-select元素的資料屬性繫結。
- 事件繫結監聽select-item 事件,並在它被觸發時呼叫元件的onSelectItem()方法。
在Vue中使用Web元件
和Angular一樣,我們需要告訴Vue忽略自定義元素,這樣它在遇到自定義元素時就不會出現錯誤。下面是我們如何在Vite中做到這一點。
// vite.config.js import vue from '@vitejs/plugin-vue' export default { plugins: [ vue({ template: { compilerOptions: { // treat all tags with a dash as custom elements isCustomElement: (tag) => tag.includes('-') } } }) ] } |
現在我們可以在我們的元件中使用我們的自定義元素。
<script setup lang="ts"> import { ref } from 'vue'; import '@org/ui/lib/select'; import { randTodo } from '@ngneat/falso'; const todos = ref(randTodo({ length: 3} )) function replace() { todos.value = randTodo( {length: 3}) } function onSelect(event: CustomEvent<Todo>) { console.log(event.detail) } </script> <template> <button @click="replace">Replace</button> <ui-select :data="todos" @select-item="onSelect" val-key="title"></ui-select> </template> |
Vue讓使用自定義元素變得輕而易舉。
我們將該元素的資料屬性與todos ref繫結,並監聽select-item事件,當它被觸發時,執行onSelect函式。
在Svelte中使用Web元件
要在Svelte元件中使用自定義元素,我們不需要做任何特別的事情。匯入自定義元素並使用它。
<script lang="ts"> import '@org/ui/lib/select'; import { Todo, randTodo } from '@ngneat/falso'; let todos: Array<Todo> = randTodo({ length: 3 }); function replace() { todos = randTodo({ length: 3 }); } function onSelect(e: CustomEvent<Todo>) { console.log(e.detail); } </script> <main> <button on:click={replace}>Replace</button> <ui-select data={todos} val-key="title" on:select-item={onSelect} /> </main> |
在React中使用Web元件
React對自定義元素的支援是最不友好的。讓我們看看我們如何用React來使用它。
import '@org/ui/lib/select'; import { randTodo, Todo } from '@ngneat/falso'; import { SelectElement } from '@org/ui/lib/select'; import { useEffect, useRef, useState } from 'react'; export function Todos() { const [todos, setTodos] = useState<Todo[]>(randTodo({ length: 3 })); const ref = useRef<HTMLElement>(); useEffect(() => { const callback = (e: CustomEvent<Todo>) => { console.log(e.detail); }; ref.current!.addEventListener('select-item', callback); return () => ref.current!.removeEventListener('select-item', callback); }, []) return ( <> <button onClick={() => setTodos(randTodo({ length: 3 }))}>Replace</button> <ui-select ref={ref} data={JSON.stringify(todos)} val-key="title"></ui-select> </> ); } |
由於自定義元素不是React元件,它們被視為標準的HTML元素。
我們需要使用JSON.stringify,因為資料屬性值被當作一個字串處理。
由於我們將資料屬性轉換器設定為陣列,Lit將處理解析工作。
我們需要獲得自定義元素的引用,並手動註冊該事件,因為React不支援自定義元素事件。
為了讓它更乾淨,你可以使用諸如use-custom-element這樣的庫。
import '@org/ui/lib/select'; import { randTodo, Todo } from '@ngneat/falso'; import { SelectElement } from '@org/ui/lib/select'; import { useState } from 'react'; import useCustomElement from 'use-custom-element'; export function Todos() { const [todos, setTodos] = useState<Todo[]>(randTodo({ length: 3 })); const [customElementProps, ref] = useCustomElement({ data: todos, 'val-key': 'title', 'select-item'(e: Todo) { console.log(e); } }); return ( <> <button onClick={() => setTodos(randTodo({ length: 3 }))}>Replace</button> <ui-select {...customElementProps} ref={ref}></ui-select> </> ); } |
在Preact中使用Web元件
Preact對Web元件的支援比React好得多。Preact的渲染器透過檢查DOM元素來決定是否使用一個屬性或屬性。
傳遞給DOM元素的未被識別的事件處理道具會完全按照指定的方式使用其套管進行註冊。
import '@org/ui/lib/select'; import { randTodo } from '@ngneat/falso'; import { useState } from 'preact/hooks'; const Todos = () => { const [todos, setTodos] = useState(randTodo({ length: 3 })); return ( <> <button onClick={() => setTodos(randTodo({ length: 3 }))}>Replace</button> <ui-select data={todos} val-key="title" onselect-item={(e) => console.log(e.detail)}> </ui-select> </> ) } |
相關文章
- React、Vue和Angular之後的Svelte前端框架 - OliverReactVueAngular前端框架
- Vue、React和AngularVueReactAngular
- 【Web Components】關於自定義元件屬性在 Vue 和 React 中不同表現的探討Web元件VueReact
- Angular、Vue、React和前端的未來AngularVueReact前端
- Angular、Vue、React 和前端的未來AngularVueReact前端
- 純前端控制元件集 WijmoJS 2018V2釋出,在React、Vue和Angular中更易用前端控制元件JSReactVueAngular
- vue和react元件傳值VueReact元件
- svelte元件:Svelte自定義彈窗Popup元件|svelte移動端彈框元件元件
- TypeScript在React高階元件中的使用技巧TypeScriptReact元件
- 尤大親自評測 Vue3 和 Svelte(19個元件後Vue更好!)Vue元件
- H5數字鍵盤元件適配React/Angular/VueH5元件ReactAngularVue
- Vue、React、Angular最佳UI框架VueReactAngularUI框架
- mobx在react如何使用?3分鐘學會!React
- js框架---angular、vue、react的三者的區別?JS框架AngularVueReact
- 致敬 React: 為 Vue 引入容器元件和展示元件ReactVue元件
- vue開發中,在js檔案裡使用pinia和元件同步VueJS元件
- svelte元件:Svelte3自定義Navbar+Tabbr元件|svelte自定義外掛元件
- 2017年React、Angular和Vue的動態ReactAngularVue
- 深度解析:在 React 中實現類似 Vue 的 KeepAlive 元件ReactVue元件
- VUE實現評分效果和不同型別分數展示效果元件Vue型別元件
- 一文搞定:前端如何選擇Angular、React和Vue三大主流框架前端AngularReactVue框架
- 在Vue3中使用Element-Plus分頁(Pagination )元件Vue元件
- 在ASP.NET 中,Javascript 分別獲取Html伺服器控制元件和Web伺服器控制元件的方法ASP.NETJavaScriptHTML伺服器控制元件Web
- 原始碼分析:vue和react元件事件繫結中的this原始碼VueReact元件事件
- svelte元件:svelte3自定義桌面PC端對話方塊元件svelte-layer元件
- vue,angular4,react如何搭建完美的工程專案VueAngularReact
- 個人理解Vue和React區別VueReact
- Misans global字型在vue中如何使用Vue
- 如何使用@vue/cli 3.0在npm上建立,釋出和使用你自己的Vue.js元件庫NPMVue.js元件
- (覆盤)Vue中如何使用v-echarts元件VueEcharts元件
- angular-electron中如何引入Zorro元件庫Angular元件
- 前端MVVM模式及其在Vue和React中的體現前端MVVM模式VueReact
- 在angular 6中使用 lessAngular
- [譯] React 中的 dumb 元件和 smart 元件React元件
- 【譯】在 React 元件中使用 Refs 指南React元件
- 在 React 中使用 SVG 圖示元件ReactSVG元件
- vue和react有什麼區別?VueReact
- 在vue腳手架中如何使用EChartsVueEcharts