Vuex

Vuex 是什么?

是一个集中式存储组件数据的仓库

npm安装

npm install vuex --save

vuex使用

在一个模块化的打包系统中,必须显式地通过 Vue.use() 来安装 Vuex:
store的index.js文件中:

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

Vue.use(Vuex)

注意

上述步骤必须在创建仓库之前完成!!!

vuex核心概念(store&&state)

仓库

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,
它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,
    若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地
    提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,
    从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

vuex仓库环境的搭建

//state会转绑给store对象
//任意一个组件内都可以通过$store来访问仓库对象
import vue from "vue";
import vuex from "vuex";
vue.use(vuex)
const store = new vuex.Store({
    state:{count:0}
})//新建仓库
new vue({
    store,
})//注册仓库

访问仓库数据

由于上一步把 store 的实例注入了所有的子组件 所以任何组件都可以通过其自身的$store来访问仓库

<template>
  <div>
    {{count}}
  </div>
</template>

<script type="text/ecmascript-6">
    export default {
        name: "App",
        data(){
          return {
            count:this.$store.state.count
          }
        }
    }
</script>

创建计数器组件

  在整个组价的改造过程中,我们发现是需要修改计数器的值,
  当我们通过 `this.$store.state.count++` 这种方式去修改store中的数据时发现仓库数据变了
  可是界面上的数据没有更新.  在对仓库数据进行修改时 我们必须遵守 Vue 的响应规则
  
  所以仓库中的所有数据在使用时最好都定义成计算属性

👆自己的理解:进行了这步操作: count:this.$store.state.count ,通过深拷贝将
仓库中的数据转存了一份,仓库中的数据一般都是共享数据,这样一来便成了独立
的数据,自然不会渲染到界面中。不建议使用转存的形式来读取仓库中的数据
而是应该使用计算属性来读取仓库中的数据;这样还可以避免脏数据的问题;
也不会丢失数据的响应式能力
仓库中的数据在组件上都有一个计算属性与之对应

严格模式

开启严格模式,仅需在创建 store 的时候传入 strict: true

const store = new Vuex.Store({
  // ...
  strict: true
})

在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。
这能保证所有的状态变更都能被调试工具跟踪到。

严格模式下,组件中直接修改了仓库中的数据,页面仍然可以渲染,但会报错!!

👆由此引入Mutation

Mutation

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

mutations:{
事件名(state){
数据的操作
}
}

注册Mutation

    //改造仓库文件
    import Vuex from "vuex"
    import Vue from "vue"
    Vue.use(Vuex)
    const store = new Vuex.Store({
      strict: true,
      state:{
        count:0
      },
      mutations:{
        inc(state){
          state.count++
        },
        dec(state){
          state.count--
        }
      }
    })
    export default store

使用mutation

你不能直接调用一个 mutation handler。
这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”
要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

  store.commit('事件名')//提交mutation来修改仓库中的数据

提交载荷(Payload)

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

// ...
mutations: {
//当n等于一个值时,就代表默认值,也就是没传值的时候会有一个默认值
  inc (state, n) {
    state.count += n
  }
}
store.commit('inc', 10)

在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:

也就是说,当要传递多个数据的时候,载荷应该写成对象的形式
如:{test,mount}

// ...
mutations: {
  inc (state, obj) {
    state.count += obj.amount
  }
}
store.commit('inc', {
  amount: 10
})

补充:

当提交mutation时没有传递载荷时
在注册mutation的时候解构赋值使其为空对象

 mutations:{
      add(state,{step=1,msg}={}){
        state.count+=step
      }
    }
this.$store.commit("add")

对象风格的提交方式

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

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

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

mutations: {
  inc (state, obj) {
    state.count += obj.amount
  }
}

Mutation 需遵守 Vue 的响应规则

既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。
这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:

  1. 最好提前在你的 store 中初始化好所有所需属性。

  2. 当需要在对象上添加新属性时,你应该
    使用 Vue.set(obj, ‘newProp’, 123)

Mutation 必须是同步函数
vue 的 devtool 中会记录每一条 mutation 日志。如果mutation中存在异步代码,会导致devtools中的记录变的混乱不可维护
当我们在mutation中书写异步代码时,严格模式下vue会提出警告,非严格模式下vue不会做出任何反应
由此引入Action

什么是Action

Action 类似于 mutation,不同在于:

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

使用

让我们来注册一个简单的 action:

