[VUE框架学习笔记]vuex是什么???(有语法糖!)

今天来学习一下vuex

  • 前言
  • 什么是vuex?
  • 使用前奏
  • 五大核心概念
    • 一个store例子
    • State
    • Getter
    • Mutations
      • Mutations的提交方式
    • Action
      • 一个例子
      • action的提交方式
      • 组合action
    • Modules
      • 模块的局部状态
  • 一个vuex的应用实例

前言

为什么会出现vuex?

  • 1.如何让多个vue组件共享状态?
  • 2.vue组件间如何通讯?

通常,在项目不是很复杂的时候,我们会利用全局事件总线解决,但是随着复杂度的提升,这些代码将变得难以维护。因此,我们需要一种更加好用的解决方案,于是,vuex诞生了!

什么是vuex?

  • Vuex是一个专门为Vue.js应用设计的状态管理架构,统一管理和维护各个vue组件的可变化状态(vue组件里面的某些data)
  • 它采用集中式存储管理应用所有组件的状态,并以响应的规则保证状态以一种课预测的方式发生变化
  • Vue五个核心概念,state,getters,mutations,action,modules

[VUE框架学习笔记]vuex是什么???(有语法糖!)_第1张图片
[VUE框架学习笔记]vuex是什么???(有语法糖!)_第2张图片

使用前奏

  • 1.npm安装
    npm install vuex
  • 2.Vue.use()
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

五大核心概念

  • state
  • getters
  • mutations
  • actions
  • modules

一个store例子

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

在App.vue文件中添加代码,在templete模板中添加一个按钮和点击事件

<button v-on:click="addClick">button>

import store from './vuex/store'
methods:
  {
     
    addClick:function(){
     
	store.commit('increment')
      	console.log(store.state.count) // -> 1
    }
  }

State

state是一个全局的状态存储,数据会存储在其中,vue组件可以直接访问其中的值,但是只可以读,不可以进行写操作

Getter

有些时候我们需要对获取的数据进行加工,获取数据的一部分或者某些属性,而不是直接获取state中的数据,这时候可以通过getter定义函数,返回对应的数据

Mutations

mutations是vuex中唯一一个可以修改数据的地方,mutations可以定义事件函数,在vue组件中可以通过commit发射事件,调用函数。需要注意的是,mutations中的操作必须是同步的,不可以存在异步操作的情况


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

const store = new Vuex.Store({
     
  state: {
     
    count: 1
  },
  mutations: {
     
    increment (state) {
     
      // 改变状态
      state.count++
    }
  }
})

你不能直接调用一个 mutation 回调函数。要唤醒一个 mutation,你调用 store.commit 方法(参数为回调函数名):

store.commit('increment')

mutation回调函数的第一个参数始终为store,你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(playload):

// ...
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
})

Mutations的提交方式

提交 mutation 的另一种方式是直接使用包含 type 属性的对象:

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

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变:

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

你可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。

import {
      mapMutations } from 'vuex'
export default {
     
  // ...
  methods: {
     
    ...mapMutations([
      'increment' // 映射 this.increment() 为 this.$store.commit('increment')
    ]),
    ...mapMutations({
     
      add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
    })
  }
}

Action

和mutation比较相似,不同的是cations中不直接修改state,而是通过commit调用mutations修改数据,而且actions中可以存在异步处理逻辑

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

可以把mutation比作仓库的管理员,负责仓库管理,而把action比作领导,可以命令仓库管理员作操作,但不会亲自动手。

一个例子

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

actions 的第一个参数是 context,它向外暴露一组与 store 实例相同的方法/属性,所以可以直接调用 context.commit 或者访问 context.state 或者 context.getters 。我们通常使用 es6 的参数解构来简化我们的代码,直接写成{ commit }

actions: {
     
  increment ({
       commit }) {
     
    commit('increment')
  }
}

Action 通过 store.dispatch 方法触发:store.dispatch(‘increment’)


