在第一版初步实现cnode的基本功能后,本来是用本地存储的存储用户登录成功返回的用户的基本信息,用于后面的回复功能,查看信息等操作需要的用户基本信息的数据。但是总的来说感觉本地储存的方案不太理想(个人想法),所以想引入vuex来存储用户信息,还有一些跨组件的状态和数据。
简单的介绍一下我理解的vuex是什么东西,因为我们知道vue的组件子父之间是可以同过props实现数据的单向和双向传递,但是我们可能经常遇到的业务场景是一个组件的状态发生改变需要在另一个与他不相关的组件进行响应,这个时候如果我们没做全局变量就没办法搞了,所以说vuex总的来说就是一个全局的状态管理。(我是这么认为的)
关于vuex的基本用法请参见 中文API
现在直接上手实现一个功能把登录成功的用户信息保存在vuex中,这个功能是基于你看过文档并初步了解了vuex,知道state,mutation這些基本概念,由于API的文档中的例子只是个简单的demo,所以我写了这个功能更贴切一个项目中实际的场景。(这里就不介绍那些基础概念了,因为API肯定介绍得比我详细)
建立一个文件 store.js代码如下。state定义需要状态的参数变量,mutation(状态变更)用于改变state的状态,注意vuex中是不能直接改变state中的状态的,一定要借助于mutation的事件分发。mutation的方法可以第一个参数一定是state,后面也可以选择带参,两种本例子下面都有定义。
"use strict"; import Vue from 'vue' import Vuex from 'vuex'; Vue.use(Vuex); const state = { // 页面打开默认设置登录状态为否 isLogin : false, // 保存登录信息 userInfo : { 'loginname' : '', 'avatar' : '', 'id' : '', 'accesstoken' : '' } } const mutations = { // 设置登录 ISLOGIN (state) { state.isLogin = true; }, // 设置登录用户信息 SETUSERINFO (state, name, avatar, id, accesstoken) { state.userInfo.loginname = name; console.log(state.userInfo.loginname); state.userInfo.avatar = avatar; state.userInfo.id = id; state.userInfo.accesstoken = accesstoken; } } export default new Vuex.Store({ state, mutations })
建立一个action.js代码如下,用于用户分发mutation的事件。可能有些人会疑惑为什么要多写这个文件来分发mutation的事件,是应为我们的mutation必须是同步执行,如果在mutation中进行回调,根本就无法确定到底什么时候能执行那个回调函数。而在action中进行事件的分发就可以进行异步操作。
/** *修改用户登录状态为已经登录 **/ export const isLogin = ({dispatch}) => { dispatch('ISLOGIN'); } /** *设置用户的登录信息 *参数 name用户名 avatar用户头像 id用户id accesstoken用户登录标识 **/ export const setUserInfo = ({dispatch}, name, avatar, id, accesstoken) => { dispatch('SETUSERINFO', name, avatar, id, accesstoken); }
建立一个getters.js代码如下,用户用户获取state中的状态。
//获取用户的登录状态 export const getLoginState = (state) => { return state.isLogin; } //获取登录用户的信息 export const getUserInfo = (state) => { return state.userInfo; }
这里注意一点在子父组件中调用vuex区别的一点是父组件一定要定义store:store,子组件随意。
import store from '../vuex/store'; import nvHeader from '../components/header.vue'; import {isLogin, setUserInfo} from '../vuex/actions'; export default { data : function(){ return { strToken : '' } }, methods : { login : function() { let rqdata = { 'accesstoken' : this.strToken } $.post('https://cnodejs.org/api/v1/accesstoken', rqdata, (data) => { if(data){ // 登入成功改变isLogin的状态为true this.userLogin(); console.log(this.userLoginState); this.setUserInfo(data.loginname, data.avatar_url, data.id, this.strToken) window.history.back(); }else{ // 失败 } }) } }, components : { 'nv-header' : nvHeader }, store : store, vuex : { actions : { userLogin : isLogin, setUserInfo : setUserInfo } } }
我们在login.vue这个组件中调用了子组件header.vue这个组件,在header.vue组件中又调用了menu.vue这个组件,而在menu这个组件中有一块用户信息是我们登录了才会去显示当前登录用户的基本信息,这就要从store中去获取状态啦,而我们之前登录成功应景对store的状态进行了更新,menu.vue中应该自动响应,把用户信息展示出来
<template> <div class="meun" :class="{'showMeun':showm}"> <div class="user_info" v-if="userLoginState"> <div class="avatar"> <img :src="user_avatar" alt=""> </div> <div class="name"> <p v-text="user_name"></p> </div> </div> <ul> <li v-link="{name:'home'}">首页</li> <li v-link="{name : 'search'}">搜索</li> <li v-link="{name : 'login'}" v-if="!userLoginState">登录</li> <li v-if="userLoginState">未读消息</li> <li v-if="userLoginState">设置</li> <li v-link="{name : 'about'}">关于</li> </ul> </div> </template> <script> import store from '../vuex/store'; import {getLoginState, getUserInfo} from '../vuex/getters'; export default { props : ['showm'], data : function() { return { user_name : this.getUserInfo.loginname || '', user_avatar : this.getUserInfo.avatar || '' } }, vuex : { getters : { userLoginState : getLoginState, getUserInfo : getUserInfo } } } </script>
ok,这个登录显示用户信息的基本功能就实现了。当然还有许多的地方可以用到vuex,比如说在本项目的弹窗组件也用到了vuex,来根据具体情境显示对应的提示文本。本人重构的 Cnode 项目也在逐渐的完善,如果觉得本篇文章对你有收获可以star支持一下,谢谢!
tip:线上demo在浏览器切换为移动端模式下访问效果更佳