日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

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

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

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

理解狀態(tài)的位置和組件邊界仍然是現(xiàn)代前端開發(fā)中主要挑戰(zhàn)之一,也是團隊在應用規(guī)模增加時做出的最重要的決定之一,可能會加速開發(fā),也可能成為最大的摩擦源。5v828資訊網(wǎng)——每日最新資訊28at.com

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

Vue 3.4 版本中從實驗狀態(tài)發(fā)布的 defineModel 宏,可能是關(guān)于組件間復雜狀態(tài)交互的實現(xiàn)方式最具變革性的特性之一。5v828資訊網(wǎng)——每日最新資訊28at.com

描述看似很無害:5v828資訊網(wǎng)——每日最新資訊28at.com

defineModel 是一個新的 <script setup> 宏,旨在簡化支持 v-model 的組件的實現(xiàn)5v828資訊網(wǎng)——每日最新資訊28at.com

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

狀態(tài)的概念模型

通常,現(xiàn)代前端應用程序有三種狀態(tài)范圍(不包括全局窗口級別的狀態(tài))。5v828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5v828資訊網(wǎng)——每日最新資訊28at.com

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

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

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

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

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

defineModel 是什么?

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

在 defineModel 之前 - props 和 emits

例如,考慮這個父子組件:5v828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5v828資訊網(wǎng)——每日最新資訊28at.com

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

為了獲得雙向綁定,我們需要內(nèi)部的 NameInput.vue 組件如下:5v828資訊網(wǎng)——每日最新資訊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 組件如下:5v828資訊網(wǎng)——每日最新資訊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>

現(xiàn)在,當我們在文本框中輸入值時,它會自動更新 prop 的值:5v828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5v828資訊網(wǎng)——每日最新資訊28at.com

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

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

在 defineModel 之后 ?

隨著 Vue 3.4 中 defineModel 的發(fā)布,我們看看它如何簡化 NameInput.vue:5v828資訊網(wǎng)——每日最新資訊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>

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

一個實際的例子

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

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

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

使用 defineModel 簡化分層狀態(tài)

考慮以下簡單的聯(lián)系人管理應用程序:5v828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5v828資訊網(wǎng)——每日最新資訊28at.com

注意這個示例中的層次結(jié)構(gòu)。當用戶從 Listing.vue 中選擇聯(lián)系人時,應用程序應在 Details.vue 中顯示詳細信息。當用戶編輯詳細信息并在 Details.vue 中保存更改時,應用程序應更新 Listing.vue 中的條目。5v828資訊網(wǎng)——每日最新資訊28at.com

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

在這種情況下,這就是我們的分層狀態(tài)的樣子:5v828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5v828資訊網(wǎng)——每日最新資訊28at.com

狀態(tài)通過 prop 從列表組件傳遞到聯(lián)系人組件。5v828資訊網(wǎng)——每日最新資訊28at.com

我們從外到內(nèi)檢查代碼。5v828資訊網(wǎng)——每日最新資訊28at.com

這是我們的父 Example3.vue 組件:5v828資訊網(wǎng)——每日最新資訊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>

這是我們的狀態(tài)所在根,并通過綁定將其傳遞給 Listing 和 Details 組件:5v828資訊網(wǎng)——每日最新資訊28at.com

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

我們先看看 Details.vue :5v828資訊網(wǎng)——每日最新資訊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>

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

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

在左側(cè),Listing.vue 組件包含聯(lián)系人列表,并有添加新聯(lián)系人的選項。5v828資訊網(wǎng)——每日最新資訊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 傳遞顯示值,因為這里不需要變更(也不需要雙向綁定):5v828資訊網(wǎng)——每日最新資訊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>

我們看看這整個事情是如何結(jié)合在一起的:5v828資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5v828資訊網(wǎng)——每日最新資訊28at.com

我們的組件在示例組件樹的層次結(jié)構(gòu)中共享狀態(tài)。5v828資訊網(wǎng)——每日最新資訊28at.com