actions:{
事件名(store,参数){
setTimeout(()=>{
store.commit(“事件名”,参数)
},2000)
}
}
传参规范与上面mutation一样

import Vuex from "vuex"
import Vue from "vue"
Vue.use(Vuex)
const store = new Vuex.Store({
  // strict: true,
  state:{
    count:0
  },
  getters:{
    flag(state){
      return state.count%2==0?"偶数":"奇数"
    }
  },
  mutations:{
    inc(state,obj){
      state.count+=obj.amount
    },
    dec(state){
      state.count--
    },
    asyncInc(state){
      state.count++
    }
  },
  actions:{
    asyncInc(store){
      setTimeout(()=>{
        store.commit("asyncInc")
      },2000)
    }
  }
})
export default store

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.statecontext.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。

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

分发 Action

Actions 支持同样的载荷方式和对象方式进行分发:

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

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

//map辅助
methods:{
  ...mapMutations(["inc","dec"]),
  ...mapActions(["asyncInc"])
}

如何修改vux仓库中的数据

通过提交一个mutation来同步的!!!修改仓库中的数据
通过分发一个action来异步的提交一个mutation;从而达到异步修改仓库数据的目的

vuex流程图
action通过异步的axios拿到后台的数据
Devtools只认识mutation,mutation同步的操作数据
之后数据再相应的渲染页面

Getters

有时候我们需要从 store 中的 state 中派生出一些状态.如果有多个组件需要用到此状态
就可以在 store 中定义“getters”(可以认为是 store 的计算属性)。就像计算属性一样,
getters 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

Getters 接受 state 作为其第一个参数:
  // 仓库文件
  import Vuex from "vuex"
  import Vue from "vue"
  Vue.use(Vuex)
  const store = new Vuex.Store({
    strict: true,
    state:{
      firstName:"T",
      lastName:"mac"
    },
    //与计算属性computed类似
    //但是getters没有对应的get,set方法
    getters:{
    //👇fullName可以访问仓库里的数据
      fullName(state){
      //console.log(this) //undefined
        return state.firstName +"-"+ state.lastName
      }
    }
  })
  export default store

访问Getters

Getters 会暴露为 store.getters 对象,你可以以属性的形式访问这些值

  //app.vue
  export default {
      name: "App",
      computed:{
        fullName(){
          return this.$store.getters.fullName
        }
      }
  }

辅助函数

  1. 仓库中的数据在组件上都有一个计算属性与之对应
  2. 仓库中的工具函数(mutation action)在组件上都有一个函数与之对应

import { mapState,mapGetters,mapMutations,mapActions} from ‘vuex’

简化业务组件的开发

  • mapState({}) 或者 mapState([])
  • mapGetters({}) 或者 mapGetters([])
  • mapMutations({}) 或者 mapMutations([])
  • mapActions({}) 或者 mapActions([])

一般规律

  • vuex中的state 我们在组件中使用时通常需要有对应的computed
  • vuex中的getters 我们在组件中使用时通常需要有对应的computed
  • vuex中的mutations 我们在组件中使用时通常需要有对应的methods
  • vuex中的actions 我们在组件中使用时通常需要有对应的methods

mapState用法

mapState(["count" ]) = {count:fn} = {  count(){ return this.$store.state.count }  }
...mapState(["count" ]) = count(){ return this.$store.state.count } 
     computed:{
      count(){
        return this.$store.state.count
      }
    }     
//当count在另一个组件的别名为myCount,但是这两个是同一个数据,只是名字不一样

mapState({myCount:"count" }) = {  myCount(){ return this.$store.state.count }  }
...mapState({myCount:"count" }) = myCount(){ return this.$store.state.count } 
     computed:{
      myCount(){
        return this.$store.state.count
      }
    } 

mapGetters用法

与mapState用法一致

mapMutations用法

 mapMutations(["add"]) = {add:fn} =  {  add(){ this.$store.commit('add') }  }
 ...mapMutations(["add" ]) = add(){  this.$store.commit('add')  } 
 methods:{
    add(){
       this.$store.commit('add')
    }
 }

mapMutations({myAdd:"add" }) = {  myAdd(){ this.$store.commit('add') }  }
...mapMutations({myAdd:"add" }) = myAdd(){ this.$store.commit('add') } 
 methods:{
    myAdd(){
        this.$store.commit('add')
    }
 } 

mapActions用法

与mapMutations用法一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值