Vuex入门

1.Vuex是什么?

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

刚接触Vuex,看这么官方的解释可能也没什么帮助!了解了下它的用处,操作了简单demo后,我对它大概有个初步的了解。我认为Vuex充当着一个“桥梁”的角色,它方便了多个类似组件间共用一个资源,进行传值,对于量大的项目实现起来更加高效!以上是我的个人见解,希望指点和交流!

2.Vuex的安装

Vuex也有多种安装方式,在这里依然采用npm进行安装。

npm install vuex --save

如果出现下图,表明安装完成。

此时,可以在package.json文件中查看到vuex已经安装好,如图:

3.Vuex项目

依然要通过vue-cli脚手架来搭建一个项目,这里介绍一下cnpm的安装与使用。

安装淘宝镜像:

npm install -g cnpm --registry=https://registry.npm.taobao.org

测试是否安装成功:

cnpm -v

如果出现对应的版本号,表明安装成功,就可以使用cnpm了。

全局安装vue-cli:

cnpm install -g vue-cli

测试是否安装成功:

vue -V

初始化项目:

vue init webpack-simple vuex-demo

打开项目:

//进入文件夹下
cd vuex-demo
//安装依赖
cnpm install 
//运行服务
cnpm run dev

父子组件中传值,之前说到过要用props或者$emit.

实现效果:两个模块内容一样

分析:如果是在父组件中有个公共资源,子组件使用需要标签绑定一下,然后通过props传递值才能使用.然后相同的东西全都是拷贝两份,如果多个呢?这样就不太合理了,因此来学习Vuex的使用。

上面已经进入到项目中,接下来安装好Vuex,在src下新建文件夹store并新建文件store.js.然后在main.js中引入新建的store.js,并在实例化对象中使用.

//这是store.js文件
//引入Vue和Vuex
import Vue from 'vue'
import Vuex from 'vuex'

在Vue中使用Vuex
Vue.use(Vuex)

//定义store并允许外部使用,把公共资源products提取出来,放在state下
export const store = new Vuex.Store({
	state:{
		products:[
	        {name:"A",price:200},
	        {name:"B",price:140},
	        {name:"C",price:20},
	        {name:"D",price:10},
        ]
	}
})
//这是main.js文件
//main.js引入store.js
import {store} from './store/store'

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

然后在App.vue中删除公共数据products以及组件标签的绑定信息.

//这是App.vue
<template>
  <div id="app">
    <!--不使用Vuex前-->
    <!-- <product-list-one v-bind:products="products"></product-list-one>
    <product-list-two v-bind:products="products"></product-list-two> -->
    <product-list-one></product-list-one>
    <product-list-two></product-list-two>
  </div>
</template>

<script>
import ProductListOne from './components/ProductListOne.vue'
import ProductListTwo from './components/ProductListTwo.vue'
export default {
  name: 'app',
  components:{
    'product-list-one':ProductListOne,
    'product-list-two':ProductListTwo
  },
  data () {
    return {
      //共用资源
      // products:[
      //   {name:"A",price:200},
      //   {name:"B",price:140},
      //   {name:"C",price:20},
      //   {name:"D",price:10},
      // ]
    }
  }
}
</script>

<style>

</style>

然后,分别在两个组件中删除原来的props以及data,使用computed.

<script>
export default {
  //这是未使用Vuex前
  // props:["products"],
  // data () {
  //   return {
      
  //   }
  // }

  //使用computed来得到products的值
  computed:{
    products(){
      return this.$store.state.products;
    }
  }
</script>

这样就简单使用了Vuex,使用了state,Vuex有五大核心:State、Getter、Mutation、Action、Module.下面继续介绍.

State:用来存储数据

Getter:用来获取数据

针对上面项目的基础,如果此时需要显示信息价格为原数据的5折,这时候需要定义方法:

//html中products换为对应的saleProducts
<li v-for="product in saleProducts">
    <span class="name">{{product.name}}</span>
    <span class="price">${{product.price}}</span>
</li>

//定义的打折方法
saleProducts(){
   //取到数据后进行修改
   var saleProducts = this.$store.state.products.map(product=>{
      return {
         //新的展示样式
         name:"**" + product.name +"**",
         price:product.price / 2
      }
   })
   //返回最后的数据
   return saleProducts;
}

同理,两个组件都需要这么写,也有点累赘。那么在store.js中提取方法

getters:{
    //state就是上面state里面的product数据
	saleProducts:(state)=>{
	     var saleProducts = state.products.map(product=>{
	        return {
	          name:"**" + product.name +"**",
	          price:product.price / 2
	        }
	      })
	     return saleProducts;
    }
},

然后,在组件中直接返回数据即可,是不是很容易了呢!

//定义的打折方法
saleProducts(){
  //返回最后的数据,直接调用store.js中getters下的方法即可
   return this.$store.getters.saleProducts;
}

Mutation:用来触发事件改变

在组件中添加一个按钮,点击一下降价.

//html
<button @click="reducePrice">商品降价</button>


//script
methods:{
    reducePrice:function(){
       this.$store.state.products.forEach(product=>{
         product.price -= 1;
       })
    }
}

当然,这样就可以了。我们使用mutation来实现一下:

mutations:{
	reducePrice:(state)=>{
			state.products.forEach(product=>{
        		product.price -= 1;
      		})
		}
	}
}
reducePrice:function(){
   this.$store.commit('reducePrice');
}

Action:提交Mutation、异步操作

如果要点击按钮后滞后2s达到效果呢?这个时候需要action.

actions:{
	reducePrice:(context,payload)=>{
		setTimeout(function(){
			context.commit('reducePrice',payload);
		},2000)
	}
}
reducePrice:function(amount){
   this.$store.dispatch("reducePrice",amount);
}

Module:模块化

最后说一下mapGetters和mapActions.

安装babel:

cnpm install babel-preset-stage-2 --save-dev

它的主要功能就是多个方法,引入之后可以直接在...mapGetters/...mapActions里面写一下就可以了,直接调用store.js中的方法.

<script>
//引入
import {mapGetters} from 'vuex'
import {mapActions} from 'vuex'

export default {
  computed:{
    products(){
      return this.$store.state.products;
    },
    ...mapGetters([
      "saleProducts"
    ])
   //多个方法,注释掉直接使用mapGetters
    // saleProducts(){
    //   // var saleProducts = this.$store.state.products.map(product=>{
    //   //   return {
    //   //     name:"**" + product.name +"**",
    //   //     price:product.price / 2
    //   //   }
    //   // })
    //   // return saleProducts;
    //   return this.$store.getters.saleProducts;
    // }
  },
  methods:{
    // reducePrice:function(amount){
    //   // this.$store.state.products.forEach(product=>{
    //   //   product.price -= 1;
    //   // })
    //   // this.$store.commit('reducePrice');
    //   this.$store.dispatch("reducePrice",amount);
    // }
    //同理
    ...mapActions([
      "reducePrice"
    ])
  }
}
</script>

猜你喜欢

转载自my.oschina.net/GracefulTing/blog/1798049