Vue3.0来袭,你想学的都在这里(二)

日日加班日日忙,需求袭来如虎狼。 测试问题堆如山,万念俱灰归故乡。javascript

最近在工做之余一直学习Vue3.0相关知识,虽然Vue3.0至今仍是rc版,但这并不影响咱们去学习。今天这篇文章是我关于Vue3.0的第四篇文章。在前文中咱们讲解了如何经过vitevuecli搭建Vue3.0开发环境,而后介绍了Vue3.0中的setup,reactive,ref等,今天这篇文章主要讲解了如下内容:前端

  1. Vue3.0中使用watch
  2. Vue3.0中使用计算属性
  3. Vue3.0中使用vue-router
  4. Vue3.0中使用vuex

开始本文前,小编提供了一个Vue3.0开发环境,仓库地址为 gitee.com/f_zijun/vue…,欢迎使用。本文首发于公众号【前端有的玩】,这是一个专一于Vue面试相关的公众号,提高本身的市场竞争力,就在【前端有的玩】。同时点击如下连接便可访问小编关于Vue3.0的其余相关文章vue

学习Vue3.0,先来了解一下Proxyjava

使用vite搭建一个Vue3.0学习环境react

使用Vue3.0,我收获了哪些知识点(一)ios

Vue3.0中使用watch

watchVue3.0中并非一个新的概念,在使用Vue2.x的时候,咱们常常会使用watch来监听Vue实例上面的一个表达式或者一个函数计算结果的变化。git

回顾Vue2.0中的watch

Vue2.0中,咱们使用watch能够经过下面多种方式去监听Vue实例上面的表达式或者函数计算结果的变化,以下罗列了其中的几种面试

  1. 最常规使用方式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

  2. 使用$watch监听

    除了常规的watch对象写法以外,Vue实例上面提供了$watch方法,能够经过$watch更灵活的去监听某一个属性的变化。好比这样一个场景,咱们有一个表单,而后但愿在用户修改表单以后能够监听到表单的数据变化。可是有一个特殊的场景,就是表单的回填数据是异步请求过来的,这时候咱们但愿在后台请求完数据以后再去监听变化,这时候就可使用$watch。以下代码所示:

    export default {
      methods: {
        loadData() {
          fetch().then(data => {
            this.formData = data
            this.$watch(
              'formData',
              () => {
                // formData数据发生变化后会进入此回调函数
              },
              {
                deep: true
              }
            )
          })
        }
      }
    }
    复制代码
  3. 监听函数表达式

    除了监听字符串以外,$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用法基本是如出一辙的,而watchEffectVue3.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)
  }
}
复制代码
  1. 中止执行

    Vue2.0中的$watch会在调用的时候返回一个函数,执行这个函数能够中止watch,以下代码所示

    const unwatch = this.$watch('name',() => {})
    // 两秒后中止监听
    setTimeout(()=> {
      unwatch()
    }, 2000)
    复制代码

    Vue3.0中,watchwatchEffect一样也会返回一个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)
      }
    }
    复制代码
    1. 清除反作用

      想象一下这样的一个场景,界面上面有两个下拉框,第二个下拉框的数据是根据第一个下拉框的数据联动的,当第一个下拉框数据发生变化后,第二个下拉框的数据会经过发送一个网络请求进行获取。这时候咱们能够经过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的做用基本是同样的。

  1. Vue2.0中使用计算属性

    computed: {
        getName() {
          const { firstName, lastName } = this.info
          return firstName + lastName
        }
      },
    复制代码
  2. 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的计算属性也能够设置gettersetter,好比上面代码中的计算属性,只设置了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.0main.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

其实vuexVue3.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,那么就须要作一部分调整

  1. 取消beforeCreatecreated

    在使用componsition api的时候,其实setup就代替了beforeCreatecreated,由于setup就是组件的实际入口函数。

  2. beforeDestroydestroyed 更名了

    setup中,beforeDestroy改名为onBeforeUnmount,destroyed改名为onUnmounted

  3. 将生命周期函数名称变为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的你,同时关注公众号【前端有的玩】,带给你不同的惊喜。喜欢本文,能够给小编一个赞哦。

结语

不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特・梵高

相关文章
相关标签/搜索