如何使用vuex

如何使用vuex

目标:在一个项目中使用vuex,并正确执行。

如何使用vuex 项目实例之gitHub地址:https://github.com/WangShuangshuang/vuex
项目截图:

思路:

1. 用 new Vuex.store({  }) 创建一个vuex的实例,并把这个实例传入到main.js中的new Vue({  })对象中。

2. Vuex.store()构造函数接收一个对象,这个对象有4个重要的组成部分(每个组成也是对象):state, getters, mutations, actions。

  2.1 state - vuex实例的数据模型  

  2.2 getters - vuex实例根据数据模型做的计算属性

  2.3 mutations - 各个组件想要更改vuex的数据模型时,必须通过(vuex实例的commit方法)commit某一个mutation而执行;每个mutation都必须是同步执行的方法

  2.4 actions - 组件如果想用异步方法来更新数据模型(比如请求一个接口得到响应数据之后,再去更新vuex的数据模型),这时就需要通过(vuex实例的dispatch方法)dispatch某一个action而执行;而每一个action的内部通过commit mutation的方式去改变数据模型

3. vuex的设计蕴含着面向对象的思想,vuex实例有自己内部的数据,而外部的方法不应该直接改变这些数据,所以必须通过调用vuex实例内部的方法,这些内部方法再去改变内部数据。保证数据的改变是可控的。

Step1 安装vuex:

 安装:
    npm install vuex --save
  使用:
    在main.js文件中,新增如下代码:

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

Vue.use(Vuex)

Step2 在main.js中,创建并注入vuex的实例对象

main.js内容:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import App from './App.vue'

Vue.config.productionTip = false

const store = new Vuex.Store({
  /* 1/4 state:数据 */
  state: {
    count: 1,
    price: 100,
  },

  /* 2/4 getters:store的计算属性 */
  getters: {
    cost(state){ // state参数必须有
      return state.count * state.price;
    },
    memberCost(state, getters){ // state, getters参数都必须有
      return getters.cost * 0.85;
    },
    // 返回值为方法的
    discountCost: (state) => (discount) => { return state.count * state.price * discount }
  },

  /* 3/4 mutations:改变数据的同步方法 */
  mutations: {
    increment(state){
      state.count++
    },
    reduce(state){
      state.count--
    },
    clear(state){
      state.count = 0;
    },
    // 附带参数的
    incrementSome(state, payload){
      state.count += payload.amount;
    },
  },

  /* 4/4 actions: 以提交mutation的形式改变数据的异步方法 */
  actions: {
    incrementAsync(context, options){ // context对象与store实例具有相同的方法和属性,但不是后者本身
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          context.commit('incrementSome', options);
          resolve({ message: 'add sucess' });
        }, 1000);
      })
    },
    clear({ commit }){
      return new Promise((reject, resolve) => {
        var res = confirm('Sure to clear ?');
        if(res){
          commit('clear');
          resolve({ message: 'clear success' })
        } else {
          reject({ message: 'would not clear' })
        }
      })
    }
  }
})

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


Step3 创建两个组件MyHello1.vue和MyHello2.vue

MyHello1.vue内容:

<template>
  <div class="hello">
    <h1>MyHello1</h1>
    <p>
      COUNT: <span class="count">{{ count }}</span> * PRICE: {{ price }}
      <br>总价:{{ cost }} 
      <br>会员价:{{ memberCost }} 
      <br>折扣价:<input class="input" v-model="discount" /> {{ discountCost(discount) }}
    </p>
    <button @click="add">Add</button>
    <br><button @click="addTwo">AddTwo</button>
    <br><button @click="addAsync">AddAsync</button>
  </div>
</template>

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

export default {
  name: 'MyHello1',
  data(){
    return {
      text: 'abcdef',
      discount: 0.5,
    }
  },
  computed: {
    textLength(){
      return this.text.length;
    },
    ...mapState([
      'count', 'price',
    ]),
    ...mapGetters([
      'cost', 'memberCost', 'discountCost'
    ]),
    ...mapActions([
      'incrementAsync'
    ])
  },
  methods:{
    add(){
      this.$store.commit('increment');
    },
    addTwo(){
     this.$store.commit({
       type: 'incrementSome',
       amount: 2,
     })
     // 等效写法: 
     // this.$store.commit('incrementSome', { amount: 2 })
    },
    addAsync(){
      this.$store.dispatch('incrementAsync', { amount: 10 })
        .then((data) => { // then()的参数为resolve方法的具体实现
          console.log(data.message);
        })
        .catch((data) => { // catch()的参数为reject方法的具体实现
          console.log(data.message);
        })
    }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.count{
  color: red;
}
.input{
  width:30px;
  height:30px;
  line-height:30px;
}
</style>

MyHello2.vue内容:

<template>
  <div class="hello">
    <h1>MyHello2</h1>
    <p>count: <span class="count">{{ count }}</span></p>
    <button @click="add">Add</button>
    <br><button @click="clear">Clear</button>
  </div>
</template>

<script>
import { mapState } from 'vuex';

export default {
  name: 'MyHello2',
  computed: {
    ...mapState([
      'count'
    ])
  },
  methods:{
    add(){
      this.$store.commit('increment');
    },
    clear(){
      this.$store.dispatch('clear')
        .then((data) => {
          console.log(data.message);
        })
        .catch((data) => {
          console.log(data.message);
        })
    }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.count{
  color: red;
}
</style>

Step4 在App.vue中引用上面两个组件:

App.vue内容:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <MyHello1/>
    <hr />
    <MyHello2/>
  </div>
</template>

<script>
import MyHello1 from './components/MyHello1.vue'
import MyHello2 from './components/MyHello2.vue'

export default {
  name: 'app',
  components: {
    MyHello1,
    MyHello2,
  }
}
</script>

<style>
</style>

本文结束。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值