好久没有写文章了,感觉自己就这样稀里糊涂的过了好久了。最近在研究小程序 本来想等小程序有所得之后再来写点什么。但是发现自己研究来研究去 ,感觉没没有什么好写的。但是又不想丢弃掉自己写作的一个习惯。刚好前段时间在重构代码的时候,发现了之前封装代码的时候出现了很多的奇怪的写法,和很多之前没考虑到的漏洞,多少还是有点心得的,写下这个文章呢?和大家交流一下
一、 为什么要用vuex
首先我们谈到一个技术肯定是要从以下几个方面来进行探究的:
- 什么情况下要用这项技术
- 这项技术相对于其他技术的优势
我这里呢?就从这两个方面来开始,逐次、深层次的介绍vuex。
首先现今几大主流的框架:react,vue,angluar包括小程序,无以复加的都提出一个组件化的思想。这样做的好处是:高内聚、可重用、可互换、可组合等优势,但同时也在开发中带来了许多新的问题,其中最重大的研究课题是: 组件间的通信 。
前端也差不多开发了一年半的时间了,主流的几种vue的组件间传递信息的方式,无非有以下几种:
1、 通过
$emit
和
props
在父子组件中进行数据传递。
2、 用eventbus(全局事件)在中进行传递。
3、 利用localstorage、sessionstorage等存储手段来进行传递。
毫无疑问,这些个方式都能完成我们所要的需求。但是在某种程度上面或多或少都有一些问题。例如:
1、 利用
$emit
和
props
在兄弟关系嵌套比较深的情况之下,代码书写量将会大大的增加。
2、 全局事件在使用的时候可能被被多次触发、销毁时机掌握等等一系列的问题,同时作为全局事件所有页面都能监听、掌控事件可能会存在安全性问题等等...
3、 ...
既然前面说了这么多其他技术的坏话,现在就要来介绍一下今天文章的主角了。 vuex --是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
首先来明确几个概念: 一、状态管理模式
上面是一个vue简单的状态管理应用,其中应该包含有:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
当然上面只是一个最简单的“单向数据流”的示意图。但是当我们存在很多的组件嵌套的时候,可能会存在这样几个问题:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
显然用前面的哪几个技术可能会将页面的状态变得更加复杂和代码逻辑繁琐,不利于代码的维护和深层次开发。在这种大环境下面,设计师们专门为vuex设计了一款状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。
二、 vuex的简单介绍
说到vuex的介绍呢?我们就先从代码的引入开始:
npm install vuex --save
复制代码
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
export default new Vuex.Store({
state,
getters,
mutations,
actions
})
复制代码
最后再main.js中:
import store from "./store"
var app=new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
复制代码
看了上面的代码,首先来解释一下:new Vuex.Store({}) 表示创建一个Vuex实例,通常情况下,他需要注入到Vue实例里. Store是Vuex的一个核心方法,字面上理解为“仓库”的意思。Vuex Store是响应式的,当Vue组件从store中读取状态(state选项)时,若store中的状态发生更新时,他会及时的响应给其他的组件(类似双向数据绑定) 而且不能直接改变store的状态,改变状态的唯一方法就是,显式地提交更改(mutations选项)
上面就将vuex的四个核心选项:state mutations getters actions说了出来。
2.1、 state:
首先是
state
,如何来获取state的值呢?一般是将这个值放置在computer里面,这样的话一旦数据发生改变的时候,就反馈到页面上面去。代码如下:
// state_name:klivitam
<template>
<div>
{{username}}
</div>
</template>
<script>
export default {
computed:{
username(){
return this.$store.state.name;
}
}
}
</script>
复制代码
state总结
:用来存放组件之间共享的数据。他跟组件的data选项类似,只不过data选项是用来存放组件的私有数据。
2.2、 getters:
其次是
getters
,来看下面一段代码:
vuex里面的代码
import Vue from "vue";
import Vuex from "vuex"
let state = {
name:"klivitam"
}
let getters = {
getName(state){
return `我的名字是:${state.name}`;
}
}
let mutations = {}
let actions = {}
Vue.use(Vuex)
export default new Vuex.Store({
state,
getters,
mutations,
actions
})
复制代码
vue内的代码:
<template>
<div>
{{username}}
</div>
</template>
<script>
export default {
data(){
return{
message: '我是一个菜鸟',
}
},
computed:{
username(){
return this.$store.getters.getName;
}
}
}
</script>
复制代码
chrome页面的效果图:
getters总结:
getters主要是用来过滤和重组。这些事件最好也是能在计算属性中完成,用于监听事件变化的。
2.3、mutations:
来看下面一段代码: vue代码:
<template>
<div>
{{username}}
<div>
<button @click="change">更改我的昵称</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
message: '我是一个菜鸟',
}
},
methods:{
change(){
this.$store.commit("changeName","jkb...")
}
},
computed: {
username() {
return this.$store.getters.getName;
}
}
}
</script>
复制代码
store代码:
let mutations = {
changeName(state,name){
state.name = name;
}
}
复制代码
点击后效果:
mutations总结
:在 Vuex store 中,实际改变 状态(state) 的唯一方式是通过 提交(commit) 一个 mutation。mutations下的函数接收state作为参数,两一个参数叫做payload(载荷),payload是用来记录开发者使用该函数的一些信息,比如说提交了什么,提交的东西是用来干什么的,包含多个字段,所以载荷一般是对象(其实这个东西跟git的commit很类似)还有一点需要注意:mutations方法必须是同步方法!
2.4、 actions:
来看下面一段代码: vue的代码:
change(){
this.$store.dispatch("changeName","jkb...")
}
复制代码
store的代码:
let mutations = {
changeName(state,name){
state.name = name;
}
}
let actions = {
changeName({commit},name){
let timer = setTimeout(()=>{
commit("changeName",name);
clearTimeout(timer);
},1000)
}
}
复制代码
actions总结
:actions的作用其实和mutations是没有差别的,无非就是一个同步、异步的差别罢了。而在功能上面主要有一下两个区别:
- actions 提交的是 mutations,而不是直接变更状态。也就是说,actions会通过mutations,让mutations帮他提交数据的变更。
- actions 可以包含任意异步操作。ajax、setTimeout、setInterval不在话下。
最简单的使用,其实也就这些 但是很可能会存在很多深沉次的思考,接下来 我就趁热打铁,写一写vuex深沉次的思考。
三、 vuex的深层次思考
关于深层次的思考,我也做了这么久了。我其实主要的考量有两个地方:
- 当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。
- 当页面的属性过多的时候,代码的可维护性下降。
针对上面的情况,我从这俩个切入点 说说我的想法:
1、 页面计算属性重复和冗余问题:
关于页面计算属性重复和冗余的问题,其实官方存在一个map函数来解决这个问题。来看下面一段代码。
import {mapState,mapGetters} from "vuex"
computed: {
...mapState([
"name",
"type"
]),
...mapGetters([
"getName"
])
}
复制代码
这种做法也能达到效果。当然也可以进行重新命名的,例如这样:
...mapState({
name:state=>state.name,
type:state=>state.type
})
复制代码
2、如何按功能模块分state属性:
当我们项目开始复杂起来的时候,我们发现单个的vuex文件已经无法去满足我们的眼球了,当然也是能够进行维护的,只是维护起来的成本开销比较大。此时就需要引入一个新的概念:
Module
. module主要的功能是将大型的store分成一个个模块。
来看下面一段代码:
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
moduleA,
moduleB
}
})
复制代码