日日加班日日忙,需求襲來如虎狼。 測試問題堆如山,萬念俱灰歸故鄉。
相關學習推薦:
最近在工作之餘一直學習Vue3.0
相關知識,雖然Vue3.0
至今還是rc
版,但這並不影響我們去學習。今天這篇文章是我關於Vue3.0
的第四篇文章。在前文中我們講解了如何通過vite
和vuecli
搭建Vue3.0
開發環境,然後介紹了Vue3.0
中的setup
,reactive
,ref
等,今天這篇文章主要講解了以下內容:
Vue3.0
中使用watch
Vue3.0
中使用計算屬性Vue3.0
中使用vue-router
Vue3.0
中使用vuex
開始本文前,小編提供了一個Vue3.0
開發環境,倉庫地址為 gitee.com/f_zijun/vue…,歡迎使用。本文首發於公眾號【前端有的玩】,這是一個專注於Vue
與面試
相關的公眾號,提升自己的市場競爭力,就在【前端有的玩】。同時點選以下連結即可存取小編關於Vue3.0
的其他相關文章
學習Vue3.0,先來了解一下Proxy
使用vite
搭建一個Vue3.0
學習環境
Vue3.0
中使用watch
watch
在Vue3.0
中並不是一個新的概念,在使用Vue2.x
的時候,我們經常會使用watch
來監聽Vue
範例上面的一個表示式或者一個函數計算結果的變化。
Vue2.0
中的watch
在Vue2.0
中,我們使用watch
可以通過下面多種方式去監聽Vue
範例上面的表示式或者函數計算結果的變化,如下羅列了其中的幾種
最常規使用方式
export default { data() { return { name: '子君', info: { gzh: '前端有的玩' } } }, watch: { name(newValue, oldValue) { console.log(newValue, oldValue) }, 'info.gzh': { handler(newValue, oldValue) { console.log(newValue, oldValue) }, // 設定immediate會在watch之後立即執行 immediate: true } } }複製程式碼
我們可以在watch
屬性裡面設定要監聽的Vue
範例上面的屬性,也可以通過.
鍵路徑去監聽物件中的某一個屬性的變化,也可以通過設定immediate
在監聽後立即觸發,設定deep
去深度監聽物件裡面的屬性,不論巢狀層級有多深。
使用$watch
監聽
除了常規的watch
物件寫法之外,Vue
範例上面提供了$watch
方法,可以通過$watch
更靈活的去監聽某一個屬性的變化。比如這樣一個場景,我們有一個表單,然後希望在使用者修改表單之後可以監聽到表單的資料變化。但是有一個特殊的場景,就是表單的回填資料是非同步請求過來的,這時候我們希望在後臺請求完資料之後再去監聽變化,這時候就可以使用$watch
。如下程式碼所示:
export default { methods: { loadData() { fetch().then(data => { this.formData = data this.$watch( 'formData', () => { // formData資料發生變化後會進入此回撥函數 }, { deep: true } ) }) } } }複製程式碼
監聽函數表示式
除了監聽字串之外,$watch
的第一個引數也可以是一個函數,當函數的返回值發生變化之後,觸發回撥函數
this.$watch(() => this.name, () => { // 函數的返回值發生變化,進入此回撥函數})複製程式碼
上文中就是Vue2.0
中我們使用watch
的一些常用寫法,對於Vue3.0
,因為其對Vue2.0
做了部分的向下相容,所以上面的用法在Vue3.0
中基本都可以使用,但是Vue3.0
一個很大的亮點就是composition API
,所以除了Vue2.0
中的寫法之外,也可以使用componsition api
中提供的watch
Vue3.0
中使用watch
在Vue3.0
中,除了Vue2.0
的寫法之外,有兩個api
可以對資料變化進行監聽,第一種是watch
,第二種是watchEffect
。對於watch
,其與Vue2.0
中的$watch
用法基本是一模一樣的,而watchEffect
是Vue3.0
新提供的api
下面的範例演示瞭如何使用watch
import { watch, ref, reactive } from 'vue'export default { setup() { const name = ref('子君') const otherName = reactive({ firstName: '王', lastName: '二狗' }) watch(name, (newValue, oldValue) => { // 輸出 前端有的玩 子君 console.log(newValue, oldValue) }) // watch 可以監聽一個函數的返回值 watch( () => { return otherName.firstName + otherName.lastName }, value => { // 當otherName中的 firstName或者lastName發生變化時,都會進入這個函數 console.log(`我叫${value}`) } ) setTimeout(() => { name.value = '前端有的玩' otherName.firstName = '李' }, 3000) } }複製程式碼
watch
除了可以監聽單個值或者函數返回值之外,也可以同時監聽多個資料來源,比如下面程式碼所示:
export default { setup() { const name = ref('子君') const gzh = ref('前端有的玩') watch([name, gzh], ([name, gzh], [prevName, prevGzh]) => { console.log(prevName, name) console.log(prevGzh, gzh) }) setTimeout(() => { name.value = '前端有的玩' gzh.value = '關注我,一起玩前端' }, 3000) } }複製程式碼
watchEffect
的用法與watch
有所不同,watchEffect
會傳入一個函數,然後立即執行這個函數,對於函數裡面的響應式依賴會進行監聽,然後當依賴發生變化時,會重新呼叫傳入的函數,如下程式碼所示:
import { ref, watchEffect } from 'vue'export default { setup() { const id = ref('0') watchEffect(() => { // 先輸出 0 然後兩秒後輸出 1 console.log(id.value) }) setTimeout(() => { id.value = '1' }, 2000) } }複製程式碼
停止執行
Vue2.0
中的$watch
會在呼叫的時候返回一個函數,執行這個函數可以停止watch
,如下程式碼所示
const unwatch = this.$watch('name',() => {})// 兩秒後停止監聽setTimeout(()=> { unwatch() }, 2000)複製程式碼
在Vue3.0
中,watch
與watchEffect
同樣也會返回一個unwatch
函數,用於取消執行,比如下面程式碼所示
export default { setup() { const id = ref('0') const unwatch = watchEffect(() => { // 僅僅輸出0 console.log(id.value) }) setTimeout(() => { id.value = '1' }, 2000) // 1秒後取消watch,所以上面的程式碼只會輸出0 setTimeout(() => { unwatch() }, 1000) } }複製程式碼
清除副作用
想象一下這樣的一個場景,介面上面有兩個下拉框,第二個下拉框的資料是根據第一個下拉框的資料聯動的,當第一個下拉框資料發生變化後,第二個下拉框的資料會通過傳送一個網路請求進行獲取。這時候我們可以通過watchEffect
來實現這個功能,比如像下面程式碼這樣
import { ref, watchEffect } from 'vue'function loadData(id) { return new Promise(resolve => { setTimeout(() => { resolve( new Array(10).fill(0).map(() => { return id.value + Math.random() }) ) }, 2000) }) }export default { setup() { // 下拉框1 選中的資料 const select1Id = ref(0) // 下拉框2的資料 const select2List = ref([]) watchEffect(() => { // 模擬請求 loadData(select1Id).then(data => { select2List.value = data console.log(data) }) }) // 模擬資料發生變化 setInterval(() => { select1Id.value = 1 }, 3000) } }複製程式碼
現在假如我切換了一下第一個下拉框的資料之後,這時候資料請求已經發出,然後我將這個頁面切換到另一個頁面,因為請求已經發出,所以我希望在頁面離開的時候,可以結束這個請求,防止資料返回後出現異常,這時候就可以使用watchEffect
為第一個回撥函數傳入的入參來處理這個情況,如下程式碼所示
function loadData(id, cb) { return new Promise(resolve => { const timer = setTimeout(() => { resolve( new Array(10).fill(0).map(() => { return id.value + Math.random() }) ) }, 2000) cb(() => { clearTimeout(timer) }) }) }export default { setup() { // 下拉框1 選中的資料 const select1Id = ref(0) // 下拉框2的資料 const select2List = ref([]) watchEffect(onInvalidate => { // 模擬請求 let cancel = undefined // 第一個引數是一個回撥函數,用於模擬取消請求,關於取消請求,可以瞭解axios的CancelToken loadData(select1Id, cb => { cancel = cb }).then(data => { select2List.value = data console.log(data) }) onInvalidate(() => { cancel && cancel() }) }) } }複製程式碼
Vue3.0
中使用計算屬性想一想在Vue2.0
中我們一般會用計算屬性做什麼操作呢?我想最常見的就是當模板中有一個複雜計算的時候,可以先使用計算屬性進行計算,然後再在模板中使用,實際上,Vue3.0
中的計算屬性的作用和Vue2.0
的作用基本是一樣的。
在Vue2.0
中使用計算屬性
computed: { getName() { const { firstName, lastName } = this.info return firstName + lastName } },複製程式碼
在Vue3.0
中使用計算屬性
<template> <p class="about"> <h1>{{ name }}</h1> </p></template> <script> import { computed, reactive } from 'vue' export default { setup() { const info = reactive({ firstName: '王', lastName: '二狗' }) const name = computed(() => info.firstName + info.lastName) return { name } } } </script>複製程式碼
和Vue2.0
一樣,Vue3.0
的計算屬性也可以設定getter
和setter
,比如上面程式碼中的計算屬性,只設定了getter
,即加入cumputed
傳入的引數是一個函數,那麼這個就是getter
,假如要設定setter
,需要像下面這樣去寫
export default { setup() { const info = reactive({ firstName: '王', lastName: '二狗' }) const name = computed({ get: () => info.firstName + '-' + info.lastName, set(val) { const names = val.split('-') info.firstName = names[0] info.lastName = names[1] } }) return { name } } }複製程式碼
Vue3.0
中使用vue-router
vue-router
在Vue2.0
中我們使用vue-router
的時候,會通過new VueRouter
的方式去實現一個VueRouter
範例,就像下面程式碼這樣
import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter)const router = new VueRouter({ mode: 'history', routes: [] })export default router複製程式碼
但到了Vue3.0
,我們建立VueRouter
的範例發生了一點點變化,就像Vue3.0
在main.js
中初始化Vue
範例需要像下面寫法一樣
import { createApp } from 'vue'createApp(App).$mount('#app')複製程式碼
vue-router
也修改為了這種函數的宣告方式
import { createRouter, createWebHashHistory } from 'vue-router'const router = createRouter({ // vue-router有hash和history兩種路由模式,可以通過createWebHashHistory和createWebHistory來指定 history: createWebHashHistory(), routes }) router.beforeEach(() => { }) router.afterEach(() => { })export default router複製程式碼
然後在main.js
中,通過
createApp(App).use(router)複製程式碼
來參照到Vue
中
setup
中使用vue-router
在Vue2.0
中,我們通過this.$route
可以獲取到當前的路由,然後通過this.$router
來獲取到路由範例來進行路由跳轉,但是在setup
中,我們是無法拿到this
的,這也意味著我們不能像Vue2.0
那樣去使用vue-router
, 此時就需要像下面這樣去使用
import { useRoute, useRouter } from 'vue-router'export default { setup() { // 獲取當前路由 const route = useRoute() // 獲取路由範例 const router = useRouter() // 噹噹前路由發生變化時,呼叫回撥函數 watch(() => route, () => { // 回撥函數 }, { immediate: true, deep: true }) // 路由跳轉 function getHome() { router.push({ path: '/home' }) } return { getHome() } } }複製程式碼
上面程式碼我們使用watch
來監聽路由是否發生變化,除了watch
之外,我們也可以使用vue-router
提供的生命週期函數
import { onBeforeRouteUpdate, useRoute } from 'vue-router'export default { setup() { onBeforeRouteUpdate(() => { // 噹噹前路由發生變化時,呼叫回撥函數 }) } }複製程式碼
除了onBeforeRouteUpdate
之外,vue-router
在路由離開的時候也提供了一個生命週期勾點函數
onBeforeRouteLeave(() => { console.log('噹噹前頁面路由離開的時候呼叫') })複製程式碼
Vue3.0
中使用vuex
其實vuex
在Vue3.0
中的使用方式和vue-router
基本是一致的
vuex
首先新建store/index.js
,然後新增如下程式碼
import { createStore } from 'vuex'export default createStore({ state: {}, mutations: {}, actions: {} })複製程式碼
然後在main.js
中,通過以下方式使用
createApp(App).use(store)複製程式碼
setup
中使用vuex
和useRouter
一樣,vuex
也提供了useStore
供呼叫時使用,比如下面這段程式碼
import { useStore } from 'vuex'export default { setup() { const store = useStore() const roleMenus = store.getters['roleMenus'] return { roleMenus } } }複製程式碼
其餘的使用方式基本和Vue2.0
中的用法是一致的,大傢俱體可以參考vuex
官方檔案
在前文中,我們說到Vue3.0
是相容一部分Vue2.0
的,所以對於Vue2.0
的元件寫法,生命週期勾點函數並未發生變化,但是假如你使用的是componsition api
,那麼就需要做一部分調整
取消beforeCreate
與created
在使用componsition api
的時候,其實setup
就代替了beforeCreate
與created
,因為setup
就是元件的實際入口函數。
beforeDestroy
與destroyed
改名了
在setup
中,beforeDestroy
更名為onBeforeUnmount
,destroyed
更名為onUnmounted
將生命週期函數名稱變為on+XXX
,比如mounted
變成了onMounted
,updated
變成了onUpdated
在setup
中使用生命週期函數的方式
setup() { onMounted(() => { console.log('mounted!') }) onUpdated(() => { console.log('updated!') }) onUnmounted(() => { console.log('unmounted!') }) }複製程式碼
實際用法與Vue2.0
基本是一致的,只是寫法發生了變化,所以學習成本是很低的。
這是小編關於Vue3.0
的第四篇文章,每一篇文章都是自己在學習中做的一些總結。小編整理了一個vue3.0
的開發環境,倉庫地址為 gitee.com/f_zijun/vue…,內部整合了typescript
,eslint
,vue-router
,vuex
,ant desigin vue
等,希望可以幫到正在學習Vue3.0
的你,同時關注公眾號【前端有的玩】,帶給你不一樣的驚喜。喜歡本文,可以給小編一個贊哦。
不要吹滅你的靈感和你的想象力; 不要成為你的模型的奴隸。 ——文森特・梵高
以上就是使用Vue3.0收穫的知識點(二)的詳細內容,更多請關注TW511.COM其它相關文章!