AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

Vue 3.4 重磅升級:defineModel 宏如何徹底改變前端狀態管理!

來源: 責編: 時間:2024-06-27 17:19:59 121觀看
導讀理解狀態的位置和組件邊界仍然是現代前端開發中主要挑戰之一,也是團隊在應用規模增加時做出的最重要的決定之一,可能會加速開發,也可能成為最大的摩擦源。如果做得好,構建、組合、重構和測試前端組件會變得輕而易舉;如果做

理解狀態的位置和組件邊界仍然是現代前端開發中主要挑戰之一,也是團隊在應用規模增加時做出的最重要的決定之一,可能會加速開發,也可能成為最大的摩擦源。Bnc28資訊網——每日最新資訊28at.com

如果做得好,構建、組合、重構和測試前端組件會變得輕而易舉;如果做得不好,則會成為難以追蹤的幽靈錯誤的無盡源泉,使代碼庫變得脆弱。Bnc28資訊網——每日最新資訊28at.com

Vue 3.4 版本中從實驗狀態發布的 defineModel 宏,可能是關于組件間復雜狀態交互的實現方式最具變革性的特性之一。Bnc28資訊網——每日最新資訊28at.com

描述看似很無害:Bnc28資訊網——每日最新資訊28at.com

defineModel 是一個新的 <script setup> 宏,旨在簡化支持 v-model 的組件的實現Bnc28資訊網——每日最新資訊28at.com

表面上看,這個宏的實用性似乎微不足道,但它對團隊如何處理狀態和管理組件邊界有深遠影響。我們看看 defineModel 是做什么的,為什么它的添加在 Vue 3.4 中感覺像是一種范式轉變——盡管它只是一個簡單的宏。Bnc28資訊網——每日最新資訊28at.com

狀態的概念模型

通常,現代前端應用程序有三種狀態范圍(不包括全局窗口級別的狀態)。Bnc28資訊網——每日最新資訊28at.com

圖片圖片Bnc28資訊網——每日最新資訊28at.com

  1. 全局共享狀態。這是整個層次結構中不同組件可訪問的狀態,例如登錄用戶的賬戶信息和路由間共享的信息。
  2. 分層組件狀態。這是在層次結構的子樹中不同組件可訪問的狀態,例如列表-詳情編輯視圖。
  3. 單個組件級別的狀態。這是僅在層次結構中的單個組件中可訪問的狀態,狀態交互不需要在樹中上下傳遞。

在全局級別,有許多庫和解決方案可以解決這個問題。例如,React 的 Zustand、Jotai、Recoil、Redux 等,Vue 的 Pinia 可以將狀態從組件樹中提取出來放入全局范圍,以跨越樹。它旨在保存真正的全局狀態,如淺色/深色模式或租戶 ID。Bnc28資訊網——每日最新資訊28at.com

第二層狀態是團隊遇到“屬性傳遞”摩擦的地方——無論是在 React、Vue 還是其他庫或框架中。部分原因是管理狀態在組件之間的上下移動是繁重的。Bnc28資訊網——每日最新資訊28at.com

在這種情況下,團隊的自然決定是將狀態移動到全局存儲中,或者進入第三個組件狀態范圍,僅僅是為了避免這種摩擦,而不斷堆積到一個巨大的組件中——這會產生另一種痛苦。Bnc28資訊網——每日最新資訊28at.com

如果能在保持 Vue 的雙向綁定的同時,輕松地將狀態分離開來,而不需要屬性傳遞的摩擦,那該多好。這正是 defineModel 的作用所在,它大大減少了在樹中移動狀態的摩擦,同時保持 Vue 的雙向綁定。Bnc28資訊網——每日最新資訊28at.com

defineModel 是什么?

重要的是首先了解它是什么以及它的功能。對于那些不熟悉 Vue 的人來說,組件間上下移動狀態的慣用模式一直是使用 props 和 emits。Bnc28資訊網——每日最新資訊28at.com

在 defineModel 之前 - props 和 emits

例如,考慮這個父子組件:Bnc28資訊網——每日最新資訊28at.com

圖片圖片Bnc28資訊網——每日最新資訊28at.com

外部組件定義了 ref 并將其作為 prop 傳遞給子組件。更新通過子組件向父組件的 emit 事件來完成。Bnc28資訊網——每日最新資訊28at.com