action多此一举吗?

mutation 必须同步执行这个限制么?Action 就不受约束!我们可以在 action 内部执行异步操作:

actions: {
     
  incrementAsync ({
       commit }) {
     
    setTimeout(() => {
     
      commit('increment')
    }, 1000)
  }
}

action的提交方式

  • 1.载荷形式分发
store.dispatch('incrementAsync', {
     
  amount: 10
})
  • 2.以对象形式分发
store.dispatch({
     
  type: 'incrementAsync',
  amount: 10
})
  • 3.在组件中分发
    在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):
import {
      mapActions } from 'vuex'
export default {
     
  // ...
  methods: {
     
    ...mapActions([
      'increment' // 映射 this.increment() 为 this.$store.dispatch('increment')
    ]),
    ...mapActions({
     
      add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
    })
  }
}

组合action

action通常是异步的,那么如何知道action什么时候接触呢?如何组合多个action呢?

第一件事是store.dispatch的返回的是被触发的action函数的返回值,因此你可以在action中返回Promise:

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

就可以使用then()

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

在另一个action中也可以

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

最后,如果我们利用 [async / await] 这个 JavaScript 即将到来的新特性,我们可以像这样组合 action:
假设 getData() 和 getOtherData() 返回的是 Promise

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

Modules

使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store对象会变得臃肿不堪。

为了解决以上问题,Vuex运行将store分割到多个模块(module)。每个模块拥有自己的state,mutation,action,getters,甚至时嵌套子模块—从上至下进行类似的分割:

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: {
     
    incrementIfOdd ({
       state, commit }) {
     
      if (state.count % 2 === 1) {
     
        commit('increment')
      }
    }
  }
}

对于模块内部的 getter,根节点状态会作为第三个参数:

const moduleA = {
     
  // ...
  getters: {
     
    sumWithRootCount (state, getters, rootState) {
     
      return state.count + rootState.count
    }
  }
}

一个vuex的应用实例

  • store.js
export default new Vuex.Store({
     
  state: {
     
    messages: []
  },
  actions: {
     
    newMessage ({
      commit}, msg) {
     
      commit('NEW_MESSAGE', msg)
    }
  },
  mutations: {
     
    NEW_MESSAGE (state, msg) {
     
      state.messages.push(msg)
    }
  }
})

  • main.js
import Vue from 'vue'
import App from './App.vue'

import store from './vuex/store'

new Vue({
     
  el: '#app',
  store,
  render: h => h(App)
})

  • client.vue
<template>
    <div>
        <h1>{
    { clientid }}h1>
        <div>
            <ul>
                <li v-for="message in messages">
                    <label>{
    { message.sender }}:label> {
    { message.text }}
                li>
            ul>
            <div>
                <input v-model="msg" placeholder="Enter a message, then hit [enter]" @keyup.enter="trySendMessage">
            div>
        div>
    div>
template>
<script>
    import {
      mapState, mapActions } from 'vuex'

    export default {
     
        data() {
     
            return {
     
                msg: ''
            }
        },
        props: ['clientid'],
        computed:{
     
                ...mapState({
     
                  messages: state => state.messages
            })
    },
 methods: {
     
        trySendMessage() {
     
            this.newMessage({
     
                text: this.msg,
                sender: this.clientid
            })
            this.resetMessage()
        },
        resetMessage() {
     
            this.msg = ''
        },
       ...mapActions(['newMessage'])
    }
    }
</script>
<style>
</style>

  • App.vue
 <div>
        <client clientid="Client A">client>
div>
<div>
        <client clientid="Client B">client>
div>
<script>
  import client from './components/Client.vue'
  import store from './vuex/store'
export default {
     
  name: 'app',
  data () {
     
    return {
     
      msg: 'Welcome to Your Vue.js App'
    }
  },
  components:{
     client}
}
</script>

你可能感兴趣的:(VUE框架学习笔记,vue.js,javascript,html)