v2 用的是結合選項式API
1、結合選項式API
用組件的選項 (data
、computed
、methods
、watch
) 組織邏輯在大多數情況下都有效。然而,當我們的組件變得更大時,邏輯關注點的列表也會增長。這可能會導致組件難以閱讀和理解,尤其是對於那些一開始就沒有編寫這些組件的人來說。
一個大型組件的示例,其中邏輯關注點是按顏色分組。
這種碎片化使得理解和維護復雜組件變得困難。選項的分離掩蓋了潛在的邏輯問題。此外,在處理單個邏輯關注點時,我們必須不斷地“跳轉”相關代碼的選項塊。
如果我們能夠將與同一個邏輯關注點相關的代碼配置在一起會更好。而這正是組合式 API 使我們能夠做到的
如: data 和 methods 寫在一起
2、Composition API 的入口 setup()
新的 setup
組件選項在創建組件之前執行,一旦 props
被解析,並充當合成 API 的入口點。
setup
選項應該是一個接受 props
和 context
的函數,我們將在稍后討論。此外,我們從 setup
返回的所有內容都將暴露給組件的其余部分 (計算屬性、方法、生命周期鈎子等等) 以及組件的模板。就是說以上東西都是 setup 返回。
上面的警告是說, setup 發生在 生命周期 beaforeCreate() 之前,實例還沒有被創建, 所以選項中也沒有 this。
使用的方法:
個人理解這樣寫,data 和 methods 寫在一塊,維護起來比較方便
// src/components/UserRepositories.vue `setup` function import { fetchUserRepositories } from '@/api/repositories' // 在我們的組件內 setup (props) { let repositories = [] const getUserRepositories = async () => { repositories = await fetchUserRepositories(props.user) } return { repositories, getUserRepositories // 返回的函數與方法的行為相同 } }
但是,上面的寫法中 data repositories 並不是響應式的
在 Vue 3.0 中,我們可以通過一個新的 ref
函數使任何響應式變量在任何地方起作用
ref
接受參數並返回它包裝在具有 value
property 的對象中,然后可以使用該 property 訪問或更改響應式變量的值:
import { ref } from 'vue' const counter = ref(0) console.log(counter) // { value: 0 } console.log(counter.value) // 0 counter.value++ console.log(counter.value) // 1
在任何值周圍都有一個包裝器對象,這樣我們就可以在整個應用程序中安全地傳遞它,而不必擔心在某個地方失去它的響應性。
// src/components/UserRepositories.vue `setup` function import { fetchUserRepositories } from '@/api/repositories' import { ref } from 'vue' // in our component setup (props) { const repositories = ref([]) const getUserRepositories = async () => { repositories.value = await fetchUserRepositories(props.user) } return { repositories, getUserRepositories } }
完成!現在,每當我們調用 getUserRepositories
時,repositories
都將發生變化,視圖將更新以反映更改。
我們的組件現在應該如下所示:(v2 用的是結合選項式API向 V3組合式API 遷移)
下面 setup(props) 可以接收到 外部的 props(父組件傳過來的值),使用方式如下 props.user
// src/components/UserRepositories.vue import { fetchUserRepositories } from '@/api/repositories' import { ref } from 'vue' export default { components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList }, props: { user: { type: String, required: true } }, setup (props) { const repositories = ref([]) const getUserRepositories = async () => { repositories.value = await fetchUserRepositories(props.user) } return { repositories, getUserRepositories } }, data () { return { filters: { ... }, // 3 searchQuery: '' // 2 } }, computed: { filteredRepositories () { ... }, // 3 repositoriesMatchingSearchQuery () { ... }, // 2 }, watch: { user: 'getUserRepositories' // 1 }, methods: { updateFilters () { ... }, // 3 }, mounted () { this.getUserRepositories() // 1 } }
我們已經將第一個邏輯關注點中的幾個部分移到了 setup
方法中,它們彼此非常接近。剩下的就是在 mounted
鈎子中調用 getUserRepositories
,並設置一個監聽器,以便在 user
prop 發生變化時執行此操作。
我們將從生命周期鈎子開始。
#生命周期鈎子注冊內部 setup
為了使組合式 API 的特性與選項式 API 相比更加完整,我們還需要一種在 setup
中注冊生命周期鈎子的方法。這要歸功於從 Vue 導出的幾個新函數。組合式 API 上的生命周期鈎子與選項式 API 的名稱相同,但前綴為 on
:即 mounted
看起來像 onMounted
。
這些函數接受在組件調用鈎子時將執行的回調。
讓我們將其添加到 setup
函數中:
// src/components/UserRepositories.vue `setup` function import { fetchUserRepositories } from '@/api/repositories' import { ref, onMounted } from 'vue' // in our component setup (props) { const repositories = ref([]) const getUserRepositories = async () => { repositories.value = await fetchUserRepositories(props.user) } onMounted(getUserRepositories) // on `mounted` call `getUserRepositories` return { repositories, getUserRepositories } }
現在我們需要對 user
prop 所做的更改做出反應。為此,我們將使用獨立的 watch
函數。
watch
響應式更改
就像我們如何使用 watch
選項在組件內的 user
property 上設置偵聽器一樣,我們也可以使用從 Vue 導入的 watch
函數執行相同的操作。它接受 3 個參數:
- 一個響應式引用或我們想要偵聽的 getter 函數
- 一個回調
- 可選的配置選項
下面讓我們快速了解一下它是如何工作的
import { ref, watch } from 'vue' const counter = ref(0) watch(counter, (newValue, oldValue) => { console.log('The new counter value is: ' + counter.value) })