如果沒有 defineModel 來幫助簡化這種交互,很容易看到本能是采取捷徑或?qū)顟B(tài)移入全局狀態(tài),因為編寫各種 emits 和 computed 會產(chǎn)生相當大的摩擦,即使在這個小示例中也是如此!5v828資訊網(wǎng)——每日最新資訊28at.com

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

使用 defineModel 和可組合組件

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

在 Vue 中,這很容易實現(xiàn),并使重構(gòu)和重新組織復雜性變得輕而易舉。5v828資訊網(wǎng)——每日最新資訊28at.com

我們只需將我們的狀態(tài)和函數(shù)向上提取到另一個函數(shù)中:5v828資訊網(wǎng)——每日最新資訊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 中移動更多的邏輯和狀態(tài),將 name 和 handle refs 以及 handleCancel() 和 handleDone() 函數(shù)移動到另一個可組合組件中并共享它們是非常低摩擦的:5v828資訊網(wǎng)——每日最新資訊28at.com

// useDetailsEditor.ts//  
                

本文鏈接:http://m.www897cc.com/showinfo-26-96994-0.htmlVue 3.4 重磅升級:defineModel 宏如何徹底改變前端狀態(tài)管理!

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

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

下一篇: OpenTelemetry 深度定制:跨服務追蹤的實戰(zhàn)技巧

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
欧美成黄导航| 亚洲自拍偷拍一区| 韩国美女久久| 激情五月婷婷综合| 亚洲欧洲综合另类| 美国十次了思思久久精品导航| 久久久综合精品| 欧美精品啪啪| 国产精品捆绑调教| 精品动漫3d一区二区三区免费版| 亚洲精品日韩一| 亚洲欧美在线视频观看| 久久久久亚洲综合| 欧美男人的天堂| 国产欧美一区二区精品婷婷 | 久久久精彩视频| 欧美搞黄网站| 国产农村妇女精品| 亚洲国产日韩一区二区| 亚洲欧美福利一区二区| 噜噜噜噜噜久久久久久91| 欧美视频中文字幕在线| 激情综合网址| 亚洲一区二区三区四区中文| 久久综合网hezyo| 国产精品区一区| 最新日韩在线| 久久国产精品72免费观看| 欧美日韩成人激情| 在线观看成人av电影| 亚洲一区在线播放| 欧美成人一区二免费视频软件| 国产精品美女诱惑| 亚洲精品一区二区三| 久久电影一区| 国产精品国产三级国产普通话三级 | 欧美区一区二区三区| 狠狠色狠狠色综合日日tαg| 一片黄亚洲嫩模| 蜜臀av国产精品久久久久| 国产精品一区久久久| 日韩视频精品在线| 久久久在线视频| 国产欧美精品日韩精品| 一本色道久久综合狠狠躁篇怎么玩| 久久久噜噜噜久噜久久| 国产精品制服诱惑| 中文日韩欧美| 欧美日本国产一区| 1024成人| 久久免费精品视频| 国产毛片精品视频| 亚洲一二三区在线观看| 欧美精品一线| 亚洲丰满少妇videoshd| 午夜精品美女久久久久av福利| 欧美日韩国产91| 亚洲人午夜精品| 久久先锋影音av| 国产一区二区三区奇米久涩| 亚洲一区久久久| 欧美日韩国产成人精品| 亚洲欧洲久久| 欧美成人激情在线| 亚洲国产电影| 美女露胸一区二区三区| 伊人久久婷婷| 久久婷婷国产麻豆91天堂| 国产一区二区三区直播精品电影| 午夜精品区一区二区三| 国产精品久久久久久久浪潮网站 | 极品少妇一区二区| 久久国产精品高清| 国产日韩欧美a| 亚洲欧美日韩中文播放| 国产精品久久久久久亚洲调教 | 日韩香蕉视频| 欧美日韩一区二| 一本色道88久久加勒比精品 | 久久综合久色欧美综合狠狠 | 亚洲高清不卡| 免费日本视频一区| 在线免费观看日韩欧美| 久久综合九色九九| 尤妮丝一区二区裸体视频| 久久久噜噜噜久久狠狠50岁| 一区精品在线| 能在线观看的日韩av| 亚洲福利视频网站| 欧美国产精品一区| 日韩视频在线一区| 欧美视频亚洲视频| 亚洲欧美精品伊人久久| 国产欧美一区二区三区另类精品 | 欧美日韩国产首页| 亚洲婷婷综合久久一本伊一区| 国产精品免费福利| 久久成人人人人精品欧| 伊人成综合网伊人222| 欧美成人一区二区三区| 日韩视频精品| 国产精品毛片a∨一区二区三区| 午夜国产精品视频| 狠狠色狠狠色综合| 欧美激情亚洲国产| 亚洲视频电影在线| 国产精品亚洲综合久久| 久久精品国产99精品国产亚洲性色| 一色屋精品视频在线看| 欧美精品色综合| 亚洲免费网址| 国内精品久久久久影院色 | 国产精品一区久久久| 久久夜色精品亚洲噜噜国产mv | 亚洲午夜91| 国产色视频一区| 葵司免费一区二区三区四区五区| 亚洲精品国产系列| 国产精品入口| 久久在线免费| 日韩亚洲精品在线| 国产欧美日韩另类视频免费观看| 久久米奇亚洲| 一片黄亚洲嫩模| 国产伊人精品| 欧美日本精品在线| 欧美一区日本一区韩国一区| 亚洲国产成人久久综合| 国产精品美女久久久浪潮软件| 久久久久久网站| 一区二区三区四区国产| 国产综合久久久久久| 欧美精品一区二区精品网| 亚洲欧美成人精品| 亚洲国产综合在线看不卡| 国产精品久久久久久久久久妞妞| 久久人人爽人人爽爽久久| 一本大道久久精品懂色aⅴ| 国模 一区 二区 三区| 欧美日本一道本在线视频| 性色av一区二区三区| 亚洲日本中文字幕区| 国产午夜精品视频免费不卡69堂| 欧美精品黄色| 久久精品欧美日韩精品| 99国产精品99久久久久久| 国内精品**久久毛片app| 欧美激情综合网| 久久精品视频在线| 一区二区久久久久久| 狠狠色狠色综合曰曰| 欧美亚州一区二区三区| 久久综合一区| 午夜在线精品| 一区二区动漫| 亚洲成色www久久网站| 国产精品久久久久久妇女6080 | 亚洲国产免费| 国产综合视频| 国产精品第一区| 欧美激情国产高清| 久久伊人免费视频| 亚洲欧美电影院| 亚洲免费精品| 在线日韩欧美视频| 国产日韩精品视频一区| 欧美四级在线| 欧美激情一区二区三区四区| 久久久噜噜噜久久中文字免| 亚洲男女自偷自拍图片另类| 日韩天天综合| 亚洲国产精品久久久久| 国产一区二区按摩在线观看| 国产精品久久| 欧美视频福利| 欧美日韩高清在线| 欧美极品在线播放| 欧美aⅴ99久久黑人专区| 久久久久久久91| 欧美在线观看你懂的| 亚洲综合色噜噜狠狠| 一区二区三区精品视频在线观看| 亚洲国产精品第一区二区| 激情五月***国产精品| 国模 一区 二区 三区| 国产日韩欧美在线播放| 国产精品蜜臀在线观看| 国产精品黄视频| 欧美日韩在线综合| 欧美日韩系列| 欧美日韩调教| 欧美日韩一区高清| 欧美日韩1234| 欧美日韩国产欧| 欧美日韩网址| 欧美视频国产精品| 欧美三区在线视频| 欧美日韩一区二区视频在线| 欧美久久一区| 欧美日产国产成人免费图片| 欧美激情精品久久久久| 欧美精品久久一区二区| 欧美精品日韩综合在线| 欧美日韩一区二区视频在线|