js 操作vuex数据_[Vue 系列]之 Vuex 数据流向

原标题:[Vue 系列]之 Vuex 数据流向

摘要

来自摩拜前端团队的 bing

本文主要了解 Vuex 的整个数据流向及各模块之间的触发使用。

欢迎留言并分享 Vuex 使用中遇到的坑,欢迎批评指正。其他前端干货敬请关注我司微信公众号 - 《前端新视野》。

日常开发中一般我们都会接触到组件化的概念,将一些通用的模块封装成组件去复用,提高开发效率,组件中父子组件、兄弟组件、跨级组件等组件之间的通信是我们必须要去关注的。

但当我们的组件非常复杂,嵌套层级很深的时候:

父组件给子组件不得不将 props 一层一层的传递下去

子组件同样也要利用 $emit 事件机制层层注册

数据最终变的难以维护

这时我们可以引入 Vuex来管理状态(数据)。一、Vuex 是什么

Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。

它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

通俗一点的话说就是:

Vue 应用中统一管理数据的地方。

Vuex 的特点是:

把数据单独隔离 -- 意味着它有自己的生态系统,有固定的输入和输出,

图一是整个 Vuex 的数据流向及触发过程示意:

图一

其中:

Actions 作为数据的输入

State 作为数据的输出。二、数据流向 2.1 Components 收集用户反馈触发 Actions

图一中 Actions是负责处理从 Vue Components 接收到的用户行为的模块。

调用其他 action

发送异步请求以及提交(commit) mutations

都是在这个模块中操作。

2.1.1 定义 Action

要点:

action 函数接受一个与 store 实例具有相同方法和属性的 context 对象;

因为 action 通常是异步的,可以结合 Promise 来组合多个 action 来处理复杂的异步流程。

// store/index.js

actions:{

// 基础的action

addTodoOne(context, todo){

if(todo.value != ""){

context.commit("ADD_TODO", todo);

}

},

// 解构赋值

addTodoTwo({ commit }, todo){

if(todo.value != ""){

commit("ADD_TODO", todo);

}

},

// 异步调用

addTodoThree({ dispatch, commit}, todo){

if(todo.value != ""){

commit('ADD_TODO', todo)

return dispatch('asyncAddTodo', todo).then(() => {

commit('ADD_TODO_ASYNC', todo)

})

}

},

asyncAddTodo ({commit}, todo) {

return new Promise((resolve, reject) => {

setTimeout(() => {

resolve()

}, 1000)

})

}

},

这里:注意一下参数的不同

context 里面有:

dispatch -- 调用其他 action

commit -- 调用 mutation2.1.2 触发 Action

定义好的 action怎样在 Component中触发呢?

="button"class="btn btn-success btn-lg btn-block"

@click="addTodos"> 添加

<>

import {mapActions} from "vuex";

export default{

...

methods:{

// 用户行为

addTodos(){

let todo = {

value: this.value,

id: ++this.id

};

this.value = "";

// 触发Action 方式一

this.$store.dispatch("addTodo", todo);

// 触发Action 方式二 、addTodo为 mapActions 函数返回

this.addTodo(todo)

// 触发Action 方式三、add为 mapActions 函数返回

this.add(todo)

},

...mapActions([

'addTodo',

]),

...mapActions({

add: 'addTodo'

})

}

}

>

最基本的触发方式:

this.$store.dispatch("addTodo", todo);

方式二和三种中使用 '...' 扩展运算符将 mapActions返回值混入到 methods 中。

mapActions是 Vuex 提供的辅助函数,可以有效精简我们的代码。

mapActions可以接受一个数组或一个对象

在使用module时,可以接受module路径跟简写对象,暂不展开,详情请阅读官方文档https://vuex.vuejs.org/zh/guide/modules.html

// 调用 `this.addTodo()`方法映射为 `this.$store.dispatch('addTodo')`

...mapActions([

'addTodo',

]),

// 调用 `this.add()` 方法映射为 `this.$store.dispatch('addTodo')`

...mapActions({

add: 'addTodo'

})

2.2 Actions 提交(commit)Mutations,请求修改 State 2.2.1 定义 Mutation

要点:

mutation 默认接受当前 state 为第一个参数;

