大家都知道Vue的父传子用在很多场景,比如像这样:
父组件:
<template> <div id="app"> <product-list-one :msg='msg'></product-list-one> </div> </template> <script> export default { name: 'app', components:{ 'product-list-one':ProductListOne, }, data () { return { msg:'love' } } } </script>
子组件:
<template> <div id="product-list-one"> <div>{{msg}}</div> </div> </template> <script> props:['msg'] </script>
有父传子,当然也有子传父:
子组件:
<template> <div id="product-list-one"> <button @click="but">点击</button> </div> </template> <script> data(){ return { txt:'hello' } }, methods:{ but() { this.$emit('get',this.txt); } } </script>
父组件:
<template> <div id="app"> <product-list-one :msg='msg' @get='world'></product-list-one> </div> </template> <script> import ProductListOne from './components/ProductListOne.vue' export default { name: 'app', components:{ 'product-list-one':ProductListOne }, methods:{ world(data){ console.log(data) } } } </script>
但是有些场景如果使用父传子、子传父的话,很难实现。比如说:
a组件
跟b组件
相互通信,必须要有一个公共变量库才更方便。 所以Vuex
应运而生,通过创建一个集中的数据存储,供程序中所有组件访问。
一、安装
npm install vuex
二、配置
创建一个store
文件夹在根目录src
下,然后在文件夹里创建一个名叫index.js
文件。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ strict:true, state:{}, getters:{}, mutations:{}, actions:{} });
然后在src
文件夹下的main.js
文件里引入store
。
import Vue from 'vue' import App from './App.vue' import {store} from './store/store' new Vue({ store:store, el: '#app', render: h => h(App) })
三、实际操作
Vuex分为四大板块:
- state
- getters
- mutations
- actions
那么我们接下来分别讲解一下
。
1、state
state
用于存储数据。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ strict:true, state:{ products:[ {name:"马云",price:200}, {name:"马化腾",price:140}, {name:"马冬梅",price:20}, {name:"马蓉",price:10} ] } });
使用this.$store.state.products
获取获取数据。
<template> <div id="product-list-one"> <ul> <li v-for="(product,index) in saleProducts" :key="index"> <span class="name">{{product.name}}</span> <span class="price">${{product.price}}</span> </li> </ul> </div> </template> <script> export default { computed:{ products(){ return this.$store.state.products; } }, } </script>
2、getters
getters
用于获取数据。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ strict:true, state:{ products:[ {name:"马云",price:200}, {name:"马化腾",price:140}, {name:"马冬梅",price:20}, {name:"马蓉",price:10} ] }, getters:{ saleProducts: (state) =>{ var saleProducts = state.products.map(product =>{ return { name: "**" + product.name + "**", price: product.price / 2 }; }); return saleProducts; } } });
调用获取数据的方法。
<template> <div id="product-list-one"> <ul> <li v-for="(product,index) in saleProducts" :key="index"> <span class="name">{{product.name}}</span> <span class="price">${{product.price}}</span> </li> </ul> </div> </template> <script> import {mapGetters} from 'vuex' export default { computed:{ ...mapGetters([ "saleProducts" ]) } } </script>
3、mutations
mutations
用于变更state
中的状态。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ strict:true, state:{ products:[ {name:"马云",price:200}, {name:"马化腾",price:140}, {name:"马冬梅",price:20}, {name:"马蓉",price:10} ] }, getters:{ saleProducts: (state) =>{ var saleProducts = state.products.map(product =>{ return { name: "**" + product.name + "**", price: product.price / 2 }; }); return saleProducts; } }, mutations:{ reducePrice: (state,payload) =>{ state.products.forEach(product =>{ product.price -= payload; }) } } });
mutations
更像是事件注册,所以需要我们需要store.commit()
触发一下。
<template> <div id="product-list-one"> <ul> <li v-for="(product,index) in saleProducts" :key="index"> <span class="name">{{product.name}}</span> <span class="price">${{product.price}}</span> </li> </ul> <button @click="reducePrice(2)">商品降价</button> </div> </template> <script> import {mapGetters} from 'vuex' export default { computed:{ products(){ return this.$store.state.products; }, ...mapGetters([ "saleProducts" ]) }, methods:{ reducePrice (n) { this.$store.commit('reducePrice',n); } } } </script>
4、actions
actions
用于提交的是mutations
,而不是直接提交状态。actions
可以包含任意异步操作。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ strict:true, state:{ products:[ {name:"马云",price:200}, {name:"马化腾",price:140}, {name:"马冬梅",price:20}, {name:"马蓉",price:10} ] }, getters:{ saleProducts: (state) =>{ var saleProducts = state.products.map(product =>{ return { name: "**" + product.name + "**", price: product.price / 2 }; }); return saleProducts; } }, mutations:{ reducePrice: (state,payload) =>{ // setTimeout(function(){ state.products.forEach(product =>{ product.price -= payload; }) // },3000); } }, actions:{ reducePrice:(context,payload) =>{ setTimeout(function(){ context.commit("reducePrice",payload); // context.commit()相当于 this.$store.commit(),触发mutations事件。 },2000); } } });
需要用store.dispatch()
触发actions
,但是为了方便,我们这里使用mapActions
。
<template> <div id="product-list-one"> <ul> <li v-for="(product,index) in saleProducts" :key="index"> <span class="name">{{product.name}}</span> <span class="price">${{product.price}}</span> </li> </ul> <button @click="reducePrice(2)">商品降价</button> </div> </template> <script> import {mapGetters} from 'vuex' import {mapActions} from 'vuex' export default { props:['msg'], data(){ return { txt:'hello' } }, computed:{ products(){ return this.$store.state.products; }, ...mapGetters([ "saleProducts" ]) }, methods:{ ...mapActions([ "reducePrice" ]) } } </script>