淺析 Vue 3.0 的組裝式 API(一)
(一)響應(yīng)式數(shù)據(jù)
1. 簡單例子
從最簡單的數(shù)據(jù)綁定開始,在 Vue 2.0 中,我們這樣將一個(gè)數(shù)據(jù)綁定到模板的指定位置:
在組件創(chuàng)建參數(shù)的 data 構(gòu)造函數(shù)中返回一個(gè)用來綁定的數(shù)據(jù)對象,其中有個(gè) now
字段,會(huì)被渲染到模板內(nèi)的 .app > p
內(nèi)。
<template> <div class="app"> <h1>Hello world!</h1> <p>Now is: {{now.toString()}}</p> </div> </template> <script> // Vue 2.0 export default { data() { return { now: new Date(), }; }, }; </script>
用 Vue3 的組裝 API 實(shí)現(xiàn)的話,則是這樣:
// Vue 3.0 export default { setup() { return { now: new Date(), }; }, };
2. 更新數(shù)據(jù)
奇怪,看起來好像沒啥區(qū)別,只是把 data
改成了 setup
嗎?
并不是,假如我們現(xiàn)在對這個(gè) DEMO 做個(gè)小改動(dòng),讓它每秒鐘刷新一次時(shí)間,用 Vue2 大概是這樣實(shí)現(xiàn):
// Vue 2.0 export default { data() { return { now: new Date(), }; }, mounted() { setInterval(() => this.now = new Date(), 1000); }, };
而 Vue3 的等效實(shí)現(xiàn)則為:
// Vue 3.0 import { ref, onMounted } from 'vue'; export default { setup() { const now = ref(new Date()); onMounted(() => { setInterval(() => now.value = new Date(), 1000); }); return { now, }; }, };
3. 對比分析
寫了太多 Vue 的我們可能已經(jīng)忘了,Vue2 的代碼從標(biāo)準(zhǔn) JS 模塊的角度來看有多奇怪:
mounted
中修改的this.now
數(shù)據(jù)是在哪創(chuàng)建的?我們在模塊default
對象的成員里并沒有找到對應(yīng)字段,倒是在data
內(nèi)返回的另一個(gè)對象中有這個(gè)字段;- 而
data
中返回的now
也不是真正的this.now
,而是this.now
的初始值,在data
中setInterval
修改now
并不能更新渲染出來的時(shí)間; - 如果想復(fù)用這個(gè)數(shù)據(jù)和它的更新邏輯,你必須將這樣的結(jié)構(gòu)單獨(dú)寫一份,然后通過特殊的
mixin
函數(shù)混入到當(dāng)前組件的構(gòu)造參數(shù)內(nèi)。
這一切,是因?yàn)檎麄€(gè)模塊 default
對象其實(shí)是 vm
對象的構(gòu)造參數(shù)。其背后隱藏了對象的創(chuàng)建邏輯,在構(gòu)造對象時(shí)構(gòu)造參數(shù)中的一些不同層級(jí)的字段被綁定到了 vm
對象上。
不少新手可能都犯過一個(gè)錯(cuò)誤,在 data
中返回的數(shù)據(jù)字段和 props
、methods
或者 computed
中的字段命名撞車(尤其是使用名為 data 的字段),在編碼階段并不能被 IDE 直接發(fā)現(xiàn)。就是因?yàn)樯厦娴脑?,這些字段創(chuàng)建時(shí)隸屬于不同的位置,在之后構(gòu)造時(shí)才被綁在了同一個(gè)對象上,導(dǎo)致了運(yùn)行時(shí)才能發(fā)現(xiàn)的沖突。
Vue3 中,改成提供 ref
、reactive
、toRef
、onMounted
等函數(shù)的形式實(shí)現(xiàn),例子中:
- 在
setup
中看到的now
即是用于綁定的this.now
; - 修改
now.value
即可看到頁面狀態(tài)的更新; - 如果要封裝這份數(shù)據(jù)處理,只需要將
now
和onMounted
處理提取到同一個(gè)函數(shù)內(nèi),再將now
返回即可,不再需要黑盒的mixin
處理。
可以說 Vue3 是直接將響應(yīng)數(shù)據(jù)的創(chuàng)建決定權(quán)、生命周期的通知回調(diào),都通過 API 的形式交給了開發(fā)者,更直觀明了和可控。
4. API 說明
下面詳細(xì)說說常用的幾個(gè)響應(yīng)式數(shù)據(jù)相關(guān) API:ref
, reactive
和 toRefs
。
(1) ref
上面例子中使用到的 ref,可以將一個(gè)數(shù)據(jù)包裝成響應(yīng)式數(shù)據(jù)代理對象。
const count = ref(0); console.log(count.value); // => 0 count.value++; console.log(count.value); // => 1
當(dāng)你修改代理對象的 count.value 屬性時(shí),模板中使用到 count 的位置將響應(yīng)數(shù)據(jù)的變化,更新視圖中的數(shù)據(jù)狀態(tài)。
(2) reactive
對于對象的響應(yīng)式封裝,使用 ref
稍顯麻煩:
const state = ref({ count: 0, }); console.log(state.value.count); // => 0 state.value.count++; console.log(state.value.count); // => 1
這時(shí)可以改為使用 reactive
,像操作普通對象的字段一樣修改 count
即可更新視圖:
const state = reactive({ count: 0, }); console.log(state.count); // => 0 state.count++; console.log(state.count); // => 1
對代理對象 state
添加新的字段也可觸發(fā)視圖更新。
(3) toRefs
有時(shí)候,對象的名字過長,我們想直接在模板內(nèi)使用對象內(nèi)部字段,直接使用解構(gòu)是不行的:
import { reactive } from 'vue'; export default { setup() { const position = reactive({ x: 0, y: 0, }); return { // 錯(cuò)誤,解構(gòu)出來的 x, y 并沒有響應(yīng)式代理。綁定到模板上后,數(shù)據(jù)變化無法觸發(fā)視圖更新 ...position, }; }, };
這個(gè)情況下,使用 toRefs
處理后再解構(gòu)賦值即可:
import { reactive, toRefs } from 'vue'; export default { setup() { const position = reactive({ x: 0, y: 0, }); return { ...toRefs(position), }; }, };
但需要注意,toRefs
只處理調(diào)用時(shí) position
的現(xiàn)有字段,如果在之后對 position
增加新字段,將無法觸發(fā)視圖更新。
以上就是淺析 Vue 3.0 的組裝式 API(一)的詳細(xì)內(nèi)容,更多關(guān)于Vue 組裝式 API的資料請關(guān)注腳本之家其它相關(guān)文章!
- vue設(shè)置全局訪問接口API地址操作
- vue項(xiàng)目接口管理,所有接口都在apis文件夾中統(tǒng)一管理操作
- VUE使用axios調(diào)用后臺(tái)API接口的方法
- Vue3新特性之在Composition API中使用CSS Modules
- Vue.js中Line第三方登錄api的實(shí)現(xiàn)代碼
- 使用Vue Composition API寫出清晰、可擴(kuò)展的表單實(shí)現(xiàn)
- 精讀《Vue3.0 Function API》
- 淺談Vue3.0新版API之composition-api入坑指南
- vue 使用外部JS與調(diào)用原生API操作示例
- vue 更改連接后臺(tái)的api示例
- Vue項(xiàng)目中Api的組織和返回?cái)?shù)據(jù)處理的操作
相關(guān)文章
vue3+element-plus props中的變量使用 v-model 報(bào)錯(cuò)及解決方案
這篇文章主要介紹了vue3+element-plus props中的變量使用 v-model 報(bào)錯(cuò)及解決方案,prop 是單向數(shù)據(jù)流,這里只能用:model-value,不能用v-model,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10vue實(shí)現(xiàn)簡單轉(zhuǎn)盤抽獎(jiǎng)功能
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)簡單轉(zhuǎn)盤抽獎(jiǎng)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03基于Vue3+TypeScript實(shí)現(xiàn)鼠標(biāo)框選功能
這篇文章主要介紹了基于Vue3+TypeScript實(shí)現(xiàn)鼠標(biāo)框選功能,文中通過代碼示例給大家講解的非常纖細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-07-07vue+element+Java實(shí)現(xiàn)批量刪除功能
這篇文章主要介紹了vue+element+Java實(shí)現(xiàn)批量刪除功能,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04vue獲取token實(shí)現(xiàn)token登錄的示例代碼
最近新做了個(gè)vue項(xiàng)目,正好項(xiàng)目中有登錄部分,本文就詳細(xì)的介紹一下登錄部分的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),感興趣的小伙伴們可以參考一下2021-11-11vue項(xiàng)目中Eslint校驗(yàn)代碼報(bào)錯(cuò)的解決方案
這篇文章主要介紹了vue項(xiàng)目中Eslint校驗(yàn)代碼報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04