前端之美-VueJsVUE

vuex快速入门

2019-03-22  本文已影响256人  明灭_

本文为课程 vuex深入浅出 的学习总结与记录;同时参照了vuex官方文档
文中demo的代码可参考:我的码云


一、概念

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

二、在项目中使用vuex

可以通过以下步骤引入vuex

  1. 安装:npm install vuex --save
  2. 创建store目录,用来存放所有状态。大型项目的目录结构可能如下所示:
    image.png
    在此我们只创建一个store.js文件作为示例:
    state中存放的是唯一数据源
import Vue from 'vue'
import Vuex from 'vuex';

Vue.use(Vuex)

export const store = new Vuex.Store({   // 注意Store的S大写
    state: {
        data1: ...,
        data2: ...
        ...
    }
})

  1. main.js中添加如下代码:
import {store} from '../store/index'

new Vue({
  ...
  store,
  ...
})

三、核心概念介绍

原课程是以小demo的形式讲解vuex,在此依同样方法做以记录。
此demo有两个组件listOne.vuelistTwo.vueApp.vue为主组件。
最终效果和初始代码(省略样式)如下:

效果图
store.js:
import Vue from 'vue'
import Vuex from 'vuex';

Vue.use(Vuex)

export const store = new Vuex.Store({   // 注意Store的S大写
    state: {
        productList: [
            {name: 'goods 1',price: 100},
            {name: 'goods 2',price: 200},
            {name: 'goods 3',price: 300},
            {name: 'goods 3',price: 400}
        ]
    }
})

App.vue:

<template>
  <div>
    <list-one/>
    <list-two/>
  </div>
</template>

<script>
import listOne from './components/listOne.vue';
import listTwo from './components/listTwo.vue';

export default {
  name: 'App',
  components: {
    listOne, listTwo
  }
}
</script>

listOne.vue:

<template>
<div class="list-one">
  <h1>list one</h1>
  <ul>
    <li v-for="(product, index) in productList" :key=index>
       <p>名称:{{product.name}}</p>
      <p>价格:{{product.price}}</p> 
    </li>
  </ul>
  <button>降价</button>
  <button>异步降价</button>
</div>
</template>

<script>
  export default {
      data() {
          productList: this.$store.state.productList // 获取store.js > state > productList
      }
  }
</script>

listTwo.vue:

<template>
  <div class="list-two">
    <h1>list two</h1>
    <ul>
      <li v-for="(product, index) in getProductList" :key=index>
        <p>名称:{{product.name}}</p>
        <p>价格:{{product.price}}</p> 
      </li>
  </ul>
</div>
</template>

<script>
import {mapGetters} from 'vuex'

export default {
    data() {
          productList: this.$store.state.productList
    }
}
</script>
核心概念1:state
import {mapState} from 'vuex;

...

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

此时组件中修改如下:

<li v-for="(product, index) in productList" :key=index>

核心概念2:getters

// store.js:
import Vue from 'vue'
import Vuex from 'vuex';

Vue.use(Vuex)

export const store = new Vuex.Store({ 
    state: {
        productList: [
            {name: 'goods 1',price: 100},
            {name: 'goods 2',price: 200},
            {name: 'goods 3',price: 300},
            {name: 'goods 3',price: 400}
        ]
    },
    getters: {
        getSaledPrice: (state) => {
            let saleProduct = state.productList.map((item) => {
                return {
                    name: '**' + item.name + '**',
                    price: item.price / 2
                }
            })
            return saleProduct;
        }
    }
})

listOne.vue中的productList的值更换为this.$store.getters.getSaledPrice:

// listOne.vue
export default {
    data () {
        return {
            productList : this.$store.getters.getSaledPrice 
        }
    }
}

此时效果如下:(注意list one部分名称和价格的变动)

image.png
computed: {
    ...mapGetters:([
        'getSaledPrice',
         ...
    ])
}

核心概念3:mutation

// store.js
mutations: {
    reducePrice: (state, payload) => {
        return state.productList.forEach((product) => {
            product.price -= payload;
        })
    }
}
// listOne.vue
methods: {
    reducePrice(){
        this.$store.commit('reducePrice', 4)
    }
}

点击降价按钮,可以发现价格发生变化:


image.png
// listOne.vue
<template>
    ...
    <button @click="reducePrice(4)">降价</button>
    ...
</template>

<script>
  .....
  methons: {
      ...mapMutations([
         'reducePrice'
      ])
  }
  .....
</script>

核心概念4:action

  1. action提交的是mutation,而不是直接变更状态。
  2. action可以包含异步操作,而mutation不行。
  3. actions中的回调函数的第一个参数是context, 是一个与store实例具有相同属性和方法的对象.
  4. action通过store.dispatch方法触发,mutation通过store.commit方法提交。
// store.js

actions: {   // 提交的是mutation,可以包含异步操作
    reducePriceAsync: (context, payload) => {
        setTimeout(()=> {
            context.commit('reducePrice', payload);  // reducePrice为上一步mutation中的属性
        },2000)
    }
}
methods: {
  reducePriceAsync(){
        this.$store.dispatch('reducePriceAsync', 2)
   },
}

或使用mapActions辅助对象:

// listOne.js

<template>
    ...
    <button @click="reducePriceAsync(4)">异步降价</button>
    ...
</template>

<script>
  .....
  methons: {
     ...mapActions([
          'resducePriceAsync'
     ])
  }
  .....
</script>

核心概念5:module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

image.png
上一篇下一篇

猜你喜欢

热点阅读