基于vue3的vue-router-next与vuex4的初体验

1,495 阅读4分钟

前言

国庆长假第5天,我们来接着玩 vue 3💪

上次我们初体验了 vue 3composition api 的基本用法。这次我们来试试还在 beta 测试版的 vue-router-nextvuex 4。链接如下:

插播一条最新消息:vue 的中文官网今天也上线了 vue 3 的中文文档。比英文文档晚了几个月啊。。。(所以学好英语能够抢先国内竞争对手好几个月,尤大大接受采访也表示自己半路出家,靠英语好才有今天的成就。)


demo

具体的介绍呢大家可以去查阅文档。routervuex 的用法发生了小小的变化,在 import 上支持了 vue 3 大力宣传的 tree shaking 机制,具体体现在创建实例和调用两个部分。这个demo使用了 composition api,而 setup 函数内部无法通过 this 获取当前 vue 实例,因此在用法上也有些许差别。

好了,废话不多说,直接上 demo。这次的 demo 依然基于v家最新基于 rollup 的打包工具 vite文档传送门。不过,同学们依然可以使用自己熟悉的 vue-cliwebpackvue 官方也给出了一个用 webpack 搭的简易demo,传送门,可以代替下面的 demo架子。具体方法就不在这里赘述了。来看一看 demo 的目录结构

└─src
    └─router
        └─index.js
    └─store
        └─index.js
    └─views
        ├─About.vue
        └─HelloWorld.vue
    ├─App.vue
    ├─index.css
    └─main.js

demo 中给出了两个页面:HelloWorld.vueAbout.vue。页面逻辑非常简单,HelloWorldAbout 页面各有一个相互跳转的链接,HelloWorld 页面有一个点击按钮,且两个页面共用了一个显示点击次数的 state

页面的 template

<!-- App.vue -->
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <router-view></router-view>
</template>
<!-- HelloWorld.vue -->
<template>
  <h1>HelloWorld</h1>
  <button @click="increment">count is: {{ count }}</button>
  <div>
    <button @click.prevent="toAboutPage">to About</button>
  </div>
</template>
<!-- About.vue -->
<template>
  <div>about</div>
  <div>count is: {{ count }}</div>
  <router-link :to="{name: 'HelloWorld'}">to HelloWorld</router-link>
</template>

依赖引入

npm install vue-router@next
npm install vuex@next

vue-router-next使用方法

vue-router不再通过 new VueRouter()的方式,而是通过 createRouter() 的方式创建。另外,路由模式选项名由 mode 改为了 historyhistory 模式传递createWebHistory()作为参数,hash 模式则传递 createWebHashHistory()作为参数。

// index.js
// * 引入vue-router相关方法
import { createRouter, createWebHistory } from 'vue-router'

// * 引入组件
import HelloWorld from '../views/HelloWorld.vue'
import About from '../views/About.vue'

// * 声明路由
const routes = [
  {
    path: '/',
    name: 'HelloWorld',
    component: HelloWorld
  },
  {
    path: '/About',
    name: 'About',
    component: About
  }
]
// 创建并向外暴露路由实例
export const router = createRouter({
  history: createWebHistory(),
  routes
})

在vue实例中使用 router 实例改为了以下方式:

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router/index'

createApp(App).use(router).mount('#app')

在单文件组件中使用router,分为 composition api 和 以前的 options api 两种方法。composition api 无法通过this拿到 vue 实例,因此需要引入 useRouteuseRouter 来获取当前router实例。具体方法如下:

import { useRouter, useRoute } from 'vue-router'
import { onMounted } from 'vue'

export default {
  name: 'HelloWorld',
  setup() {
    const router = useRouter()

    function toAboutPage() {
      router.push({
        name: 'About'
      })
    }
    onMounted(() => {
      console.log('route', useRoute())
    })
    return {
      toAboutPage
    }
  }
}

vuex 4使用方法

创建 vuex 实例有略微的变化,需要从 vuex 中引入 createStore 方法。这里需要注意,声明 state 最好传递一个 return 一个对象的函数,取代直接传递一个对象,就像 options apidata 的传参方式(忘记在哪个文档看到的了,但貌似vue 3中这个有必要)。我们定义了一个名为 countstate,一个让 count 自增的 mutation 方法和一个调用该 mutation 方法的 action 方法。

// index.js
import { createStore } from 'vuex'
// 创建并向外暴露vuex实例
export const store = createStore({
  state() {
    return {
      count: 1
    }
  },
  mutations: {
    countPlus(state) {
      state.count++
    }
  },
  actions: {
    increment({ commit }) {
      commit('countPlus')
    }
  }
})
// main.js 引入vuex实例
import { store } from './store/index'

createApp(App).use(store).mount('#app')

在单文件组件中,我们在 setup 方法中调用 state 需要引入 useState 方法,使用一个计算属性接收 count 这个 state,调用 dispatch和原来的方式差别不大。

import { useStore } from 'vuex'
import { computed } from 'vue'

export default {
  name: 'HelloWorld',
  setup() {
    const store = useStore()
    const count = computed(() => {
      return store.state.count
    })

    function increment() {
      store.dispatch('increment')
    }
    return {
      count,
      increment
    }
  }
}

补充

补充一点,使用 getCurrentInstance 方法,通过 ctx 属性也可以拿到 $router$store,如下:

import { onMounted, getCurrentInstance } from 'vue'
setup() {
  onMounted(() => {
    const instance = getCurrentInstance()
    // 打印来看看
    console.log(instance.ctx.$router)
    console.log(instance.ctx.$store)
  })
}

当然,我们一般是不会只为了拿$router$store就使用这个方法的。不同于vue 2 的 thisgetCurrentInstance 这种获取实例的方法被用于更复杂更高级的应用场景。具体可以参考官方文档