對於Vue3和Ts的心得和思考
本文正在參加「金石計劃」
作者:京東物流 吳雲闊
1 前言
Vue3已經正式發佈了一段時間了,各種生態已經成熟。最近使用taro+vue3重構冷鏈的小程序,經過了一段時間的開發和使用,有了一些自己的思考。
總的來説,Vue3無論是在底層原理還是在實際開發過程中,都有了很大的進步。
從源碼層面來説,使用Proxy代替Object.defineProperty的API,一個是代理的對象,一個是遞歸監控的屬性,從而在性能上有了很大的進步,並且,也解決了對象動態屬性增加、數組改變監聽上的缺陷;對diff算法進行優化,增加了靜態標記,大大提高了Vue的執行效率;還有靜態提升、事件監聽緩存等一系列提升效率的手段。
從應用層面來説,主要的改變是將option API改成了composition API(組合式API),在業務中拋棄data、methods、生命週期函數隔離開的開發方式,使代碼相對於業務有更強的聚合性,在代碼開發、代碼閲讀、代碼維護方面對於開發者都是更加友好。
對於typescript有了更好的支持,我們知道,對於大型的前端項目來説,使用typescript的類型校驗,能使前端項目有更強的健壯性,這也使得Vue3對於大型項目的開發提供了更強的質量保證。
2 組合式API
所謂的組合式API,將Vue2中的data、methods、生命週期、數據監聽等option,都封裝成鈎子函數,然後組合到setup函數中,其核心就在於setup函數。setup函數存在的意義,就是為了使用這些新增的組合式API,並且這些API只能在setup函數中使用。
setup函數執行的時機是,props初始化之後,beforeCreate函數執行之前,所以在執行setup時,還沒有初始化Vue實例,因此在setup中不能使用this對象。setup函數的返回值會被注入到Vue實例中,供Vue組件使用,所以任何數據想在Vue組件的模板中使用,必須在setup函數中return出去。
組合式API的組合,體現在兩個層面。第一層的意思是,將某一業務相關數據和處理邏輯放到一起,這是一種關注點的聚合,更方便我們編寫代碼、處理業務邏輯,並且能更聚焦業務邏輯,更方便我們看代碼。第二層面的意思,當某個組件的業務邏輯足夠複雜,setup中的代碼足夠大的情況下,我們可以在setup內部,進一步提取相關的一塊業務,使代碼邏輯更加清晰,做到了進一步的聚合作用。
如下面代碼所示,將業務代碼塊A抽出來,則代碼塊A中return出來的數據就可以在組件中使用:
// 組件
import functionA from 'A'
export default defineComponent({
name: 'componentName',
setup() {
...functionA()
}
-
})
-
// 代碼塊A
export default () => {
return {
a: 1
}
}
3 響應式API
在Vue3中響應式API,主要體現在ref和reactive兩個函數。對於響應式API,想説兩個問題,第一個是為什麼要增加響應式API,第二個是響應式API函數ref和reactive的異同點。
3.1 為什麼增加響應式API
在Vue2中所有數據都寫在data的option中,data中的數據都是響應式的,這樣產生的一個問題是,有些常量數據本身不需要監聽,從而造成了資源的浪費。所以在Vue3中增加了響應式API,只需要對需要動態更新dom的數據進行響應式,不需要動態更新dom的數據不進行響應式處理,從很大程度上節省了資源。這裏我覺得需要注意的是,寫代碼的時候一定要仔細思考一下,哪些數據需要進行響應式綁定,哪些數據不需要進行響應式綁定,而不是一股腦的全給綁定上,這樣即使代碼邏輯不能很清晰易懂,並且也會影響執行效率(寫慣了Vue2的同學需要注意)。
3.2 ref和reactive的異同點
在瞭解了為什麼要增加響應式API後,我們發現Vue3提供了兩個響應式API函數,ref和reactive。為什麼會提供兩個API呢? 一個不就可以了嗎?那麼這兩個API之間的區別是什麼呢?
在使用層面,ref綁定的數據,需要使用[data].value進行數據更改。而reactive綁定的數據需要使用[data].[prpoerty]的方式進行數據更改。在使用場景方面,一般的,單個的普通數據,我們使用ref來定義響應式。而複雜數據,如:表單數據對象、某一模塊的一組數據等,使用reactive來定義響應式。
那麼,對象是不是必須用reactive來定義呢? 其實不是的,都可以。官方説法是:可以根據自身習慣使用不同的API。其實,我覺得,他們是有各自的使用場景的,ref更強調的是數據Value的改變,reactive更強調的是數據中某一屬性的改變。
4 treeShaking思想
當 Javascript 項目達到一定體積時,將代碼分成模塊會更易於管理。但是,當這樣做時,我們最終可能會導入實際上未使用的代碼。Tree Shaking 是一種通過消除最終文件中未使用的代碼來優化體積的方法。
Vue3使用了tree shaking的方法,將組件以及其所有的生命週期函數等方法進行分開,如果在組件中使用的代碼將不會出現在最終的打包文件中,如此,會減少大大Vue3項目的打包體積。由此造成的一個結果就是,使用方法的不同。
4.1 生命週期函數的使用方法
import { defineComponent, ref, onMounted } from 'vue';
export default defineComponent({
name: 'Gift',
setup() {
const counter = ref(0);
onMounted(() => {
// 處理業務,一般進行數據請求
})
return {
counter
}
}
})
4.2 Vuex的使用方法
import { useStore } from "vuex";
import { defineComponent, ref, computed } from 'vue';
export default defineComponent({
name: 'Gift',
setup() {
const counter = ref(0);
const store = useStore();
const storeData = computed(() => store); // 配合computed,獲取store的值。
return {
counter,
storeData
}
}
})
4.3 Router的使用方法
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import { defineComponent, ref, computed } from 'vue';
export default defineComponent({
name: 'Gift',
setup() {
const counter = ref(0);
const router = useRouter();
const onClick = () => {
router.push({ name: "AddGift" });
}
return {
counter,
onClick
}
}
})
5 關於Typescript的使用
這一部分是關於Ts的內容,不過它與Vue3的開發息息相關。Vue3整體是使用Ts寫的,因此,開發Vue3的項目需要使用Ts,所以,我們還是要了解TS的。
關於Ts的使用這裏就不在細説了,在這裏想説的的是,在實際業務場景中是如何組織Ts代碼的。通過對TS的大量使用,我的一個體會是:Ts的核心思維是先關注數據結構,在根據數據結構進行頁面開發。而以前的前端開發模式是,先寫頁面,然後再關注數據。
比如説,我們要開發一個頁面,我們可能需要先定義一些interface。開發頁面的時候我們要關注:頁面數據的interface、接口返回數據的類型、請求參數的類型等等。
下面是開發一個列表頁面的例子:
// 這是列表中每一項的數據類型
interface IDataItem {
id: string | number;
name: string;
desc: string;
[key: string]: any;
-
}
-
// 接口返回值類型, 一般來説,我們不確定接口返回的數據的類型,因此使用泛型
interface IRes<T> {
code: number;
msg: string;
data: T
-
}
-
// 口返回數據類型定義
interface IDataInfo {
list: Array<IDataItem>;
pageNum: number;
pageSize: number;
total: number;
-
}
-
// 請求
export const getDatalist = (
params: Record<string, any>
): Promise<IRes<IDataInfo>> => {
return Http.get("/api/data/list", params);
};
如上面代碼,當我們的interface定義完成後,我們的頁面數據基本都已清楚,直接寫頁面就會清晰很多,且出錯概率會大大降低。
- 應用健康度隱患刨析解決系列之數據庫時區設置
- 對於Vue3和Ts的心得和思考
- 一文詳解擴散模型:DDPM
- zookeeper的Leader選舉源碼解析
- 一文帶你搞懂如何優化慢SQL
- 京東金融Android瘦身探索與實踐
- 微前端框架single-spa子應用加載解析
- cookie時效無限延長方案
- 聊聊前端性能指標那些事兒
- Spring竟然可以創建“重複”名稱的bean?—一次項目中存在多個bean名稱重複問題的排查
- 京東金融Android瘦身探索與實踐
- Spring源碼核心剖析
- 深入淺出RPC服務 | 不同層的網絡協議
- 安全測試之探索windows遊戲掃雷
- 關於數據庫分庫分表的一點想法
- 對於Vue3和Ts的心得和思考
- Bitmap、RoaringBitmap原理分析
- 京東小程序CI工具實踐
- 測試用例設計指南
- 當你對 redis 説你中意的女孩是 Mia