日日加班日日忙,需求袭来如虎狼。 测试问题堆如山,万念俱灰归故乡。
相关学习推荐:javascript
最近在工作之余一直学习vue3.0相关知识,虽然vue3.0至今还是rc版,但这并不影响我们去学习。今天这篇文章是我关于vue3.0的第四篇文章。在前文中我们讲解了如何通过vite和vuecli搭建vue3.0开发环境,然后介绍了vue3.0中的setup,reactive,ref等,今天这篇文章主要讲解了以下内容:
vue3.0中使用watchvue3.0中使用计算属性vue3.0中使用vue-routervue3.0中使用vuex开始本文前,小编提供了一个vue3.0开发环境,仓库地址为 gitee.com/f_zijun/vue…,欢迎使用。本文首发于公众号【前端有的玩】,这是一个专注于vue与面试相关的公众号,提升自己的市场竞争力,就在【前端有的玩】。同时点击以下链接即可访问小编关于vue3.0的其他相关文章
学习vue3.0,先来了解一下proxy
使用vite搭建一个vue3.0学习环境
使用vue3.0收获的知识点(一)
vue3.0中使用watchwatch在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的用法下面的示例演示了如何使用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的用法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中的生命周期钩子函数在前文中,我们说到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收获的知识点(二)的详细内容。