日日加班日日忙,需求袭来如虎狼。 测试问题堆如山,万念俱灰归故乡。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
的你,同时关注公众号【前端有的玩】,带给你不同的惊喜。喜欢本文,能够给小编一个赞哦。
不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特・梵高