Vuex

Vuex

官方文档:https://vuex.vuejs.org/zh/

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

npm install vuex --save
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

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

使用 this.$store.state.count 访问全局数据,this.$store.commit('increment') 执行全局方法。

this.$store.commit('increment')

this.$store.state.count // -> 1

State 数据

那么我们如何在 Vue 组件中展示状态呢?

方法一:

 <h1>{{this.$store.state.count}}</h1>

方法二:计算属性

<h1>{{count}}</h1>

computed:{
  count : function(){
     return this.$store.state.count
  }
}

方法三:mapState 使用数组

<template>
	<h1>{{count}}</h1>
</template>

<script>
    import { mapState } from 'vuex'  //导入mapState
    export default {
        computed: mapState([
            'count'
        ])
    }
</script>

方法四:mapState 使用对象

<template>
    <h1>{{count1}}</h1>
</template>

<script>
    import {mapState} from 'vuex'

    export default {
        computed: mapState({
                count1: 'count'
            }
        )
    }
</script>

方法五:mapState与其他计算属性混合

<template>
    <h1>{{count1}}</h1>
</template>

<script>
    import {mapState} from 'vuex'

    export default {
        computed: {
            // 使用对象展开运算符将此对象混入到外部对象中
            ...mapState({    
                    count1: 'count'
                }
            )
        }
    }
</script>

Getter 计算属性

getters:{
  reverseMsg:function (state) {
    return state.msg.split('').reverse().join('');
  }

mapGetters辅助函数

<template>
    <h1>{{reverseMsg}}</h1>
</template>

<script>
    import {mapGetters} from 'vuex'

    export default {
        computed: mapGetters(['reverseMsg'])
    }
</script>

计算属性如何传参?

getters:{
  mixMsg:function (state) {
    return function(val) {
      return val+state.msg;
    }
  }
}
<h1>{{mixMsg}}</h1>

computed: {
    mixMsg:function(){
        return this.$store.getters.mixMsg("vuex ");
    }
}

Mutation 同步方法

用来变更state数据的值。

mutations: {
	addCount:function (state,val) {
		state.count+=val;
}
<template>
    <div>
        <h1>{{count}}</h1>
        <button @click="clickEvent(3)">点我</button>
    </div>
</template>

<script>
    import {mapState} from 'vuex'
    export default {
        name: 'HelloWorld',
        methods:{
            clickEvent:function(val){
                //向 store.commit 传入额外的参数,即 mutation 的载荷(payload)
                this.$store.commit('addCount',val);
            }
        },
        computed: mapState([
            'count'
        ])
    }
</script>

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

mutations: {
    addCount:function (state,payload) {
    state.count+=payload.val;
    }
}
methods:{
    clickEvent:function(val){
        this.$store.commit('addCount',{val:val});
    }
}

mapMutations辅助函数

methods: {
    ...mapMutations(['increment']), // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
    ...mapMutations({
      add: 'increment'  // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
}

Action

异步请求服务器来获取数据,修改state数据依然用Mutation。

actions: {
    setduanzi:function (context) {                         //context为store对象
        var httpUrl = '../duanzi.json';
        Vue.axios.get(httpUrl).then(
            function (response) {
                context.commit('setduanzi',response.data);   //调用mutation里的setduanzi方法
            }
        )
    }

mutations: {
  setduanzi:function (state,payload) {
    state.duanzi = payload
  }
}
<template>
    <div>
        <button @click="clickEvent">获取段子</button>
        <ul v-for="item in duanzi">
            <li >{{item.msg}}</li>
            <li >{{item.time}}</li>
        </ul>
    </div>
</template>

<script>
    import {mapState} from 'vuex'

    export default {

        computed: mapState([
            'duanzi'
        ]),

        methods: {
            clickEvent: function () {
                this.$store.dispatch('setduanzi')     // dispatch调用store的action方法
            }
        }
    }
</script>

mapActions 辅助函数

<template>
    <div>
        <button @click="setduanzi">获取段子</button>
        <ul v-for="item in duanzi">
            <li >{{item.msg}}</li>
            <li >{{item.time}}</li>
        </ul>
    </div>
</template>

<script>
    import {mapState,mapActions} from 'vuex'

    export default {

        computed: {
            ...mapState(['duanzi'])
        },

        methods: {
            ...mapActions(['setduanzi'])
        }
    }
</script>

Module

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

不开启命名空间:

  1. 在store目录下新建一个模块product.js,写product特有的state数据,getter计算属性,mutations修改数据的方法,actions异步修改数据的方法,并导出。
import Vue from 'vue'
export default {
    state: {
        productNum:10,
        products:null
    },
    getters:{
        productNumMsg:function (state) {
            return state.productNum+"件商品";
        }
    },
    mutations: {
        addProductNum:function (state) {
            state.productNum++;
        },
        showProduct:function (state,payload) {
            state.products=payload;
        }
    },
    actions: {
        showProduct:function (context) {
            var url = "../product.json";
            Vue.axios.get(url).then(
                function (response) {
                    context.commit("showProduct",response.data);
                }
            )
        }
    }
}
  1. 在index.js中的modules块中引入
import product from "./product";

modules: {
    product
}
  1. 编写测试页面,mapState映射的是modules块中的product名称,通过product.products继续获得对应的数据。
<template>
  <div>
    <button @click="showProduct">获取产品</button>
    <ul v-for="item in product.products">
      <li>{{item.name}}</li>
      <li>{{item.price}}</li>
      <li>{{productNumMsg}}</li>
    </ul>
    <button @click="addProductNum">添加数量</button>
  </div>
</template>

<script>
  import {mapGetters, mapState,mapMutations,mapActions} from "vuex";
  var mapStateObj = new mapState(['product']);
  var mapGettersObj = new mapGetters(['productNumMsg']);
  var mapMutationsObj = new mapMutations(['addProductNum','showProduct']);
  var mapActionsObj = new mapActions(['showProduct']);

  export default {
    computed: {
      ...mapStateObj,
      ...mapGettersObj
    },
    methods:{
      ...mapMutationsObj,
      ...mapActionsObj
    }
  }
</script>

开启命名空间:

  1. 在product.js中加入 namespaced: true
export default {
    namespaced: true,
    ...
  1. 修改测试页面,在各个map对象前面加入命名空间名称。
import {mapGetters, mapState,mapMutations,mapActions} from "vuex";
var mapStateObj = new mapState('product',['products']);
var mapGettersObj = new mapGetters('product',['productNumMsg']);
var mapMutationsObj = new mapMutations('product',['addProductNum','showProduct']);
var mapActionsObj = new mapActions('product',['showProduct']);
posted @ 2020-09-28 10:04  Baby丿太依赖  阅读(185)  评论(0)    收藏  举报