為了獲得雙向綁定,我們需要內部的 NameInput.vue 組件如下:Bnc28資訊網——每日最新資訊28at.com

<!-- NameInput.vue --><template>  <LabeledContainer label="NameInput.vue">    <input v-model="name"/>  </LabeledContainer></template><script setup lang="ts">const props = defineProps<{  modelValue: string}>()const emits = defineEmits<{  'update:modelValue': [string]}>()const name = computed({  get() {    return props.modelValue  },  set(val) {    emits('update:modelValue', val)  }})</script>

外部的 Example1.vue 組件如下:Bnc28資訊網——每日最新資訊28at.com

<!-- Example1.vue --><template>  <LabeledContainer label="Example1.vue">    <h1>Example 1</h1>    <p>Hello, {{ name.length === 0 ? "(enter your name below)" : name }}</p>    <NameInput v-model="name"/>  </LabeledContainer></template><script setup lang="ts">const name = ref('')</script>

現在,當我們在文本框中輸入值時,它會自動更新 prop 的值:Bnc28資訊網——每日最新資訊28at.com

圖片圖片Bnc28資訊網——每日最新資訊28at.com

我們的非常簡單的組件具有父子組件之間的雙向綁定。Bnc28資訊網——每日最新資訊28at.com

可以很容易地看到,對于如此簡單的事情,這種樣板代碼會變得多么繁瑣!Bnc28資訊網——每日最新資訊28at.com

在 defineModel 之后 ?

隨著 Vue 3.4 中 defineModel 的發布,我們看看它如何簡化 NameInput.vue:Bnc28資訊網——每日最新資訊28at.com

<!-- NameInput.vue --><template>  <LabeledContainer label="NameInput.vue">    <input v-model="name"/>  </LabeledContainer></template><script setup lang="ts">const name = defineModel<string>({ required: true })</script>

父組件保持不變,但大量的樣板代碼被刪除了!這個小小的宏完全改變了管理狀態的體驗。Bnc28資訊網——每日最新資訊28at.com

一個實際的例子

表面上看,這似乎是一個微不足道的變化。當然,獲得了一些便利,但這對開發人員管理狀態有多大影響?僅僅是一個簡單的宏,聲稱會有這么大的影響豈不是荒謬?Bnc28資訊網——每日最新資訊28at.com

事實上,開發人員往往會選擇阻力最小的路徑,如果阻力最小的路徑是壞習慣,那么,開發人員將創建一個充滿許多壞習慣的代碼庫——即“技術債務”。如果你見過 1000 多行的 React 或 Vue 組件(我們中誰沒見過?),那么很可能的原因是將狀態以可管理的方式分散出來的摩擦太大;隨著組件的有機增長,將狀態保持在一個巨大的組件中比分解出新組件更容易。Bnc28資訊網——每日最新資訊28at.com

defineModel 的實現是,它創建了一條最小阻力路徑,同時有助于改善團隊對狀態的思考方式。突然之間,管理分層組件狀態變得微不足道,并消除了將狀態移入全局范圍或在大型組件中進行松散操作的誘惑(通常是 1000 多行組件的來源)。Bnc28資訊網——每日最新資訊28at.com

使用 defineModel 簡化分層狀態

考慮以下簡單的聯系人管理應用程序:Bnc28資訊網——每日最新資訊28at.com

圖片圖片Bnc28資訊網——每日最新資訊28at.com

注意這個示例中的層次結構。當用戶從 Listing.vue 中選擇聯系人時,應用程序應在 Details.vue 中顯示詳細信息。當用戶編輯詳細信息并在 Details.vue 中保存更改時,應用程序應更新 Listing.vue 中的條目。Bnc28資訊網——每日最新資訊28at.com

如果我們想在 Listing.vue 和 Details.vue 之間共享狀態,它必須是全局狀態或從公共父級 Example3.vue 開始的分層狀態——否則,很容易看到將所有內容放入一個巨大的組件中的誘惑!Bnc28資訊網——每日最新資訊28at.com

在這種情況下,這就是我們的分層狀態的樣子:Bnc28資訊網——每日最新資訊28at.com

圖片圖片Bnc28資訊網——每日最新資訊28at.com

狀態通過 prop 從列表組件傳遞到聯系人組件。Bnc28資訊網——每日最新資訊28at.com

我們從外到內檢查代碼。Bnc28資訊網——每日最新資訊28at.com

