您的位置:首页 > 产品设计 > UI/UE

前端框架Vue(10)——vuex 状态管理

2017-05-11 17:34 615 查看

1、Vuex 是什么?

Github vue-spa-demo 项目地址

在使用 Vue 框架做单页面应用时,我们时常会遇到传值,组件公用状态的问题。(子父间传值文章传送门) ,如果是简单的应用,兄弟组件之间通信还能使用 eventBus 来作为中介。但是一旦应用比较庞大,那状态将会变得难以维持管理。

Vue 为我们提供了进行大型状态管理的 Vuex,类似 Flux 。Vuex 采用了集中式存储管理所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

直接用官方文档提供的关系图来讲:



一个 store 中包含了: Actions( 行为 ) 、Mutations( 突变 )、State( 状态 ),完整的 Vuex 动作是这样的 Components( 组件 )中 methods 里面一个方法 dispatch (调用)Actions,Actions 然后 commit 对应的Mutations, 只有 Mutations 可以操作 State 中的状态数据,状态一改变,组件中就重新渲染。路线:C——>A——>M——>S——>C。

2、Vuex 安装

(1)引入式

<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>


(2)npm 安装

npm install vuex --save


3、Vuex 使用,结合小实例

一、这边提供两中目录结构共使用:

1、适合简单的项目,所有模块放到 store.js 中管理

import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex)

const store = new Vuex.Store({
state:{
count: 10,
},
mutations:{
//格式:类型(名字)+处理函数
//加1
INCREMENT(state) {
//console.log(state)//state对象
state.count++;
}
},
actions:{
increment({commit}){
commit("INCREMENT")
}
}
})

export default store


2、将各个 js 单文件分开,便于管理

==store
=index.js
=mutations.js
=actions.js
=getters.js


index.js 主文件入口:

/**
*主要入口文件,引入其他四个js
*/
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)

//引入actions、mutations、getters
import actions from "./actions.js"
import mutations from "./mutations.js"
import getters from "./getters.js"

// 定义状态state
const state = {

}

// 设置暴露接口
export default new Vuex.Store({
state,
mutations,
actions,
getters
})


mutations.js 、actions.js 、getters.js 文件类似:

export default {
//方法 对state数据进行统一操作
}


main.js 进行全局注册:

import store from './store/index'

/* eslint-disable no-new */
new Vue({
el: '#app',
store,
router,
template: '<App/>',
components: { App }
})


二、结合简易‘’不符合逻辑‘’计算器讲解 Vuex

1、先上简陋图:



2、逻辑: 输入框中进行数字输入,加减乘除按钮点击使用,点击确认输出结果。

3、目录结构:



*一 一对应

XTGL : 计算器

showBox : 最上方显示区

input : 输入区

calc : 四则运算区

output : 结果输出区

4、代码实现:

components 部分

inputBox.vue 负责初始值的输入,dispatch actions 中的 inputevent ,为了将输入的值显示到 showBox 中。

<template>
<div class="inputBox">
<div class="layui-form-item">
<label class="layui-form-label">输入:</label>
<div class="layui-input-block">
<input class="layui-input" v-model="inputNum" @blur="inputEvent">
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
inputNum: '',
}
},
methods:{
inputEvent:function(){
//调用dispatch
this.$store.dispatch('inputevent',this.inputNum)
}
}
}
</script>


showBox.vue 只需要将 store.js 中 state 里的初始值拿到并显示,这边
this.$store.state.inputNum
需要写在 computed 中。

<template>
<div class="showBox">
<div class="layui-form-item">
<div class="layui-input-block">
<input class="layui-input" v-model="inputNum">
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {

}
},
computed:{
//拿inputNum
inputNum () {
return this.$store.state.inputNum
}
}
}
</script>
<style scoped>
.layui-input-block{
margin-left: 0!important;
}
.layui-input{
width: 100%!important;
}
</style>


calc.vue

<template>
<div class="clacBox">
<div>
<button class="btn layui-btn" @click="increment">加1</button>
<button class="btn layui-btn" @click="decrement">减1</button>
<button class="btn layui-btn" @click="increment">乘2</button>
<button class="btn layui-btn" @click="increment">除2</button>
</div>
</div>
</template>
<script>
export default {
data () {
return {

}
},
methods:{
increment () {
//dispatch调用
this.$store.dispatch('increment')
},
decrement () {
this.$store.dispatch('decrement')
}
}
}
</script>
<style scoped>

</style>


outputBox.vue 点击确认按钮,操作 store.js 中 actions 中 resultevent, 并且拿到结果值 resultNum。

<template>
<div class="inputBox">
<div class="layui-form-item">
<label class="layui-form-label">结果:</label>
<div class="layui-input-inline">
<input class="layui-input" v-model="resultNum">
</div>
</div>

<button class="btn layui-btn layui-btn-danger" @click="resultEvent">确认</button>
</div>
</template>
<script>
import {mapState} from "vuex"
export default {
data () {
return {

}
},
computed:{
resultNum () {
return this.$store.state.resultNum
}
},
methods:{
resultEvent () {
this.$store.dispatch('resultevent')
}
}
}
</script>
<style scoped>
.inputBox{
overflow: hidden;
}
.layui-form-item{
float: right;
margin-top: 15px;
}
button{
float: right;
margin-top: 15px;
}
</style>


XTGL.vue 父组件

<template>
<div id="XTGLPage" class="XTGLPage">
<showBox></showBox>
<inputBox></inputBox>
<calcBox></calcBox>
<outputBox></outputBox>
</div>
</template>
<script>
import showBox from "./chlidComponents/showBox.vue"
import inputBox from "./chlidComponents/inputBox.vue"
import calcBox from "./chlidComponents/calc.vue"
import outputBox from "./chlidComponents/outputBox.vue"
export default {
name:'',
data () {
return {

}
},
components:{
inputBox,
showBox,
calcBox,
outputBox
}
}
</script>
<style scoped>
.XTGLPage{
width: 500px;
height: 400px;
padding: 30px 20px 0;
border: 2px solid #ccc;
box-shadow: 10 10 0 0 #333;
background-color: #ccc;
}
</style>


store 中 store.js 部分 完整操作是 ‘自下往上’

import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex)

const store = new Vuex.Store({
state:{
inputNum:'',
outputNum:'',
resultNum:''
},
mutations:{
//格式:类型(名字)+处理函数
//大写
//inputNum赋值
INPUTEVENT(state,value) {
state.inputNum += value
state.outputNum = value
},
//加
INCREMENT(state,value) {
state.inputNum += '+1'
state.outputNum++
},
//减
DECREMENT(state,value) {
state.inputNum += '-1'
state.outputNum--
},
//结果
RESULTEVENT(state){
state.resultNum = state.outputNum
console.log(state.resultNum)
}
},
actions:{
//小写
inputevent({commit},value){
commit("INPUTEVENT",value)
},
increment({commit},value){
commit("INCREMENT",value)
},
decrement({commit},value){
commit("DECREMENT",value)
},
resultevent({commit}){
commit("RESULTEVENT")
}
}
})

export default store


代码比较多,文字解释待加入,先看效果图:



操作复杂度,逻辑复杂度为0,自己都尴尬的设计,希望对于学习、理解 Vuex 有些许帮助!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  vue vuex 状态管理