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>