VUE3 项目开发实战入门系列 (8.-Vuex 4)

633 阅读3分钟

Vuex 4

​ Vuex是什么?官方的解释是Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,通俗一点来说就是有数据需要全局共享(比如在多个组件都有引用),那么就可以使用Vuex来统一管理,Vuex数据是响应式的,数据的更新会触发组件更新,这点和组件内data一样。只不过这是一个全局的data。

​ Vuex4是Vue3的版本,就好像Vuex3之于Vue2一样,官方网站

章节内容

  1. 安装Vuex4
  2. 创建store目录
  3. 添加API目录
  4. 登录接口
  5. 测试登录页

安装Vuex4

npm install vuex@next --save

创建store目录

​ 和Vue2一样,需要创建一个单独的目录的管理store文件,在src目录下创建store文件夹,并且新建文件如下:

- src
	- store
		- modules 		// 存放模块文件的文件夹
			- user.js	// 用户模块文件
		- index.js

​ 这里我们用登录来举个例子,一般情况下登录后需要保存token和用户信息到store(后面提到的store就是vuex),因为用户信息在应用里是很多地方都是会用到的。

创建store对象 src/store/index

import { createStore } from 'vuex'
import user from './modules/user'

const store = createStore({
    modules: {
        user
    }
})

export default store;

上面导入了modules下的user文件,我们接着来完善该文件内容 src/store/modules/user.js

import { loginApi } from "@/api/user";

const user = {
    namespaced: true,

    state: {
        // access token
        token: "",
        // 用户信息
        info: {}
    },
    
    getters: {},

    mutations: {
        SET_TOKEN (state, token) {
            state.token = token;
        },
        SET_INFO (state, user) {
            state.info = user;
        }
    },

    actions: {
        login ({ commit }, data) {
            return new Promise((resolve, reject) => {
                loginApi(data).then(res => {
                    const {data} = res.data;

                    if(data && data.token && data.user) {
                        // 把用户信息保存到state
                        commit("SET_TOKEN", data.token);
                        commit("SET_INFO", data.user);
                    }
                    
                    resolve(res);
                }).catch(err => {
                    reject(err);
                })
            })
        }
    }
}

export default user;

​ 有Vue2经验的同学应该很看出这文件结构和上一版本的Vuex完全是一摸一样的,如果要查看详细的区别请查看这里,最后还需要在store挂载到app,这样store就添加成功了。

src/main.js

// 导入store
import store from "@/store/index"

app.use(store)

和之前的router差不多,自行添加到对应位置即可。

​ 注意store/modules/user.js代码的第一行是有导入api目录的,并且暴露了一个loginApi方法, 这里api目录的主要作用是方便应用统一的管理请求接口,例子里我们使用了登录作为案例,所以就放入到user模块中,下面来新建该目录。

添加API目录

新建api目录统一管理请求接口 src/api/user.js

import { request } from "@/setup"

export function loginApi(data) {
    return request({
        url: "/api/login",
        method: "POST",
        data
    })
}

​ 这里代码第一行我们导入了一个request函数,这是我们之前封装的axios,但是之前的封装里并没有暴露独立方法,所以要稍微做下修改。

src/setup/index.js

import HttpRequest from "@/utils/httpRequest"

function useRequest() {
    const httpRequest = new HttpRequest({
        // 你的axios基准路径, https://vitejs.dev/guide/env-and-mode.html
        baseURL: import.meta.env.MODE === "development" ? "" : "http://127.0.0.1:5000"
    });
    // 自定义异步请求错误处理
    httpRequest.useErrorHandles(error => {
        console.log(error.response)
    })
    return httpRequest.createRequest();
}
// request请求方法
export const request = useRequest();

function setupRequest(app) {
    // 绑定$request属性到Vue原型,类似Vue.prototype。
    app.config.globalProperties.$request = request;
}

const setup = {
    install(app) {
        setupRequest(app);
    }
}

export default setup;

这里我们就可以在组件中调用this.$request,也可以在其他地方导入request了。

关于接口url: "/api/login",在上一章节里刚好搭建了mock数据环境,那接下来新增一个POST类型的登录接口

登录接口

在mock目录添加user文件 mock/user.js

const Mock = require('mockjs')

export default [
    {
        url: '/api/login',
        method: 'POST',
        response: ({ body }) => {
            // 如果用户名和密码都是admin,则登录成功
            if(body.username === "admin" && body.password === "admin") {
                return Mock.mock({
                    code: 0,
                    message: 'ok',
                    type: 'success',
                    // data里包含了token和user信息,这里要根据实例情况判断,并不是每个接口都是这么设计的
                    data: {
                        token: "@paragraph( 18 )",
                        user: {
                            id: '@integer(0, 100)',
                            realname: '@cname( 4 )',
                            role: 'administrator'
                        }
                    }
                })
            } else {
                return {
                    code: 1,
                    message: "fail",
                    type: "error",
                    data: null
                }
            }
        }
    }
]

测试登录页

​ 当然这里并不是真正的测试。而且在登录页进行实际的调用,我们会在下一节引入jest编写单元测试。

​ 编辑登录页src/views/login.vue

<template>
  <div>
    <h2>登录页 - by ctcode</h2>
    <a-form layout="inline" :model="formData" @finish="onFinish(formData)">
      <a-form-item>
        <a-input
          v-model:value="formData.username"
          placeholder="用户名"
        />
      </a-form-item>
      <a-form-item>
        <a-input 
        v-model:value="formData.password" 
        type="password"
        placeholder="密码" />
      </a-form-item>
      <a-form-item>
        <a-button type="primary" html-type="submit"> 登录 </a-button>
      </a-form-item>
    </a-form>
  </div>
</template>

<script>
import { reactive } from "vue";
import { useStore } from "vuex";
import { message } from "ant-design-vue";

export default {
  setup() {
    const store = useStore();
    
    // 声明响应表单数据对象
    const formData = reactive({
      username: "",
      password: "",
    });

    /**
     * 请求登录函数
     * @param {object} data
     */
    async function onFinish(formData) {
      const result = await store.dispatch("user/login", formData);
      const { data, type } = result.data;

      // 登录后结果处理,这里要根据后台接口实际的返回进行处理
      if(type == "success") {
        message.success(`登录成功:欢迎${data.user.realname}`)
      } else {
        message.error("登录失败!")
      }
    }

    return {
      formData,
      onFinish,
    };
  }
};
</script>

页面效果如下:

image20210225182448711.png

页面的内容相比之前复杂了点,相关代码都是来自于组件库form组件,主要是实现一个登录的表单,表单提交后通过store.dispatch调用store/mudules/user.js下的actions方法进行登录操作,然后打印返回接口返回结果。

我们在mock接口里已经设置了账号密码都是admin,名字是随机的,现在去登录试下吧。

image20210225182906408.png

查看代码:

git clone https://github.com/chitucode/ctcode-vue3.git (已下载可直接checkout)
git checkout v8.0 

好友微信号

添加大佬微信 和上千同伴一起提升技术交流生活

hsian_

最后

码字不容易 你的点击关注点赞留言就是我最好的驱动力