了解Vuex状态管理模式的理解强化指南

更新日期: 2020-11-29阅读: 1.2k标签: vuex
1

vuex是什么呢?它是Vue的状态管理模式,在使用vue的时候,需要在vue中各个组件之间传递值是很痛苦的,在vue中我们可以使用vuex来保存我们需要管理的状态值,值一旦被改变,所有引用该值的地方就会自动更新。是不是很方便,很好用呢?

vuex是专门为vue.js设计的状态管理模式,集中式存储和管理应用程序中所有组件的状态,vuex也集成了vue的官方调式工具,一个vuex应用的核心是store,一个容器,store包含了应用中大部分状态。

那么我们在什么时候应用vuex呢?vuex也不是随便乱用的,小型简单的应用就不那么合适了,因为用了Vuex是繁琐多余的,更适合使用简单的store模式;对于vuex更加适用于中大型单页应用:多个视图使用于同一状态,不同视图需要变更同一状态。

传参的方法对于多层嵌套的组件来说,是非常繁琐的,并且对于兄弟组件间的状态传递无能为力;采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝,通常会导致无法维护的代码

npm install vuex --save //yarn add vuex
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

在创建vuex实例的地方引入vue,vuex

import Vue from 'vue'//引入vue
import Vuex from 'vuex'//引入vuex

Vue.use(Vuex); //使用 vuex

import store from './store' //引入状态管理 store

new一个Vuex.Store实例,并注册state,mutations,actions,getters到Vuex.Store实例中:

import Vue from 'vue';
import Vuex from 'vuex'; // 引入vuex
import store from './store' // 注册store

Vue.use(Vuex); // 使用vuex

export default new Vuex.Store({
 state: {...},
 mutations: {...},
 actions: {...},
 getters: {...}
})

// 当代码量大额时候写个js文件即可
store
action.js
index.js
mutation.js
// 引入到store/index.js注册到vuex实例中
import mutations from './mutations' // 引入mutations
import actions from './action' // 引入action
import Vue from 'vue' // 引入vue
import Vuex from 'vuex' // 引入vuex

Vue.use(Vuex);
// 创建state
const state = {
 count: 0
};

export default new Vuex.Store({
 state, // 注册state
 action, // 注册actions
 mutations // 注册mutations
})

创建好vuex.store后,需要在入口文件main.js中引入store并注册到vue实例中,这样就可以在任何组件使用store了。

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store' // 引入状态管理store

Vue.config.productiontip = false
new Vue({
 router,
 store, // 注册store
 render: h => h(App)
}).$mount('#app')

在组件中使用,引入vuex中各属性对应的辅助函数

import {mapActions, mapState,mapGetters} from 'vuex' 
//注册 action 、 state 、getter
2

创建一个vue项目,输入vue int webpack web,安装vuex,命令:npm install vuex --save。

store,index.js

import Vue from 'vue' // 引入vue
import Vuex from 'vuex' // 引入vuex
// 使用vuex
Vue.use(Vuex);
// 创建Vuex实例
const store = new Vuex.store({
})
export default store // 导出store

main.js

import Vue from 'Vue'
import App from './App'
import router from './router'
import store from '.store'

Vue.config.productiontip = false

new Vue({
 el: '#app',
 store,
 router,
 components: {App},
 ...
})

State,可以在页面通过this.$store.state来获取我们定义的数据

import Vue from 'vue' // 引入vue
import Vuex from 'vuex' // 引入vuex
// 使用vuex
Vue.use(Vuex);

// 创建Vuex实例:
const store = new Vuex.Store({
 state: {
  count: 1
 }
})
export default store // 导出store
{{this.$store.state.count}}

Getters相当于vue中的computed计算属性,getter的返回值根据它的依赖被缓存起来,且只有当它的依赖值发生改变时才会重新计算。

Getters可以用于监听,state中的值的变化,返回计算后的结果。

{{this.$store.getSateCount}}
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
 state: {
  count: 1;
 },
 getters: {
  getStateCount: function(state){
   return state.count+1;
  }
 }

Mutations

{{this.$store.state.count}}
<button @click="addFun">+</button>
<button @click="reductionFun">-</button>

methods: {
 addFun() {
  this.$store.commit("add");
 },
 reductionFun() {
  this.$store.commit("reduction");
 }
}

