Vue3 中的 Vue-Router 和 VueX详解
作者:John是橘红
Vue3 中的 Vue-Router 和 VueX
先使用 vue create 指令来创建 vue 工程项目,并选择自定义,将 Router 和 VueX 勾上。
勾上以后看主入口 main.js,可以看到项目自动帮我们注册了 vue-router 和 VueX。
// main.js createApp(App).use(store).use(router).mount('#app')
1. Vue-Router 路由的理解和使用
路由是指根据 url 的不同,展示不同的内容。
查看 src 文件夹里的 router,这就是来处理路由的地方。
其中,index.js 有关键的代码
const routes = [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue') } ]
定义了两个路由项。当访问根目录,就加载 HomeView 这个组件。如果访问 /about
,则懒加载 AboutView 这个组件。
import(...)
是异步加载路由的方法。因为如果一口气全部组件加载出来,主页的加载的性能将会很低,为了提高组件的加载性能,使用懒加载按需加载,等进入 /about 或其他的页面再加载响应部分的代码。但是异步加载代码也有相应的问题,就是去其他的页面可能会有卡顿(其实就是加载的时间分摊了)。
因此,vue-router 就是根据 url 不同来显示不同组件的特性。
现在查看根组件 App.vue,上面有关键的代码:
<template> <nav> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </nav> <router-view/> </template>
router-link 是跳转路由的标签,点击后就会跳转到相应的路由。
router-view 负责展示当前路由对应的组件内容。例如上面的代码,当跳转到根路径上时,router 会进行搜索,当搜索到匹配项时,便显示相应的组件 HomeView。
2. VueX 语法详解
在文首就看到了,注册了 VueX,接下来看 src 的 store 目录,这里边的 index.js 可以看到以下内容,稍后会讲。
export default createStore({ state: { }, getters: { }, mutations: { }, actions: { }, modules: { } })
2.1 VueX 是什么
VueX 是数据管理框架。之前的数据传递都是父子之间的传递,虽然也有 provider 之类的方法进行跨级传递,但是可维护性也不会特别高。
VueX 提供了一个全局都可以使用的数据管理仓库,不用考虑父子传值之类的问题,并且可以跨页面传递数据。提高了可维护性。
使用方法
提供数据:在 store 里的 state 里定义一些数据
// VueX 创建了一个全局唯一的仓库,用来存放全局的数据 export default createStore({ state: { name: "John", }, getters: { }, mutations: { }, actions: { }, modules: { } })
在需要用数据的地方通过 this.$store
获取即可
<template> <div>{{ myName }}</div> </template> <script> export default { name: "LoginView", computed: { myName() { return this.$store.state.name; }, }, }; </script>
2.2 VueX 数据修改流程
讲一下 VueX 的修改规范,因为全局的数据是不能随意更改的,因此 VueX 有一套机制流程,并不能直接用赋值的方法进行修改。
修改流程
在组件里提交一个 action 到 store,dispatch 的第一个参数是 action 名称,后面可自定义参数。
// LoginView.vue <template> <div>{{ myName }}</div> <button @click="handleClick">click</button> </template> <script> export default { name: "LoginView", computed: { myName() { return this.$store.state.name; }, }, methods: { handleClick() { // 1. 想改变数据,VueX 要求第一步,必须派发一个 action,action 名称为 actions 里的方法名 this.$store.dispatch("change"); }, }, }; </script>
store 感知到 action,执行 actions 下面对应的方法
actions 对应的方法 commit 信息后传递给 mutations。commit 的信息为 mutations 里的方法名。
mutations 里对应的方法执行修改数据的操作。
import { createStore } from "vuex"; // VueX 创建了一个全局唯一的仓库,用来存放全局的数据 export default createStore({ state: { name: "John", }, getters: { }, mutations: { // 4. 接收到 commit 信息后,触发对应的 mutation change(state) { // 5. 在 mutation 里修改数据 state.name = "Modified Name"; }, }, actions: { // 2. 接收到 action 后执行相应的方法 change(store) { // 3. commit 后发送给 mutations store.commit("change"); }, }, modules: {}, });
从上面的流程来看,VueX 创建了一个全局唯一的仓库,用来存放全局的数据,同时里面设置了一系列的数据操作流程。
这流程下来有点麻烦啊,为啥不直接 commit 过去呢?同步代码看起来是如此,但是如果有异步操作的话,这些步骤就很有必要了。
注意mutations 和 actions 里的方法第一个参数各不相同。
actions 里面第一个参数是 store,因为需要用 store.commit 方法来提交给 mutations。
mutations 里边的方法第一个参数是 state,因为 store 是用来修改 store 里 state 的方法。
可见,vue 官方在代码层面都是推荐分离的。
其他细则 mutations 里面只允许写同步代码,不许写异步代码actions 里面允许写异步操作
优点在于,将两种功能分离,mutations 里做数据的改变,actions 里做主要的逻辑书写,维护的时候会更加方便。
getter 是啥
store 里的数据有时候并不能直接拿来用,还需要经过一些小处理。一般就会想,在组件内处理不就完事了?但是呢,万一有很多的组件都有着需求呢,挨个写就不合适。getter 就相当于 store 里的 computed 属性,对 state 进行了一定的处理。
使用方法:
设置 getter
getter 接收两个参数,然后返回一个值。
state,必选,是 store 里的数据getters,可选,是 store 里的所有 getters
例如,我要计算得到大写后的 name:
// store/index.js getters: { upperCasedName: (state) => { return state.name.toUpperCase(); } },
组件获取 store 里的 getter
<template> <div>{{ upperCasedName }}</div> <button @click="handleClick">click</button> </template> <script> export default { name: "LoginView", computed: { upperCasedName() { return this.$store.getters.upperCasedName; }, }, methods: { handleClick() { // 1. 想改变数据,VueX 要求第一步,必须派发一个 action this.$store.dispatch("change"); }, }, }; </script>
通过 computed 获取到 getter 后,点击按钮改变了 store 里的 name,上边显示的仍然是大写的,因为获取的是全部字母大写后的 name。
2.3 Composition API 使用 VueX
composition API 使用 useStore 获取 store 即可。
<template> <div>{{ name }}</div> </template> <script> import { useStore } from "vuex"; export default { name: "LoginView", setup() { const store = useStore(); const name = store.state.name; return { name, }; }, }; </script>
用 toRefs 解构的方法也行:
<template> <div>{{ name }}</div> <button @click="handleClick">Click</button> </template> <script> import { toRefs } from "@vue/reactivity"; import { useStore } from "vuex"; export default { name: "LoginView", setup() { const store = useStore(); const { name } = toRefs(store.state); const handleClick = () => { store.commit("changeName"); }; return { name, handleClick, }; }, }; </script>
到此这篇关于Vue3 中的 Vue-Router 和 VueX的文章就介绍到这了,更多相关Vue3 中的 Vue-Router 和 VueX内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!