1 vuex的基础
vuex主要应用于vue中管理数据状态的一个库,通过创建一个集中的数据存储,供程序中所有组件访问。
先创建一个项目叫做vuex-test
npm install
npm install install express -g
npm install -g vue-cli
vue init webpack-simple vuex-test
cd vuex-test
npm install
npm run dev
2 创建组件
ProductListOne.vue
<template>
<div id="product-list-one">
<h2>product list one</h2>
<ul>
<li v-for="product in products">
<span class="name">{{product.name}}</span>
<span class="price">{{product.price}}</span>
</li>
</ul>
</div>
</template>
<script>
export default {
props:['products'],
data () {
return {
}
}
}
</script>
<style scoped>
#product-list-one{
background: #fff8d1;
box-shadow: 1px 2px 3px rgba(0,0,0,0.2);
margin-bottom: 30px;
padding: 10px 20px;
}
#product-list-one ul{
padding:0;
list-style-type: none;
}
#product-list-one li{
display: inline-block;
margin-top: 10px;
margin-right: 10px;
padding: 20px;
background: rgba(255,255,255,0.7);
}
.price{
font-weight:bold;
color:#e8800c;
}
</style>
ProductListTwo.vue
<template>
<div id="product-list-two">
<h2>product list two</h2>
<ul>
<li v-for="product in products">
<span class="name">{{product.name}}</span>
<span class="price">{{product.price}}</span>
</li>
</ul>
</div>
</template>
<script>
export default {
props:['products'],
data () {
return {
}
}
}
</script>
<style scoped>
#product-list-two{
background: #d1e4ff;
box-shadow: 1px 2px 3px rgba(0,0,0,0.2);
margin-bottom: 30px;
padding: 10px 20px;
}
#product-list-two ul{
padding:0;
list-style-type: none;
}
#product-list-two li{
margin-top: 10px;
margin-right: 10px;
padding: 20px;
background: rgba(255,255,255,0.7);
}
.price{
font-weight:bold;
color:#860ce8;
display: block;
}
</style>
app.vue
<template>
<div id="app">
<product-list-one v-bind:products="products"></product-list-one>
<product-list-two v-bind:products="products"></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:'马云',price:200},
{name:'马化腾',price:140},
{name:'马冬梅',price:20},
{name:'马蓉',price:10}
]
}
}
}
</script>
<style>
body{
font-family: UBuntu;
color:#555;
}
</style>
3 搭建vuex中央管理
创建一个文件夹叫做store,下面再创建一个store.js
import Vue from 'vue';
import vuex from 'vuex';
Vue.use(vuex);
export const store=new vuex.Store({
state:{
products:[
{name:'马云',price:200},
{name:'马化腾',price:140},
{name:'马冬梅',price:20},
{name:'马蓉',price:10}
]
}
})
4 使用computed获取store的数据
在main.js中引入store
import Vue from 'vue'
import App from './App.vue'
import {store} from './store/store.js';
new Vue({
store:store,
el: '#app',
render: h => h(App)
})
其他两个组件使用computed引入数据
<script>
export default {
computed:{
products(){
return this.$store.state.products
}
}
}
</script>
5 vuex-getters
store.js
import Vue from 'vue';
import vuex from 'vuex';
Vue.use(vuex);
export const store=new vuex.Store({
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 in saleProducts">
<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
},
saleProducts(){
return this.$store.getters.saleProducts;
}
}
}
</script>
<style scoped>
#product-list-one{
background: #fff8d1;
box-shadow: 1px 2px 3px rgba(0,0,0,0.2);
margin-bottom: 30px;
padding: 10px 20px;
}
#product-list-one ul{
padding:0;
list-style-type: none;
}
#product-list-one li{
display: inline-block;
margin-top: 10px;
margin-right: 10px;
padding: 20px;
background: rgba(255,255,255,0.7);
}
.price{
font-weight:bold;
color:#e8800c;
}
</style>
6 vuex-mutations
store.js
import Vue from 'vue';
import vuex from 'vuex';
Vue.use(vuex);
export const store=new vuex.Store({
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=>{
state.products.forEach(product => {
product.price-=1;
});
}
}
})
组件:
<template>
<div id="product-list-one">
<ul>
<li v-for="product in saleProducts">
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
</ul>
<button @click="reducePrice">商品降价</button>
</div>
</template>
<script>
export default {
computed:{
products(){
return this.$store.state.products
},
saleProducts(){
return this.$store.getters.saleProducts;
}
},
methods:{
reducePrice(){
//触发了store里的降价的方法
this.$store.commit('reducePrice')
}
}
}
</script>
<style scoped>
#product-list-one{
background: #fff8d1;
box-shadow: 1px 2px 3px rgba(0,0,0,0.2);
margin-bottom: 30px;
padding: 10px 20px;
}
#product-list-one ul{
padding:0;
list-style-type: none;
}
#product-list-one li{
display: inline-block;
margin-top: 10px;
margin-right: 10px;
padding: 20px;
background: rgba(255,255,255,0.7);
}
.price{
font-weight:bold;
color:#e8800c;
}
</style>
7 vuex-actions
store.js
import Vue from 'vue';
import vuex from 'vuex';
Vue.use(vuex);
export const store=new vuex.Store({
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;//参数来自actions
});
}
},
actions:{
reducePrice:(context,payload)=>{
setTimeout(function(){
context.commit('reducePrice',payload);//这个名字来自mutations,参数来自组件
},2000)
}
}
})
组件
<template>
<div id="product-list-one">
<ul>
<li v-for="product in saleProducts">
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
</ul>
<button @click="reducePrice(4)">商品降价</button>
</div>
</template>
<script>
export default {
computed:{
products(){
return this.$store.state.products
},
saleProducts(){
return this.$store.getters.saleProducts;
}
},
methods:{
reducePrice(amount){
//触发了store里的降价的方法
//this.$store.commit('reducePrice')//这个名字来自mutations
this.$store.dispatch('reducePrice',amount)//这个名字来自actions,参数传递给actions
}
}
}
</script>
<style scoped>
#product-list-one{
background: #fff8d1;
box-shadow: 1px 2px 3px rgba(0,0,0,0.2);
margin-bottom: 30px;
padding: 10px 20px;
}
#product-list-one ul{
padding:0;
list-style-type: none;
}
#product-list-one li{
display: inline-block;
margin-top: 10px;
margin-right: 10px;
padding: 20px;
background: rgba(255,255,255,0.7);
}
.price{
font-weight:bold;
color:#e8800c;
}
</style>
8 vuex-map
先下载一个东西
npm install babel-preset-stage-2 --save-dev
然后在.babelrc中配置一下
{
"presets": [
["env", { "modules": false }],
"stage-3",
["stage-2"]
]
}
然后在组件中引入并使用
<template>
<div id="product-list-one">
<ul>
<li v-for="product in saleProducts">
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
</ul>
<button @click="reducePrice(4)">商品降价</button>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {mapActions} from 'vuex';
export default {
computed:{
products(){
return this.$store.state.products
},
// saleProducts(){
// return this.$store.getters.saleProducts;
// }
...mapGetters([
"saleProducts"
])
},
methods:{
// reducePrice(amount){
// //触发了store里的降价的方法
// //this.$store.commit('reducePrice')//这个名字来自mutations
// this.$store.dispatch('reducePrice',amount)//这个名字来自actions,参数传递给actions
// }
...mapActions([
"reducePrice"
])
}
}
</script>
<style scoped>
#product-list-one{
background: #fff8d1;
box-shadow: 1px 2px 3px rgba(0,0,0,0.2);
margin-bottom: 30px;
padding: 10px 20px;
}
#product-list-one ul{
padding:0;
list-style-type: none;
}
#product-list-one li{
display: inline-block;
margin-top: 10px;
margin-right: 10px;
padding: 20px;
background: rgba(255,255,255,0.7);
}
.price{
font-weight:bold;
color:#e8800c;
}
</style>