vue2 - vuex全局数据管理

135 阅读3分钟

我们日常网页中,登录总会需要的吧,那么登录后显示的自身图像logo+名称总会显示在页面右上角,表明我们正在登录状态中。

那么,便需要全局共享的变量来显示。

这里用vuex管理全局变量,其他定义全局变量的方法不是很常见。

我打算从看文档(开始 | Vuex (vuejs.org))开始,边看边测试,以及借用其他博主的力量,希望能把vuex学稳点。

唠唠嗑 vuex

官方解释:是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

我的感觉就是npm vuex之后,用它实例化创建一个仓库(store),然后在仓库里对数据进行管理,而且重点在于,它是全局且共享的(==在任何组件component都可以访问并且修改它),类似于单例模式;并且,最令人兴奋的一点是,它会在页面上响应式更新。

下载 vuex

ps:我用的开发工具为hbuilder,创建的是vue2项目。

npm install vuex@next --save

一开始美美的按照文档直接下载了最新版本(next可确保下载的是最新版本),但是这会出现版本冲突的问题。

vue和vuex版本对应问题_vuex和vue的版本关系-CSDN博客

vue3对应vuex4版本。

而vue2要对应vuex3版本。

npm install vuex@3 --save

ok,安装成功。

vuex 唠唠嗑项目结构

为了避免以后项目过大而导致store太大,还是推荐进行模块化store,也是说,每一个module都拥有自己的 state、mutation、action、getter。

这么说可能有点儿抽象,换句话说,当你创建一个购物平台项目的时候,你的后台数据库是咋样的,应该是很多个表吧,有管理用户登录注册的表,管理商品的表等等,那么,store也是一样的,它可以被分成很多个module,每个module分别管理不同表的数据状态。

但是呢,即使在不同的module中定义了各自的state、mutation、action、getter,如果你没有给它命名空间(类似给予它自己的名字给了它可以单独存在的空间),那么它们的mutation、action、getter还是全局的,只有state是局部的。我个人还是比较喜欢设置namespaced: true的,还是大家有点分界感,相互给自己独处的空间比较好,这样就意味着state、mutation、action、getter都是局部的。

image.png

ps:我用的开发工具为hbuilder,创建的是vue2项目。(再说明一次)

所以,我目前的项目结构是这样的:

image.png

好了,终于到激动人心的代码阶段了!

vuex - main.js

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import '@wangeditor/editor/dist/css/style.css'

//1-引入store文件
import store from './store'


Vue.config.productionTip = false

Vue.use(ElementUI);

//2-配置好store
new Vue({
  store, 
  render: h => h(App),
}).$mount('#app')

vuex - store/index.js

这里我假设弄的是教育平台,有登录信息表以及课程信息表。

import Vue from 'vue'
import Vuex from 'vuex' //1-引入vuex
import Login from './modules/login.js'//登录信息表
import Lesson from './modules/lesson.js'//课程信息表

Vue.use(Vuex)//2-在vue中使用vuex

export default new Vuex.Store({
//3-在这里配置好整体仓库中的各个表
  modules:{
	  Login,
	  Lesson 
  }
//这里可以创建全局信息表
state:{
	  name:'it\'s me'
  }
  
...(省略getter\mutation\action哈)
})

vuex - store/modules

登录信息表 /login.js

export default {
  namespaced: true, // 为当前模块开启独立的 命名空间
  state: {
  user:{
   username: 'aaa',
   password:'123456'
  }   
  },
  getters: {},
  mutations: {
    changeUser(state, user) {
      console.log(user);
      state.user = user;
    }
  },
  actions: {
    actChangeUser(context, user) {
      console.log(user);
      context.commit('changeUser', user);
    }
  }
}

课程信息表 /lesson.js

export default {
  namespaced: true, // 为当前模块开启独立的 命名空间
  state: {
   Les:{
       lname: '1',//课程名称
       lcategory:'2'//课程所属科目
   }

  },
  getters: {},
  mutations: {
    changeLes(state, les) {
      console.log(les);
      state.Les = les;
    }
  },
  actions: {
    actChangeLes(context, les) {
      console.log(les);
      context.commit('changeLes', les);
    }
  }
}

你可能会问,mutation是什么,action又是什么,目前为止,我是这样理解的,在mutation定义函数,然后在action中运行mutation函数更改state的值,而且还可以进行异步操作。

先这样简单理解,以后可能又会回来更改这个笔记。

找到一篇简洁的博主文章,说得很全面又详细。(前端 - 超详细!Vuex手把手教程 - 个人文章 - SegmentFault 思否

vuex - 在component中使用store

获得数据

法1-获得store的数据 - $store.state.

<template>
<div>
<p>{{tip}} </p>//网页显示 这里会显示state数据的值哦。
<p>{{$store.state.name}} </p> //网页显示 it‘s me
<p>{{$store.state.Lesson.Les}} </p>//网页显示 {"lname":"1","lcategory":"2"}
<p @click="show">点击在控制台显示获取store数据<p>
</div>
</template>

<script>
export default{
   data(){
    return{
     tip:'这里会显示state数据的值哦。'
    }
   },
   methods:{
   show(){
   console.log(this.$store.state.name);
   },
   }
}
</script>

<style>

</style>

法2-获得store的数据 - 用mapState获得

<template>
<div>
<p>{{tip}} </p>//网页显示 这里会显示state数据的值哦。
<p>{{$store.state.name}} </p> //网页显示 it‘s me
<p>{{$store.state.Lesson.Les}} </p>//网页显示 {"lname":"1","lcategory":"2"}

<p>{{Les}}</p>//网页显示 {"lname":"1","lcategory":"2"}

</div>
</template>

<script>
//1-引入mapState映射
import { mapState } from 'vuex'

export default{
   data(){
    return{
     tip:'这里会显示state数据的值哦。'
    }
   },
   //2-在copmuted中使用mapState映射函数
   computed: {
    //mapState默认会把state当第一个参数传进来
    ...mapState({
	   Les:state=>state.Lesson.Les
    })
			
   },
}
</script>

<style>

</style>

修改数据

这里我目前比较喜欢组件直接调用,如果是在mutation里头,我就用commit;如果是actions里头,我就用dispatch。

<template>
<div>
<p>{{tip}} </p>//网页显示 这里会显示state数据的值哦。

<p>{{Les}}</p>//一开始,网页显示 {"lname":"1","lcategory":"2"}

//之后会根据我点击了哪个按钮而改变Les中的值
<p>test1--mutation-commit</p>
<button @click="editLesByMutation">改变</button>
<p>test1--action-dispatch</p>
<button @click="editLesByAction">改变</button>

</div>
</template>

<script>
//1-引入mapState映射
import { mapState } from 'vuex'

export default{
   data(){
    return{
     tip:'这里会显示state数据的值哦。'
    }
   },
   //2-在copmuted中使用mapState映射函数
   computed: {
    //mapState默认会把state当第一个参数传进来
    ...mapState({
	   Les:state=>state.Lesson.Les
    })
			
   },
   methods:{
   editLesByMutation(){
    const Les={
     lname:'hello',
     lcategory:'我是由mutation修改的'
    }
     this.$store.commit('Lesson/changeLes',Les);//这里用透过路径进而可以访问到module中的mutation
   },
   
   editLesByAction(){
     const Les={
      lname:'hello',
      lcategory:'我是由action修改的'
    }
     this.$store.dispatch('Lesson/actChangeLes',Les);//这里用透过路径进而可以访问到module中的action
   },
   },
}
</script>

<style>

</style>

好了,学习vuex就这样先告一段落了把,现在要去干点正事了,赶紧把需求完成。

image.png