index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
// 创建Vuex实例
const store = new Vuex.store({
 state: {
  count: 1
 },
 getters: {
  getStateCount: function(state){
   return state count+1;
  }
 },
 mutations: {
  add(state) {
   state.count = state.count+1;
  },
  reduction(state){
   state.count = state.count-1;
  }
 }
})
export default store // 导出store

Actions:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
 state: {
  count: 1;
 },
 getters: {
  getStateCount: function(state){
   return state.count+1;
  }
 }
 mutations: {
  add(state) {
   state.count = state.count+1;
  },
  reduction(state) {
   state.count = state.count-1;
  }
 },
 actions: {
  addFun(context) {
   context.commit("add");
  },
  reductionFun(context) {
   context.commit("reduction");
  }
 }
// vue
methods: {
 addFun() {
  this.$store.dispatch("addFun");
  // this.$store.commit("add");
 },
 reductionFun() {
  this.$store.dispatch("reductionFun");
 }
}

传值:

methods: {
 addFun() {
  this.$store.dispatch("addFun");
  // this.$store.commit("add");
 },
 reductionFun() {
  var n = 10;
  this.$store.dispatch("reductionFun", n);
 }
}
 mutations: {
  add(state) {
   state.count = state.count+1;
  },
  reduction(state,n) {
   state.count = state.count-n;
  }
 },
 actions: {
  addFun(context) {
   context.commit("add");
  },
  reductionFun(context,n) {
   context.commit("reduction",n);
  }
 }

mapState、mapGetters、mapActions

this.$stroe.state.count
this.$store.dispatch('funName')
<div style="border:1px solid red; margin-top: 50px;">
 {{count1}}
</div>

import {mapState,mapActions,mapGetters} from 'vuex';

computed: {
 ...mapState({
  count1:state=> state.count
 })
}
3

state是最底层的初始数据,getters就相当于vue中的计算属性,是对state数据进行处理和扩展的,mutations是当需要修改state时,定义的mutations,actions时当需要很多很多的mutations进行处理时,在actions进行mutations派发的,异步处理也是在这里定义的。

vuex时一个为vue.js应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证以一种可预测的方式发生变化。

那么状态管理模式是怎样的书写格式:

new Vue({
 // state 初始状态(数据)
 data() {
  return {
   count: 0
  }
 },
 template: `<div>{{count}}</div>`,
 methods: {
  increment() {
   this.count++
  }
 }
})

多个数组共享状态时:

多个视图依赖于同一状态,来自不同视图的行为需要变更同一状态。

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {  //状态
    count: 0
  },
  mutations: {  //变化
    increment (state) {
      state.count++
    }
  }
})
store.commit('increment')

state初始状态,getter相当于计算属性,mutation状态变更,action行动,module模块。

Vue.use(Vuex)

const app = new Vue({
  el: '#app',
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}
computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

const store = new Vuex.Store({

  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todos.done)
    }
  }
  
})
getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}

store.getters.doneTodosCount // -> 1

mapGetters 辅助函数是将 store 中的 getter 映射到局部计算属性

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

mutations: {
  increment (state, n) {
    state.count += n
  }
}

store.commit('increment', 10)

this.$store.commit('xxx') 提交 mutation

mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用