這是我們的父 Example3.vue 組件:Bnc28資訊網——每日最新資訊28at.com

<template>  <LabeledContainer label="Example3.vue">    <h1>Example 3</h1>    <p v-if="!!selectedContact">      Selected: {{ selectedContact.name }} ({{ selectedContact.handle  }})    </p>    <div class="parent">      <Listing        v-model="contacts"        v-model:selected="selectedContact"/>      <Details v-model="selectedContact"/>    </div>  </LabeledContainer></template><script setup lang="ts">const selectedContact = ref<Contact>()const contacts = ref<Contact[]>([{  name: 'Charles',  handle: '@chrlschn'}])</script>

這是我們的狀態所在根,并通過綁定將其傳遞給 Listing 和 Details 組件:Bnc28資訊網——每日最新資訊28at.com

<!-- Snippet from Example3.vue--><Listing  v-model="contacts"  v-model:selected="selectedContact"/><Details v-model="selectedContact"/>

我們先看看 Details.vue :Bnc28資訊網——每日最新資訊28at.com

<!-- Details.vue, the right side form inputs --><template>  <LabeledContainer label="Details.vue">    <div v-if="!!selected">      <label>        Name        <input v-model="name"/>      </label>      <label>        Handle        <input v-model="handle"/>      </label>      <div>        <button @click="handleCancel">Done</button>        <button @click="handleDone">Save</button>      </div>    </div>    <p v-else>      Select a contact    </p>  </LabeledContainer></template><script setup lang="ts">const selected = defineModel<Contact|undefined>({  required: true})const name = ref('')const handle = ref('')watch (selected, (contact) => {  if (!contact) {    return  }  name.value = contact.name,  handle.value = contact.handle})function handleCancel() {  selected.value = undefined}function handleDone() {  if (!selected.value) {    return  }  selected.value.name = name.value;  selected.value.handle = handle.value;}</script>

這個組件的目的是擁有一組狀態副本,當選中的聯系人更改時,組件將值復制到本地狀態,以便在不影響原始狀態的情況下(直到用戶保存),更改名稱和 handle。這也允許用戶取消任何編輯。Bnc28資訊網——每日最新資訊28at.com

對于更大的屬性集,可以考慮創建對象的完整響應式副本并直接綁定到它。Bnc28資訊網——每日最新資訊28at.com

在左側,Listing.vue 組件包含聯系人列表,并有添加新聯系人的選項。Bnc28資訊網——每日最新資訊28at.com

<!-- Listing.vue --><template>  <LabeledContainer label="Listing.vue">    <div class="container">      <ContactItem        v-for="contact in contacts"        :cnotallow="contact"        :selected="selected == contact"        @click="selected = contact">      </ContactItem>    </div>    <div>      <button @click="handleAddContact"> Add contact </button>    </div>  </LabeledContainer></template><script setup lang="ts">const contacts = defineModel<Contact[]>({  required: true})const selected = defineModel<Contact|undefined>('selected', {  required: true})function handleAddContact() {  contacts.value.push({    name: 'Name',    handle: 'Handle'  })}</script>

然后在 ContactItem.vue 中,Listing.vue 通過普通的 props 傳遞顯示值,因為這里不需要變更(也不需要雙向綁定):Bnc28資訊網——每日最新資訊28at.com

<template>  <LabeledContainer    label="Contact.vue"    class="contact"    :class="{      'selected': !!selected    }">    <p class="name">{{ contact.name }}</p>    <p class="handle">{{ contact.handle }}</p>  </LabeledContainer></template><script setup lang="ts">defineProps<{  contact: Contact,  selected?: boolean}>()</script>

我們看看這整個事情是如何結合在一起的:Bnc28資訊網——每日最新資訊28at.com

圖片圖片Bnc28資訊網——每日最新資訊28at.com

我們的組件在示例組件樹的層次結構中共享狀態。Bnc28資訊網——每日最新資訊28at.com

如果沒有 defineModel 來幫助簡化這種交互,很容易看到本能是采取捷徑或將狀態移入全局狀態,因為編寫各種 emits 和 computed 會產生相當大的摩擦,即使在這個小示例中也是如此!Bnc28資訊網——每日最新資訊28at.com

正如 Billy Mays 可能會說:“但等一下!還有更多!”讓我們看看如何通過使用可組合組件進一步簡化代碼。Bnc28資訊網——每日最新資訊28at.com

