日日加班日日忙,需求襲來如虎狼。 測試問題堆如山,萬念俱灰歸故鄉。javascript
最近在工做之餘一直學習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
的其餘相關文章vue
使用vite
搭建一個Vue3.0
學習環境react
Vue3.0
中使用watch
watch
在Vue3.0
中並非一個新的概念,在使用Vue2.x
的時候,咱們常常會使用watch
來監聽Vue
實例上面的一個表達式或者一個函數計算結果的變化。git
Vue2.0
中的watch
在Vue2.0
中,咱們使用watch
能夠經過下面多種方式去監聽Vue
實例上面的表達式或者函數計算結果的變化,以下羅列了其中的幾種面試
最常規使用方式vue-router
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
去深度監聽對象裏面的屬性,不論嵌套層級有多深。vuex
使用$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>
<div class="about"> <h1>{{ name }}</h1> </div>
</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
的你,同時關注公衆號【前端有的玩】,帶給你不同的驚喜。喜歡本文,能夠給小編一個贊哦。
不要吹滅你的靈感和你的想象力; 不要成爲你的模型的奴隸。 ——文森特・梵高