import { mapMutations } from 'vuex'
export default {
  methods: {
  
    ...mapMutations([
      'increment',
      // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
      // `mapMutations` 也支持载荷:
      'incrementBy' 
      // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    
  this.incrementBy(); 调用
  
    ...mapMutations({
      add: 'increment' 
      // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
    
  }

}

Action 提交的是 mutation变化,而不是直接变更状态。Action 可以包含任意异步操作。

store.dispatch('increment')

使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
  
    ...mapActions([
      'increment', 
      // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' 
      // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    
    ...mapActions({
      add: 'increment' 
      // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

vue

安装vue-cli
cnpm install -g vue-cli

安装webpack模板 :
vue init webpack myProject

安装依赖
cnpm install

安装路由
cnpm install vue-router --save-dev

安装 axios http
cnpm install axios --save

4

vue和单纯的全局对象区别:

vuex的状态存储时响应式的,改变store中的状态的唯一途径就是显式地提交commit, mutation。

Vuex的核心是store,store包含着应用中大部分的状态 (state)。

一个最简单的store包含state与mutation,可以通过 store.state 来获取状态对象,以及通过 store.commit 方法触发状态变更。

State,存储着应用中的所有基础“全局对象”,this.$store.state.XXX可访问到。
mapState:使用此辅助函数帮助我们生成计算属性,获得多个state值。

Getter从 store 中的 state 中派生出一些状态,接受 state 作为第一个参数,第二个参数可传值计算,会暴露为 store.getters 对象,可以以属性的形式访问这些值。

Vuex 中的 mutation ,每个 mutation,事件类型 (type) 和 一个 回调函数 (handler)

Action 提交的是 mutation,不是直接变更状态,可以包含任意异步操作,通过 store.dispatch 方法触发。

5

vuex的出现是为了解决哪些问题呢?我们知道在组件之间的作用域是独立的父组件和子组件的通讯可以通过prop属性来传参,但是兄弟组件之间通讯就不那么友好了。

首先要告诉它们的父组件,然后由父组件告诉其他组件,一旦组件很多很多的时候,通讯起来就不方便了,vuex解决了这个问题,让多个子组件之间可以方便的通讯。

|-store/ // 存放vuex代码
| |-actions.js
| |-getters.js
| |-index.js
| |-mutations.js
| |-state.js
|-store/ // 存放vuex代码
| |-Module1
| | |-actions.js
| | |-getters.js
| | |-index.js
| | |-mutations.js
| | |-state.js
| |-Module2
| | |-actions.js
| | |-getters.js
| | |-index.js
| | |-mutations.js
| | |-state.js
| |-index.js // vuex的核心,创建一个store

vuex是什么?

Vuex是一个专门为vue.js应用程序开发的状态管理模式,它是采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex也集成到Vue的官方调式工具devtools extension,提供了诸如零配置的time-travel调试,状态快照导入导出等高级调试功能。

什么是“状态管理模式”?

new Vue({

  // state
  data () {
    return {
      count: 0
    }
  },
  
  // view
  template: `
    <div>{{ count }}</div>
  `,
  
  // actions
  methods: {
    increment () {
      this.count++
    }
  }
  
})

state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。


我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。


核心概念:State,Getter,Action,Module

Vuex 和单纯的全局对象有以下两点不同:

1.Vuex 的状态存储是响应式的。
2.不能直接改变 store 中的状态。

创建一个 store

// 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex)

const store = new Vuex.Store({

  state: {
    count: 0
  },
  
  mutations: {
    increment (state) {
      state.count++
    }
  }
  
})

通过 store.state 来获取状态对象,通过 store.commit 方法触发状态变更

store.commit('increment')

console.log(store.state.count) // -> 1

用一个对象包含了全部的应用层级状态,每个应用将仅仅包含一个 store 实例。单一状态树。Vuex 的状态存储是响应式的,读取状态方法,即是在计算属性中返回。

// 创建一个 Counter 组件

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

Vuex 通过 store 选项

const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})


const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

使用 mapState 辅助函数帮助我们生成计算属性

// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}


computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
]

mapState 函数返回的是一个对象。

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

需要从 store 中的 state 中派生出一些状态

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

const store = new Vuex.Store({

  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
  
})

Getter 会暴露为 store.getters 对象

store.getters.doneTodos 

// -> [{ id: 1, text: '...', done: true }]

Getter 也可以接受其他 getter 作为第二个参数:

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}

store.getters.doneTodosCount // -> 

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}
getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}

store.getters.getTodoById(2) 
// -> { id: 2, text: '...', done: false }

mapGetters 辅助函数是将 store 中的 getter 映射到局部计算属性:

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}
mapGetters({
  // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})

Vuex 的 store 中的状态的唯一方法是提交 mutation

每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)

向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}

store.commit('increment', 10)

在大多数情况下,载荷应该是一个对象

可以包含多个字段并且记录的 mutation

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

store.commit('increment', {
  amount: 10
})

store.commit({
  type: 'increment',
  amount: 10
}

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

Action

简单的 action:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
}

store.dispatch('increment')

store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}
store.dispatch('actionA').then(() => {
  // ...
}

actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

// 假设 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

文件:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
store.js 文件:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    num: 1
  },
  mutations: {
    changeFunction (state, num) {
      state.num++
    }
  }
})

