前言
国庆长假第5天,我们来接着玩 vue 3💪
上次我们初体验了 vue 3 的 composition api 的基本用法。这次我们来试试还在 beta 测试版的 vue-router-next 和 vuex 4。链接如下:
- github
- 文档
插播一条最新消息:
vue的中文官网今天也上线了vue 3的中文文档。比英文文档晚了几个月啊。。。(所以学好英语能够抢先国内竞争对手好几个月,尤大大接受采访也表示自己半路出家,靠英语好才有今天的成就。)
demo
具体的介绍呢大家可以去查阅文档。router 和 vuex 的用法发生了小小的变化,在 import 上支持了 vue 3 大力宣传的 tree shaking 机制,具体体现在创建实例和调用两个部分。这个demo使用了 composition api,而 setup 函数内部无法通过 this 获取当前 vue 实例,因此在用法上也有些许差别。
好了,废话不多说,直接上 demo。这次的 demo 依然基于v家最新基于 rollup 的打包工具 vite,文档传送门。不过,同学们依然可以使用自己熟悉的 vue-cli 和 webpack。vue 官方也给出了一个用 webpack 搭的简易demo,传送门,可以代替下面的 demo架子。具体方法就不在这里赘述了。来看一看 demo 的目录结构:
└─src
└─router
└─index.js
└─store
└─index.js
└─views
├─About.vue
└─HelloWorld.vue
├─App.vue
├─index.css
└─main.js
demo 中给出了两个页面:HelloWorld.vue 和 About.vue。页面逻辑非常简单,HelloWorld 和 About 页面各有一个相互跳转的链接,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 改为了 history。history 模式传递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 实例,因此需要引入 useRoute 和 useRouter 来获取当前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 api 中 data 的传参方式(忘记在哪个文档看到的了,但貌似vue 3中这个有必要)。我们定义了一个名为 count 的 state,一个让 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 的 this,getCurrentInstance 这种获取实例的方法被用于更复杂更高级的应用场景。具体可以参考官方文档