Composition API 是 vue3.0 新推出的一種邏輯復用方案,官網是這么說的
用組件的選項 (data、computed、methods、watch) 組織邏輯在大多數情況下都有效。然而,當我們的組件變得更大時,邏輯關注點的列表也會增長。這可能會導致組件難以閱讀和理解,尤其是對於那些一開始就沒有編寫這些組件的人來說。這種碎片化使得理解和維護復雜組件變得困難。選項的分離掩蓋了潛在的邏輯問題。此外,在處理單個邏輯關注點時,我們必須不斷地“跳轉”相關代碼的選項塊。如果我們能夠將與同一個邏輯關注點相關的代碼配置在一起會更好。而這正是 Composition API 使我們能夠做到的。
想要充分理解這段話,我們首先要知道 vue 模板語法存在的問題
先寫個簡單的 demo
// simple.vue export default { props: ['id'], data() { return { list: [] }; }, created() { this.getList(this.id); }, watch: { id(newId) { this.getList(newId); } }, methods: { getList(id) { this.$api.post('url', id).then(res => { this.list = res.list; }); } } };
可以看出,創建組件時接受一個 id 去請求 list 數據,當 id 變更時重新發起請求。很常見的業務邏輯,但這種寫法導致的問題已經出現,我們想要將此邏輯優雅地進行復用已不可能,因為此邏輯已經和組件本身的選項耦合在了一起。
在此之前,vue 的解決方案是使用 mixins,我們可以將此邏輯抽象為一個對象去混入到別的組件之中,就像這樣
// complex.vue let simple = {......}; export default { mixins: [simple] };
似乎還是很簡潔不是嗎,可是一個組件可能存在着很多邏輯復用的場景,那么你的組件就會變成這樣
// complex.vue import simple from './simple.js'; import simple2 from './simple2.js'; import simple3 from './simple3.js'; export default { mixins: [simple, simple2, simple3] };
mixins 可以很好地保障邏輯的復用,不會寫任何多余重復的代碼,但其弊端是會導致數據的流向變得難以追蹤,通俗地講就是加大了你對於此種代碼的理解難度。
作為一名維護者,第一次接觸到 complex 這個組件時,你不僅要把 complex 的代碼閱讀一遍,還要把 simple 、simple2、simple3 的代碼通讀一遍,不然一不小心,就會觸及到以往的功能,而原因僅僅是你定義了一個重復名稱的變量 —— minxins 在合並時發生沖突,是以組件自身的數據優先的,而這完全屬於意料外的問題。我只想加個簡單的小功能,我並不關注這個組件本身復用了多少別的業務邏輯。
到這里,再回過頭看看開頭給出的官網的話,是不是有了更深的理解呢。
而以我對於 vue 的理解,作者將 html、js、css 融入到一個組件之中,固定地采用一系列選項,就是想為開發者屏蔽掉很多考慮和負擔,這也大大加強了我們開發及維護時的便利性,而 mixins 很明顯與這一理念沖突,這也就能理解作者當初試圖棄用模板語法時的心態了,我們現在有了更好的解決方案 —— Composition API。
還是這個 demo,我們用新的語法去改寫
// simple.js import { ref, watchEffect } from 'vue'; export default function simple(id) { let list = ref([]); const getList = id => { this.$api.post('url', id).then(res => { list.value = res.list; }); }; watchEffect(() => { getList(id.value); }); return { list }; }
此時 simple 已經是一個函數了,所以我們在 complex 組件中應該這樣引入
// complex.vue import simple from './simple.js'; export default { props: ['id'], setup(props) { let { list } = simple(props.id); return { list }; } };
基於 vue3.0 給出的新語法,list 已通過 ref 變成響應式的數據,而 watchEffect 又幫助我們觀測傳入的 props.id。當 props 傳入的 id 發生變動時,則會觸發 simple 里的 getList 方法,產生 list 數據的更新, 再由 complex 組件重新渲染頁面,十分清晰明了,也正如官網所說,邏輯關注點相同的代碼將很容易配置在一起。
而且有再多的邏輯復用也不怕,因為我們此時已將 mixins 語法 以函數的形式取代掉了,變量名稱沖突的問題將迎刃而解,也順帶解決了 mixins 導致的數據流向不清晰的問題,組件的數據來源,一目了然。
// complex.vue import simple from './simple.js'; import simple2 from './simple2.js'; import simple3 from './simple3.js'; export default { setup(props) { let { list } = simple(props); let { list2 } = simple2(props); let { list3 } = simple3(props); return { list, list2, list3 }; } };
以上就是本人對於 Composition API 的一些理解,若有新的心得體會,我會繼續補充。