使用 defineModel 和可組合組件

利用可組合組件可以將其提升到一個新的水平,并通過將狀態從組件中提取出來進一步簡化我們的代碼。當組件變得更大時,這特別有用。Bnc28資訊網——每日最新資訊28at.com

在 Vue 中,這很容易實現,并使重構和重新組織復雜性變得輕而易舉。Bnc28資訊網——每日最新資訊28at.com

我們只需將我們的狀態和函數向上提取到另一個函數中:Bnc28資訊網——每日最新資訊28at.com

// useContacts composableexport function useContacts() {  const selectedContact = ref<Contact>()  const contacts = ref<Contact[]>([{    name: 'Charles',    handle: '@chrlschn'  }])  function addContact() {    contacts.value.push({      name: 'Name',      handle: 'Handle'    })  }  return {    selectedContact,    contacts,    addContact  }}

很容易看出,如果我們想從 Details.vue 中移動更多的邏輯和狀態,將 name 和 handle refs 以及 handleCancel() 和 handleDone() 函數移動到另一個可組合組件中并共享它們是非常低摩擦的:Bnc28資訊網——每日最新資訊28at.com

// useDetailsEditor.ts//  
                

本文鏈接:http://www.tebozhan.com/showinfo-26-96994-0.htmlVue 3.4 重磅升級:defineModel 宏如何徹底改變前端狀態管理!

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 我們一起聊聊 Go 模塊使用 GitLab subgroups 的問題

下一篇: OpenTelemetry 深度定制:跨服務追蹤的實戰技巧

標簽:
  • 熱門焦點
  • 5月安卓手機好評榜:魅族20 Pro奪冠

    性能榜和性價比榜之后,我們來看最后的安卓手機好評榜,數據來源安兔兔評測,收集時間2023年5月1日至5月31日,僅限國內市場。第一名:魅族20 Pro好評率:97.50%不得不感慨魅族老品牌還
  • Flowable工作流引擎的科普與實踐

    一.引言當我們在日常工作和業務中需要進行各種審批流程時,可能會面臨一系列技術和業務上的挑戰。手動處理這些審批流程可能會導致開發成本的增加以及業務復雜度的上升。在這
  • 如何使用JavaScript創建一只圖像放大鏡?

    譯者 | 布加迪審校 | 重樓如果您曾經瀏覽過購物網站,可能遇到過圖像放大功能。它可以讓您放大圖像的特定區域,以便瀏覽。結合這個小小的重要功能可以大大改善您網站的用戶體驗
  • 這款新興工具平臺,讓你的電腦效率翻倍

    隨著信息技術的發展,我們獲取信息的渠道越來越多,但是處理信息的效率卻成為一個瓶頸。于是各種工具應運而生,都在爭相解決我們的工作效率問題。今天我要給大家介紹一款效率
  • 破圈是B站頭上的緊箍咒

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之每年的暑期檔都少不了瞄準追劇女孩們的古偶劇集,2021年有優酷的《山河令》,2022年有愛奇藝的《蒼蘭訣》,今年卻輪到小破站抓住了追
  • 華為Mate 60系列用上可變靈動島:正式版體驗將會更出色

    這段時間以來,關于華為新旗艦的爆料日漸密集。據此前多方爆料,今年華為將開始恢復一年雙旗艦戰略,除上半年推出的P60系列外,往年下半年的Mate系列也將
  • 三翼鳥智能家居亮相電博會,讓用戶體驗更真實

    2021電博會在青島國際會展中心開幕中,三翼鳥直接把“家”搬到了現場,成為了展會的一大看點。這也是三翼鳥繼9月9日發布了行業首個一站式定制智慧家平臺后的
  • 榮耀Magic4 至臻版 首創智慧隱私通話 強勁影音系統

    2022年第一季度臨近尾聲,在該季度內,許多品牌陸續發布自己的最新產品,讓大家從全新的角度來了解當今的手機技術。手機是電子設備中,更新迭代十分迅速的一款產品,基
  • 北京:科技教育體驗基地開始登記

      北京“科技館之城”科技教育體驗基地登記和認證工作日前啟動。首批北京科技教育體驗基地擬于2023年全國科普日期間掛牌,后續還將開展常態化登記?! ”本┛萍冀逃w驗基
Top