美文网首页
Vue学习笔记八:Vuex

Vue学习笔记八:Vuex

作者: 开发者连小超 | 来源:发表于2019-06-19 23:25 被阅读0次

    0.什么是Vuex

    vuex是管理数据状态的一个库,通过创建一个集中的数据存储,供所有组件去访问,类似于Java中一个static的Map。


    没有vuex.png

    上图中,【根组件】可以通过prop给【组件1】、【组件2】,【组件1】和【组件2】再通过prop给【详情组件】和【添加组件】传值。
    如果【添加组件】想要更改数据,这时需要触发event传值给【组件2】,【组件2】再触发event传值给【根组件】,【根组件】值变化会分别往下传递。
    如果现在【添加组件】和【详情组件】共用一个数据,这就很麻烦了,使用vuex解决这个问题。


    使用vuex.png
    vuex有store专门存储数据,如果【组件2】想要获取数据,可以使用getter,如果【添加组件】想要更改数据,可以使用mutation。

    1.使用vuex

    //安装 
    npm install vuex --save
    

    新建store.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export const store = new Vuex.Store({
        state:{
            products:[
                {name:'马云',price:200},
                {name:'马化腾',price:140},
                {name:'马冬梅',price:20},
                {name:'马蓉',price:5},
            ]
        }
    })
    
    

    main.js

    import {store} from './store/store'
    
    new Vue({
        el:'app',
        store,
        router,
        render: h=>h(APP)
    })
    

    组件中使用

    <template>
      <div>
       <ul>
         <li v-for="(item, index) in products" :key="index">{{item.name}}</li>
       </ul>
      </div>
    </template>
    <script>
    export default {
      data () {
        return {
          products:[]
        }
      },
      methods: {
    
      },
      created() {
       this.products = this.$store.state.products
      }
    }
    </script>
    

    2.Getters

    store.js

    export default new Vuex.Store({
      state: {
        products:[
          {name:'马云',price:200},
          {name:'马化腾',price:140},
          {name:'马冬梅',price:20},
          {name:'马蓉',price:5}
        ]
      },
      getters: {
        saleProducts:(state) => {
          let saleProducts = state.products.map(product => {
              return {
                  name: '**' +product.name+ '**',
                  price: product.price/2
              }
          })
          return saleProducts
        }
      }
    }
    

    组件中

    <script>
      created() {
       this.products =this.$store.getters.saleProducts
      }
    </script>
    

    3.Mutations

    作用:更改Vuex的store中的状态的唯一方法是提交Mutation
    store.js

    export const store = new Vuex.Store({
        strict: true, //严格模式改变vuex值时必须使用Mutation,不能直接改
        state:{
            products:[
                {name:'马云',price:200},
                {name:'马化腾',price:140},
                {name:'马冬梅',price:20},
                {name:'马蓉',price:5},=
            ]
        },
        mutations: {
            reducePrice: (state) => {
                state.products.forEach(product => {
                    product.price -= 1
                })
            }
        }
    })
    

    组件中

    <script>
    export default {
        methods: {
            reducePrice:function(){
                this.$store.commit('reducePrice')
            }
        }
    }
    </script>
    

    4.Actions

    1.使用Action解决的问题

    在store.js里mutations的reducePrice()方法中,假设修改值需要请求后台获取结果后再操作,此时方法内是异步调用,我们使用setTimeout模拟异步操作。

    export default new Vuex.Store({
      state: {
        products:[
          {name:'马云',price:200},
          {name:'马化腾',price:140},
          {name:'马冬梅',price:20},
          {name:'马蓉',price:5}
        ]
      },
      mutations: {
        reducePrice: (state) => {
          //模拟发送请求获取数据
          setTimeout(()=>{
            state.products.forEach(product => {
              product.price -= 1
            })
          },2000)
        }
      }
    })
    

    组件中调用方法

      methods: {
        reducePrice:function(){
            this.$store.commit('reducePrice')
        }
      }
    

    此时点击触发reducePrice()方法,结果如下图


    图片.png

    上图中, mutations早已触发,但是因为方法内部是异步的,页面值会延迟2s修改,在开发过程中,调试时会存在误解。
    解决方法就是:用action让数据发生变化同时触发reducePrice方法。

    2.如何使用Action

    store.js

    export const store = new Vuex.Store({
        strict: true, //严格模式改变vuex值时必须使用Mutation,不能直接改,不要在发布环境下启用严格模式!
        state:{
          products:[
                {name:'马云',price:200},
                {name:'马化腾',price:140},
                {name:'马冬梅',price:20},
                {name:'马蓉',price:5},=
            ]
        },
        mutations: {
            reducePrice: (state, payload) => {
                state.products.forEach(product => {
                    product.price -= payload
                })
            }
        },
        actions: {
            reducePriceAction:(context, payload) => {
                setTimeout(function(){
                    context.commit("reducePrice",payload)
                },2000)
            }
        }
    })
    

    组件中

    <script>
    export default {
        methods: {
            reducePrice:function(amount){
                this.$store.dispatch("reducePriceAction",this.amount)
            }
        }
    }
    </script>
    

    此时,点击按钮,2s后改变值的同时触发mutations的reducePrice()方法


    图片.png

    5.Mapping Actions & Getters

    如果store.js中getter或actions有很多方法,组件使用时候得一个一个写,比较麻烦,使用...mapGetters和...mapActions解决。

    1.使用...mapGetters

    <template>
      <div>
        <ul>
          <li v-for="(item, index) in saleProducts" :key="index">{{item.name}}</li>
        </ul>
      </div>
    </template>
    <script>
    import { mapGetters } from 'vuex'
    export default {
      computed: {
          ...mapGetters([
              "saleProducts"
          ])
      }
    }
    </script>
    

    2.使用...mapActions

    <template>
      <div>
        <button @click="reducePriceAction">减价</button>
        <ul>
          <li v-for="(item, index) in products" :key="index">{{item.price}}</li>
        </ul>
      </div>
    </template>
    <script>
    import { mapActions } from 'vuex'
    export default {
      methods: {
        ...mapActions([
          'reducePriceAction'
        ])
        //或者这样写也可以 <button @click="reducePrice">减价</button>
        //...mapActions({
        //  reducePrice:'reducePriceAction'
        //})
      }
    }
    </script>
    

    相关文章

      网友评论

          本文标题:Vue学习笔记八:Vuex

          本文链接:https://www.haomeiwen.com/subject/ebqrqctx.html