vue之vuex学习

一. vuex介绍

    官网介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
    我觉得说白了就是方便管理或则获取一些共享的数据,比如多个组件之间甚至是父组件都需要的共享数据,以便集中管理修改并且可以实时响应。 store(仓库)形容的非常体贴,比如东西放在仓库里,所有人都遵循同一个规则便可可以获取到,改变等。
    props,data 和 vuex 的区别:(1)props 是 父组件向子组件传递数据时,子组件用 props 接受父数据;父子组件的关系可以总结为 prop 向下传递,事件向上传递;(2)data 是组件自身定义的私有数据;(3)vuex 是一个全局的共享的数据存储区域,相当于一个仓库。
    vuex 和单纯的全局对象有以下两点不同:vuex 的状态存储是响应式的。当 vue 组件从vuex中读取状态的时候,若 vuex 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
    你不能直接改变 vuex中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

二 . vuex 安装

  1. 直接下载 / CDN 引用,用 script标签引入。vuex代码下载
	<script src="/path/to/vue.js"></script>
  1. NPM 或 Yarn 引入
	npm install vuex --save

	yarn add vuex

    在一个模块化的打包系统中,您必须显式地通过 Vue.use() 来安装 Vuex:
如 vue-cli中需要在 main.js 的开头里面加上两行这样的代码:

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

	Vue.use(Vuex)

第一行是用ECMAScript6的import将vuex包导入进来.
第二行是Vue.js本身的插件注入语法,将插件注入Vue.js的目的是方便我们在插件内部调用它。

  • 注意:
    • vuex 依赖 Promise。如果你支持的浏览器并没有实现 Promise (比如 IE),那么你可以使用一个 polyfill 的库。
    • 官网解释:Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。
    • 使用 vuex 并不意味着你需要将所有的状态放入Vuex。虽然将所有的状态放到Vuex会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。

3.创建一个 vuex

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

三. vuex的核心概念

1. State:
  • Vuex 应用的核心就是 store,用来保存状态数据。vuex 所管理的就是状态,其它的如Actions、Mutations都是来辅助实现对状态的管理的。vue 组件要有所变化,也是直接受到 State 的驱动来变化的。
    • 将 state 从根组件注入到每一个子组件中。通过 this.$store.state.valueName 访问 state 的状态。
    • 若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
    • 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
  • mapState 辅助函数:当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 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
    }
  })
}

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

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

mapState 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。但是自从有了对象展开运算符(现处于 ECMAScript 提案 stage-4 阶段),我们可以极大地简化写法:

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}
2. Getters
  • Getters 负责对外提供需要处理过的 state 数据,不修改数据。
  • Getters本质上是用来对状态进行加工处理。Getters(可以认为是 store 的计算属性),就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计。
    • 可以通过this.$store.getters.valueName 对派生出来的状态进行访问。或者直接使用mapGetters 辅助函数,它仅仅是将 store 中的 getter 映射到局部计算属性,要求局部计算属性和getter中定义的方法名一样,类似mapState数组。
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)
   }
 }
})
3. Mutation
  • Mutations的中文意思是“变化”,利用它可以更改状态。事实上,更改 Vuex 的 store 中的状态的唯一方法就是提交 (commit)mutation。不过,mutation触发状态改变的方式有一点特别,所谓 commit 一个mutation,实际是像触发一个事件一样,传入一个mutation的类型以及携带一些数据(称作payload,载荷)。
  • mutation 必须是同步函数。
//  参数列表最多只有两个参数 : 参数1:是 state 状态, 参数2:是 commit 提交的数据
mutations: {   //放置mutations方法
  increment(state, payload) {
  	//在这里改变state中的数据
  	state.count = payload.number;
  },
  // 有时候我们需要再payload传递多个数据参数时,我们可以通过对象的方式传递
  changeSearchContentByObject(state,payload){
    state.searchContent="通过Object对象来修改数据:"+payload.searchContent
},

// 在组件调用 Mutation
this.$store.commit('increment', 10);
  • 其中所包含的,实际上是一个个的mutation处理函数,用于指明收到这个mutation的commit之后,应该做些什么(当然,主要就是改变state,只是改变哪些state值的问题)。

  • 那commit一个mutation在代码层面怎么表示呢?

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

或者这样:
this.$store.commit({
 	type: 'increment',
 	amount: 10
})
4. Action
  • Action 类似于 mutation,不同在于:

    • Action 提交的是 mutation,而不是直接变更状态。
    • Action 可以包含任意异步操作。
     actions: {
    	 //我们会经常用到 ES2015 的 参数解构 来简化代码(特别是我们需要调用 commit 很多次的时候):
          addAction({ commit }) {
              commit("add")
          },
         reduce(context) {
        	  context.commit('reduce')
          },
          incrementAsync({ commit }) {
              setTimeout(() => {
                  commit('add')
              }, 1000)
          }
      }
    
  • Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。不过,mutation处理函数中所做的事情是改变state,而action处理函数中所做的事情则是commit mutation。

  • Action 通过 store.dispatch 方法触发:具体的触发方法是 this.$store.dispatch(actionType, payload)。所传的两个参数一个是要触发的action的类型,一个是所携带的数据(payload),类似于上文所讲的 commit mutation时所传的那两个参数。

// 以载荷形式分发
this.$store.dispatch('incrementAsync', {
  amount: 10
})

或
// 以对象形式分发
this.$store.dispatch({
  type: 'incrementAsync',
  amount: 10
})
  • this.$store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 this.$store.dispatch 仍旧返回 Promise:

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

现在你可以:

$this.store.dispatch('actionA').then(() => {
  // ...
})

5. Module
  • 它实际上是对于store的一种切割。由于Vuex使用的是单一状态树,这样整个应用的所有状态都会集中到一个比较大的对象上面,那么,当应用变得非常复杂时,store 对象就很可能变得相当臃肿!为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
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 的状态
  • 模块的局部状态
    • 对于每个模块内部的 mutation 和 getter,接收的第一个参数就是模块的局部状态对象。
const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}
  • 同样,对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:
const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}
  • 对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:
const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

最后 命名空间( namespaced ) 这部分 可以去参考 官网大麦 这位作者。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值