mutation 是修改 state 的唯一途径,并且是同步执行,区别于 action ;

最好提前在你的 Store 中初始化好所有所需属性;

当需要在对象上添加新属性时,你应该使用 Vue.set(obj, 'newProp', 123),使增加的新属性在 Vue 应用中是响应式的;

官方推荐使用大写常量来定义 mutation,统一管理,一目了然。

// mutation-type.js

export const ADD_TODO = 'ADD_TODO'

// store.js

import { ADD_TODO } form './mutation-type.js'

const store = new Vuex.Store({

state:{ ... },

getters:{ ... },

mutations:{

[ADD_TODO](state, todo) {

state.todos.push(todo);

Vue.set(state, 'newProp', 123)

}

},

actions:{ ... },

modules:{ ... }

});

2.2.2 触发 Mutation

注意:1、Component中触发一些简单的同步操作,可直接触发(commit)mutation

2、若需要异步操作的则需要在 action中触发(commit)mutation

// component 中直接触发(commit)Mutation

@click="delTodo(index)"> 删除

<>

import { mapMutations } from "vuex";

export default{

...

methods: {

delTodo(index){

// 可以向commit传入额外的参数,

// 即mutation的(payload)

this.$store.commit("DEL_TODO", index)

},

// 将 `this.DEL_TODO()` 映射为

// `this.$store.commit('DEL_TODO')

...mapMutations([

'DEL_TODO'

]),

// 将 `this.testDel()` 映射为

// `this.$store.commit('DEL_TODO')

...mapMutations({

testDel: 'DEL_TODO'

})

}

}

>

// actions 中异步触发

...

actions:{

// 异步调用

addTodoThree({ dispatch, commit}, todo){

if(todo.value != ""){

commit('ADD_TODO', todo)

return dispatch('asyncAddTodo', todo).then(() => {

commit('ADD_TODO_ASYNC', todo)

})

}

},

asyncAddTodo ({commit}, todo) {

return new Promise((resolve, reject) => {

setTimeout(() => {

resolve()

}, 1000)

})

}

},

方式一:在组件的事件中直接调用

this.$store.commit("DEL_TODO",index)

方式二:异步操作在 action 中完成

2.3 Mutation 同步修改 State

// store.js

mutations:{

[ADD_TODO](state, todo) {

state.todos.push(todo);

Vue.set(state, 'newProp', 123)

},

[ADD_TODO_ASYNC](state, todo) {

state.todos.push(todo);

},

[DEL_TODO](state, index) {

state.todos.splice(index, 1);

}

},

2.4 State 改变后重新渲染(Render)Components 2.4.1 使用 State

Component中是怎样绑定 state的值呢?

import {mapState, mapGetters} from "vuex";

export default {

name: 'app',

data () { ... },

computed:{

// 第一种

state1 () {

return this.$store.state.state1

},

// 第二种

// 当计算属性的名称与state的状态名称一样时,可以省写

// 映射 this.state2 为 store.state.state2

...mapState({

state2: state => state.state2

}),

// 第三种 同名state也可以用数组的方式省写

// 映射 this.state2 为 store.state.state2

...mapState([

'state2'

]),

}

2.4.2 使用 Getter

如果想要从 Store中的 state去衍生出一些状态,可以使用 getter,相当于 state的计算属性

可以在实例化的时候和 state 并行,定义一个getters

// store.js

const store = new Vuex.Store({

state: { ... },

getters: {

count: state => {

return state.todos.length + 10;

}

}

})

注意:getter count 的第二个参数也可以关注一下

在组件中像下面这样调用:

从 $store.getters里面获取

// 组件中

computed:{

// 第一种

todoCount () {

return this.$store.getters.count

},

// 第二种

...mapGetters({

count: 'count'

}),

// 第三种

...mapGetters([

'count'

])

},

至此,一个完整的数据流向就闭环了。

总结

本文主要介绍了从用户触发开始到再次渲染更新组件结束过程中, Vuex 的数据流向及各模块的使用方式,希望对初学 Vuex 或 打算使用 Vuex 管理数据的朋友有所帮助,有任何问题或讲述不清的地方,请留言相告。

最后来个硬广:

🌟 我们出书啦,欢迎点击阅读原文试读和购买👇

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值