main.js 文件:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

views/demo.vue 文件:

<template>
  <div>
    <p>{{msg}}</p>
    <button @click="getNum">getNum</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: '0'
    }
  },
  methods: {
    getNum () {
      this.msg = this.$store.state.num
    }
  }
}
</script>

想要获得vuex里的全局数据,可以把vue看做一个类

模块化:

const moduleA = {
  namespaced: true,
  state: {
    name: ''
  },
  getters: {},
  mutations: {},
  actions: {}
}
export default moduleA;
const moduleB = {
  namespaced: true,
  state: {
    name: ''
  },
  getters: {},
  mutations: {},
  actions: {}
}
export default moduleB;
import moduleA from './moduleA.js';
import moduleB from './moduleB.js';
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
export default store;
this.$store.state.a.name // -> moduleA 的状态name
this.$store.state.b.name // -> moduleB 的状态name
computed: {
    ...mapState('a', {
      name: state => state.name
    }),
    ...mapState('b', {
      name: state => state.name
    })
}
state示例

const state = {
  name: 'weish',
  age: 22
};
 
export default state;
getters.js 示例

export const name = (state) => {
  return state.name;
}
 
export const age = (state) => {
  return state.age
}
 
export const other = (state) => {
  return `My name is ${state.name}, I am ${state.age}.`;
}

参考官方文档:https://vuex.vuejs.org/


若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。

来自:https://segmentfault.com/a/1190000039079297


链接: https://www.fly63.com/article/detial/10116

为什么使用Vuex

在学习Vuex之前,先了解一下“单向数据流”。Vuex核心就是它的store,其中,有三个重要的部分,State:通过它存取多个组件共享的数据。Mutations:可以改变State中的数据,Actions:提交mutation,可以包含任意异步操作这一步不是必要的。

Vue.js学习,关于Vuex源码解析

Vuex是一个专门为Vue.js框架设计的、用于对Vue.js应用程序进行状态管理的库,它借鉴了Flux、redux的基本思想,将共享的数据抽离到全局,以一个单例存放,同时利用Vue.js的响应式机制来进行高效的状态管理与更新。

vue + vuex + koa2交互实例

主要目的是学会使用koa框架搭建web服务,从而提供一些后端接口,供前端调用。搭建这个环境的目的是: 前端工程师在跟后台工程师商定了接口但还未联调之前,涉及到向后端请求数据的功能能够走前端工程师自己搭建的http路径

vuex 源码:深入 vuex 之 mutation

vuex 规定更改 state 的唯一方法是提交 mutation,主要是为了能用 devtools 追踪状态变化。那么,提交 mutation 除了最主要的更改 state,它还做了其它一些什么事情呢,让我们来一探究竟。

使用Vuex解决Vue中的身份验证

Vuex为Vue.js应用管理状态.。对于应用中所有的组件来说,它被当做中央存储,并用规则确保状态只能以可预见的方式改变。对于经常检查本地存储来说,听起来是个更好的选择?让我们一起来探索下吧。

关于Vuex的action传入多个参数的问题

已知Vuex中通过actions提交mutations要通过context.commit(mutations,object)的方式来完成,然而commit中只能传入两个参数,第一个就是mutations,第二个就是要传入的参数

Vuex 的异步数据更新

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数 mutation 是同步执行,不是异步执行。

vue单页面应用刷新网页后vuex的state数据丢失的解决方案

其实很简单,因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值。一种是state里的数据全部是通过请求来触发action或mutation来改变

Vuex状态管理,state、getter

首先在 vue 2.0+ 你的vue-cli项目中安装 vuex :然后 在src文件目录下新建一个名为store的文件夹,为方便引入并在store文件夹里新建一个index.js,里面的内容如下:接下来,在 main.js里面引入store,然后再全局注入一下

Vuex新手的理解与使用

开始尝试学习使用vue,是因为此前总是遇到页面逻辑数据与视图的一致性问题.在使用vue之前,我们使用jQuery插件的时候,一桩麻烦事就是既要在每个数据变更后,写代码去改变视图,又要考虑html上各种输入

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!