亲宝软件园·资讯

展开

Vue3 中的 Vue-Router 和 VueX详解

John是橘红 人气:0

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>

加载全部内容

相关教程
猜你喜欢
用户评论