日日加班日日忙,需求袭来如虎狼。 测试问题堆如山,万念俱灰归故乡。
相关学习推荐:javascript
最近在工作之余一直学习Vue3.0
相关知识,虽然Vue3.0
至今还是rc
版,但这并不影响我们去学习。今天这篇文章是我关于Vue3.0
的第四篇文章。在? z m前文中p ^ ! o 0 5 9 4我们讲解了如何通过vE . k } ~ bite
和vue7 Z % x 9 O mcli
搭建Vue3.0
开发环境,然后介绍了Vue3.0
中的setup
,reactive
,ref
等,今天这篇文章主要讲解了以下内容:
-
Vue3.0
中使用/ Q y P + : @watch
-
Vue3.0
中使用计算属性 -
Vue3.0
中使用vue-router
-
Vue3.0
中使用vuex
开始本文前,小编提供了一个Vue3.0
开发环境,仓库地址为 gitee.com/f_zijun/vue…,欢迎使用。本文h g E : Y首发于公. M D X 1 E 9 m众号【前端有的玩】,这是一个专注于Vue
与面试
相关的公众号,提升自己的市场竞争力,就在【前端有的玩】。同时点击以下链接即可访问小编关于Vue3.0
的其他相关文章
学习Vue3.0,先来了解一下Proxy
使用vite
搭建一个Vue3.0
学习环境
使用VueP P ^ _ % 6 #3.0收获的知识点(一)
Vue3.0
中使用watch
watch
在Vue3.0
中并不是一个新8 # ) F p a y c的概念,在使用Vue2.x
的时候,我们# 4 z B C经常会使用watch
来监听Vue
实例上面的一个表达式或者一个函数计算结果的变化。
回顾Vue2.0
中的watch
在Vue2.0
中,我们使用watch
可以通过下面多种方式去监听Vue
实例上面的表达式或者J % i函数计算结果的变化,如下罗列了其中的几种
-
最常规使用方式
export default {@ d P data() { return { name: '子君', info: { gzh: '前端有的玩' } } }, watch: { naQ i j 8 0me(newValue, oldValue) { console.t I b 1log(newValue, oldValue) }, 'info.gzh': { handler(newVa$ 6 h % L Xlue, oldValue) { console.log(newValue, oldValue) }, // 配置immediate会在watch之后立即~ D -执行 immediate: true } } }复制代码
我们可以在
wat| M _ch
属性里面配置要监听的Vue
实例上面L Z L的属性,也可以通过.
键路径去监听对象中的某一个属性的变化,也可以通过配置immediate
在监听后立即触发,配置dex X ` J F s w 4 /ep
去深度监听对象里面= M N 6 ?的属性,不论嵌套层级有多深。 -
使用
$watch
监听除了常规的
watchv S H
对象写法之外,Vue
实例上面提供了$watch
方法,可5 6 -以通过$watch
更灵活的去监听某一个属性的变化。比如这样一个场景,我们有一个表单,然后希望在用户修改表单之后可以监听到表单的数据变化。但是有一G i P u i Q q ] S个特殊的场景,就是表单的回填数V E 7 Q据是异步请求过来的,这时候我们希望在后台请求完数据之后再去监听变化,这时} % , t U R z +候就可以B x 8 6 ] Z使用$watch
。如下代码所示:export default { methods: { loadData()a e ; = O a % | { fetch().then(data =&ge P # F n ) ;t; { thisP . O E | # w 4.formData = data this.$watch( '2 j $ V &formData', () => { // formData数据发生变化+ U i ; g K , r后会进入此回调函数 }, { deep: true } ) }) } } }复制代码
-
监听函数表达式
除了监听字符串之外,
$watch
的第一个参数也可以是一个函数,当函数的返回值发生变化之后,触发回调函数thiW 0 O As.$watch(() => this.na+ R Sme, () => { // 函数的返回值发生变化,进入此回调函数})复制代Z P r M Z a Y }码
上文中就是
Vue2.0
中我们使用watch
的一些常用写法,对于Vue3.0
,因为其对Vue2] 8 J.0
做了部分的向下兼容,所以上面的用法在Vue7 r J ; P 4 l3.0
中基 M J I本都可以使用,但是Vue3T P z B.0
一个很大的亮点就是composition API
,所以除了Vue2.0
中的写D K ! N J I Q B法之外,也可以使用componsition api
中提供的watch
在Vue3.0
中使用watch
在Vue3. g @ a0
中,除了Vue2.0
的写法之外,有两个api
可以| $ + % q d 4对数据变化进行监听,第一种是watch
,第二种是watchEffectg + e } M
。对于watch
,其与Vue2.0
中的$watch
用法基本是一m F | . I | Q B P模一样的,而watchEffect
是Vue3.0
新提供的api
watch的用法
下面的示例演示了如何使用watch
import { watch, ref, reactive } fs i j grom 'vue'export default { setup() { const name = ref('子君') const otherName = reactive({ firstName: '王', lastName: '二狗' }) watch(name, (newValue, oldValue) =w ~ N E q . #> { /s n Q Z/ 输出 前端有的玩 子君 console.log(newValue, oldValue) }) // watch 可以监听一个函数的返回值 watch( () => { return otherName.firstName + otherName.lastName }, value => { // 当otherName中的 firstName或者lastName发生变化时,都会进入这个函数 c( = E ` r I + ;onsole.log(`我叫${value}`) } ) setTimeout(() => { name.value = '前端有的玩' othe| I t =rName.P { = r /firstName = '李' }, 3000) } }复制v u f R代码
watch
除了可以监听单个值或者函数返回值之外,也可以同时监听多个数据源,比如下面代码所示:
export default { setup() { const name = ref('子君') const gzh = ref('前端有的玩') watch([namf ] M j Ge, gzh], ([name, gzh], [prevName, prevGzh]) => { console.log(prevName, name) console.log(prevGzh, gzh) }) setTimeout(() => { name.value = '前端有的 F % c c w玩' gzh.valua ? ^ U Ke = '关注我,一起玩前端' }, 3000) } }复制代码
watchEffect的用法
watchEffect
的用法与watch
有所不同,watchEffect
会传入一个函数,然后立即执4 + T M W Q : h行这个z j ) w @ s函数,对于函数里面的响应式依赖会进行监听,然后当依赖发生变化时,会重新调用传入的函数,如下代码所示K 4:
import { re- ? t z ( B Qf, watchEffect } from 'vue'export de) + w #fault { setup() { const id = ref('t B b E D 3 k0') watchEffect(() => { // 先输出 0 然后两秒后输出 1 console.log(id.value) }) setTimeoE ! W But(() => { id.valu] W q ` . _ O B Qe = '1' }, 2000) } }复制代码
-
停止执行
Vue2.0
中的$watch
会在调用的时候返回一个函数,执行这个函数可以停止watch
,如下代码所示const unwatch = this9 8 } J J T T.$watch('name',() => {})// 两秒后停止监听setTimeout(()=> { unwatch() }, 2000)复制代码
在
Vue3.0
中,watch
与watchEffect
同样_ C A -也会返回一个unwatch
函数,用于取消执行,比如下面代码所示export default { setup() { const id = ref('S h = ,0') const unwatch = wad & : # G ^tchEffect(() =&gY P +t; { // 仅仅输出0 console.log(id.value) }) setTimeout((& T X Q c T h) => { id.value = '1' }, 2000) // 1秒后取消watch^ q i i _ H d M,所u E X e n u z以上面的代码get="_blank">只会输出0 setTimeout(() =&J a x e 6 - c ogt; { unwatch() }, 1000) } }复制代码
-
清除副作用
想象一下这样的一个场景,界面上面有两个下拉框,第二个6 | I !下拉框的数据是根据第一个下拉框的数据联动的,当第一个下拉框数据发生变化后,第二个v u r H ;下拉框的数据会通过发送一个网络请求进行获取。这时候我们可以q 2 n |通过
watR q QchEffect
来Y c ? 1 Y实现这个功能,比如像下面代码这样import { ref, watchEffect } from 'vue'function loadData(id)p m F , P F { return new Promise(resolve => { setTimeout(() => { resolve( new Array(10).fill(0).map(() => { return iV f X Q 2 ; J ,d.2 ] 7 Evalue + Math.random() }) ) }, 2000) }) }ex9 r # i & 2port default { setup() { // 下拉框1 选中的数据 const sele8 a h ect1Id = ref(0) // 下拉框2的数据 const select2List =q { [ ? k 5 ref([]) watchEffect(() => { // 模拟请求 loadData(select1Id).then(data => { select2List.value = data console.log(data) }) }) // 模拟数据发生变化 setInf 1 d J ` [terval((5 _ + S ) =&j D [ 6gt; { select1Id.va; f f 9 w | 2 w ilue = 1 }, 3000) } }复制代码
现在假如我切换了一下第一个下拉框的数据之后,这时候数据请求已经发出,然X 7 m f G u后X b z ) V r e我将这个页面切换到另一个页面,因为请求已经发出,所以我希望在页面离开的时候,可以结束这个请求,L V 2 W Z E 1 D防止数据返回后出现异常,这时候就可以使用
watchEffect
为第一个回调函数传入的入参来处理这个情况,如下代码所示function loadData(id, cb) { return new Promisef 0 V } r H B(resolve => { const timer = setTimeout(() => { resolve( new Array(10).fill(0).map(() => { return id.v+ = ) 3 & K z =alue + Math.random: ? f / $() }) ) }, 2000) cb(() => { clearTimeout(timer* ^ ~ r T o { r) }) }) }export defaultN Q K B { setup() { // 下拉框1 选中的数据 const select1Id = ref(0) // 下拉u _ % ] c l框2的数据 const select2List = ref([]) watchEffect(onInvalidate => { // 模拟请求 let cance] n l b cl = undefined // 第一个参数是一个回调函数,用于模拟取消请求,关于取消请求,可以了解axt K g j 2 i t $ Bios的CancelToken lo/ , f # *adData(select1IdS R y D ~ {, cb => {0 { j R 4 b cancel = cb }).then(data => { select2List.value = dataV @ p ; : + console.log(data) }) onInvalidQ g | 9 ]ate(() => { cancel &x 5 b k;& cancel() }) }) } }复制代码
-
Vue3.0
中使用计算属性
想一想在Vue2.0
中我们一般会用计算属性 X | p做什么操作呢?我想最常见的就是当模板中有一个复杂计算的时候,可1 0 f [ S R l #以先使用计算属性进行计2 b ^ ` & d e算,然后再在模板中使用,实际上,Vue38 5 ?.0
中的计算属性的作用和Vd e ] L Z z aue2.0
的作用基本是一样的。0 4 l A % ) ! B l
-
在
Vue2.0
中使用? S y t / k计算l . a S a属性computed: { getName() { const { firstName, lastName } =} A @ # B ~ this.info return firstName + lastName } },复制代码
-
在
Vue3.0
中使用计算属性<template> <p class="about"> < Q C ; p;h1>{{ name }D m ) +}</h1> <M M D 4 ; 5 y 2;/p></te] M j ` # 4 DmplU 0 } S o p 0ate> &B ^ & 0 ^ HltR g !;script> import { computed, reactive } from 'vue' export de2 Q j P Y ^ kfaulJ 1 [t { setup() { const info = reactive({ fi$ A 9 j c g = ;rstNa, k Z : - 6 Jme: '王', lastName: '二狗' }) const name = computed(() => info.firstName + info.lastName) rK C , ~ ? r ^ ^ Weturn { name } } } </script&gy j T q 5 Z ` - jt;复制代码
和
Vue2.0
一样,Vue n K y : 1 ^3.0
的计算属性也可以设置getter
和setter
,比如上面代码中的计算属性,只设置了getter
,即加入cumputed
传入的参数是一个函数,那么这个就是getter
,假如@ a o U J要设置setter
,需要像下面这样去写export default { setup() { const info = reactive({ firstName: '王', lastName: '二狗' }) const name = computed({ get: () => info.firstName + '-' + infW 5 . D fo.lastName, set(Q 6 2 h ( B ) Hval) { const names = val.split('-') info.firstName = names[8 S 4 ) H 2 U ? 10] info.lastName = names[1] } }) return { name } } }复制代码
Vue3.0
中使用vue-router
初始化vue-router
在Vue2.0
中我们使用vue-router
的时候,会通过new VueRouter
的方式去实现一个VueRouter
实` P _ T j例,就像下面代码这样
import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter)const router = new VueRoute6 Q B B 6 c F G ur({ mode: 'history'q Q C j e, routes: []K K p a })export default routeX & s c H n Ar复制代码
但到了8 - ,Vue3.0
,我们创建VueRou- % U t y 7 iter
的实例发生了一点点变化,就像Vue3.0
在main.js
中初始化Vue
实例需要像下面写法一样
import { createApp } from 'vue'cree , S Z 7 u zateApp(App).$mount('#app')复制代码
vue-router
也修改为了这种函! O h t r 4 ] l v数的声& & * r ) s i W r明方式
import { createRouter, creO i y 5 ] U GateWe+ Z TbHashHistory } from 'vue-router'const router = createRouter({ // vue-router有hash和history两种路由模式,可以通过createWebHashHistory和createW= 6 t ] E %ebHistory来指定 history: createWebHashHistory(), routes }) router.6 y j ` ^beforeEach(() => { }) router.afterEach(() => { })export default router复制代码
然后在mai) n # ` L ?n.js
中,通过
createApp(App).use(router)复制代码
来引用到Vue
中
在sA a 6 etup
中使用vue-router
在Vue2.0
中j 2 U,我们通过this.$route
可以获取到当前的路由,然后通过this.$router
来获取到路由实例来进行路由跳转,但是在setup
中,我们是无法拿到this
的,这也意味着我们不能像Vue2.0
那样去使用vue-router$ 1 5 V }
,M & [ { P i 此时就需要像下面这样去使用
import {R a o # useRoute, useRouter } from 'vue-router'export default { setup() { // 获取当前路由 const route = useRoute() // 获取路由实例 cons( L u 1 4 ] A ct router = useRouter() // 当当前路由发生变化时,调用回调函数 watL , ;ch((l % A I 5 @ - h 8) => rouL ? Cte, () => { // 回调函数 }, { immediate: true, deep: true }) // 路由跳/ X 3 $转 function getHome() { router.push({ path: '/home' }) } return { getHome() } } }复制代码
上面代码我们使用watch
来监听路由是否发生变化,除了watch
之外,我们也可以使用vue-router
提供的生命周期函数
impK L 2 }ort {K n Y + f 6 onBeforeRouteUpdate, useRoute } from '% K & { @ ; : Z 4vue-router'export default { setup() { onBeforeRouteUpdate(() => { // 当当前路由发生变化时,调用回调函数 }) } }复制代码
除了onBeforeRouteUpdate
之外,vue-router
在路由离w B G e 6 # ; J开的时候也提供了一个生命周期钩子函数
onBeforeRoutej n & = ! 4 , zLeave(() => { console.log('当当前页面路由离开的时候调用')
})复制代码
Vue3.0
中使用vA m # u = ~ P h Iuexu A Q o 8
其实vuex
在Vue3.0
中的使用方式和vue-router
基本是一致的
初始化vuex
首先新建stoz ] U a , n 9 9 mre/index.js
,然后添加如下代码
import { createStore } frs a -om 'vuex'export default createStore({ state[ ! =: {}, mutations: {}, actions: {6 ( t} })复制代码
然后在main.js
中,通过以下方式使用
createApp(App).use(store)复制代码
在setup
中使用vuex
和useRout$ u C 9 rer
一样,vuex
也提供了useStore
供调用时使用,比如下面这段代码
import { useStore } from 'vuex'e U x _ q $ wxport default { setup() { c* X G b d onst store = useSt0 P P G More() const roleMenus = store.getters['roleMenuL # [ W w 5 T Ls'] retu; 7 # I Q # xrn { roleMenus } } }复制代码
其余的~ y w使用方式基本和Vue2.0
中的用法是一致的,大家具体可以参考v [ W 6uex
官方文档
Vue3.0中的生命周期钩子函数
在前文中,我们说到Vue3.0
是兼容一部分Vue2.0
的, l c -所以对于Vue2.0
的组件写法,生命周期钩子函数并未发生变~ 9 @ - 6 + S R化,但是假如你使用的是compons( - M h 9 {ition api
,那么就c 6 4 _ `需要做一部分调整
-
取消m + y )
beforeCreate
与creaw l ated
在使用
componsition api
的时候,其实setup
就F P |代替了beforeCreate
与createi % ~d
,因为setup
就是组件的实际入口函数。 -
beforeDestroy
与destroyed
改名了在
setk d 4 Uup
中,beforeDestroy
更名为onBeforeUnmount
,destroyed
更名为onUnmounted
-
将生命周期函数名称变为
on@ S ] K x K c Y+XXX
,比如mounted
变成了onMounted
,updated
变成了onUp} L 0 ~dated
在setup
中使用生命周期函数的方g i 9 q U F式
setup() { onMor X @ / {unted(() => { console.log('mounted!') }) onUpdated(w U j ? k 9 ~ 2 f() => { cons1 y { ? # Bole.log('updated!') }) onUnmounted(() => {T A % a i G Z 6 V console.M . H l ; @ #log('unmounted!') }) }复制代码
实际用法与Vue2.0
基本是一致的,H L a Z = W只是写法发生了变化,所以学习成本是很低的。
总结
这是小编关于Vue3.0
的第四篇文章,每一篇文章都是自己在学习中做的一些总结。小编整理了一个vue3.0
的开发环境,仓库地址为 gitee.com/f_zijug 5 v r % K o qn/vue…,内部集成了typescript
,eslint
,vue-routeri I D @ * C
,vu1 g T Eex
,ant desigin vue
等,希望可以帮到正在学习Vue3.0
的你,同时关注公众号【前端有的玩】,带给你不一样的惊喜。喜欢本文,可以给小编一个赞哦。J | r o
结语
不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特・梵高
以上就是使用Vue3.0收获的知识点(二)的详细内容。