vuex 的使用

参考官方文档
https://vuex.vuejs.org/zh-cn/

Vuex 是什么?

官方是这么解释的:

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,
并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、
状态快照导入导出等高级调试功能。

读完了,你发现,这说的啥啊?完全没有看懂啊?
好吧!那就简单总结一句话,vuex就是处理vue中组件之间通信的
有了这个,你再也不用烦恼vue跨组件通信了。
因为Vuex里的数据都是响应式的,任何组件使用同一store的数据,
只要store的数据变化,与之对应的组件都会立即变化

安装

npm安装

npm install vuex --save

CDN
https://unpkg.com/vuex
这种方式引入的话,要放在vue.js后边
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>

装好后怎么使用它?
首先在src目录下建立一个store文件,再这个文件夹下新建一个index.js,打开index.js

写入代码

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

Vue.use(Vuex)

export default new Vuex.Store({

})
或者
const store =  new Vuex.Store({

})
export default store

在main.js引入这个文件

// index.js创建完毕然后打开main.js
import Vue from 'vue'

import App from './App'

// 引入store文件下的index.js,如果你是index.js文件
// 引入的时候可以省略index.js,若是其它文件名.js请全部引入
// 比如:import store from './store/store.js'
import store from './store'


new Vue({
  el: '#app',
  store, // 然后再这里使用一下
  components: { App },
  template: '<App/>'
})

下边介绍核心概念就4个

State  
Getter
Mutation
Action
废话不多说,啥意思看官方解释,这里只说怎么用

State

state干啥的,官方解释一大堆,看完了我也觉得懵逼,这是啥啊?
其实state简单理解就是存储数据的,相当于我们的.vue文件里的data里造数据差不多

打开store文件下的index.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  state:{
    //这里我们创建个数组
    foodlist:[
      {name:'大米',price:20,count:5},
      {name:'鸡腿',price:10,count:8},
      {name:'沙拉',price:5,count:10},
      {name:'土豆',price:13,count:2}
    ]
  }
})

准备两个组件(名字你随意啊)

Header.vue

// 在Header.vue中拿到存在state里的数据然后渲染在页面中
// 1.直接使用$store.state.foodlist获取state里的数据(你在state里定义的是什么名字就用什么名字)
<template>
    <div class="header">
        <span>食物</span>
        <span>价格</span>
        <span>数量</span>
        <ul>
            <li v-for="(food,index) in list" :key="index">
               {{food.name}}———{{food.price}}————{{food.count}}    
            </li> 
        </ul>  
    </div>
</template>

<script>
export default {
    data(){
        return{
            list:this.$store.state.foodlist
        }
    }
};
</script>

<style scoped>
span{
    margin-left: 40px;
}
.header {
  width: 600px;
  height: 200px;
  margin-left: 50px;
  border: 1px solid #000;
  background-color: antiquewhite;
}
</style>

Foot.vue

<template>
    <div class="foot">
        <span>食物</span>
        <span>价格</span>
        <span>数量</span>
        <ul>
            <li v-for="(food,index) in list" :key="index">
               {{food.name}}———{{food.price}}————{{food.count}}    
            </li> 
        </ul>  
    </div>
</template>

<script>
export default {
    data(){
        return{
            list:this.$store.state.foodlist
        }
    }
};
</script>

<style scoped>
span{
    margin-left: 40px;
}
.foot {
  width: 600px;
  height: 200px;
  margin-left: 50px;
  background-color: azure;
  border: 1px solid #000;
  margin-top: 50px;
}
</style>

使用了$store
两个组件的数据是不是一毛一样!这时候不同的组件就都拿到了数据
后边的3个方法就只用一个组件测试了!其它组件用法都一样的

改写header.vue

// 上边这种方法虽然也可以拿到数据,但官方推荐使用计算属性的方式获取数据
<template>
    <div class="foot">
        <span>食物</span>
        <span>价格</span>
        <span>数量</span>
        <ul>
            <li v-for="(food,index) in getList" :key="index">
               {{food.name}}———{{food.price}}————{{food.count}}    
            </li> 
        </ul>  
    </div>
</template>

<script>
export default {
    computed:{
        // 定义一个方法,return 你的数据
        getList(){
            return this.$store.state.foodlist;
        }
    }
};
</script>

Mutation

这里不先说getter,因为很好明白,state存数据,那getter看名字就知道是取数据,因为已经有$store.state可以
取到数据了,我们等会说getter,这里我们说改变数据,在组件内,来自store的数据只能读取,那我们肯定想怎么改
state里的数据,而修改store里的数据的唯一途径就是显示的提交mutation,啥意思啊!看不懂最后一句,没有关系,
我们知道你有改数据的需求的地方,只会在某一个组件内,而你不可能手动去store里改,因为state里的数据都是接口
请求下来的,那么怎么改呢,我们需要用$store.commit(),官方解释的这个方法是在组件内向store里显示提交mutation

说白了,就是在你的mutation里先定义好了一个操作state里的数据的方法,然后在你的组件里调一下你定义
-----------------------------------------------------

在mutation里那个的方法名,不过需要注意的是mutation里的方法不推荐进行异步操作,这个我们等会说
-----------------------------------

打开store的js文件

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

Vue.use(Vuex)

export default new Vuex.Store({
  state:{
    //这里我们创建个数组
    foodlist:[
      {name:'大米',price:20,count:5},
      {name:'鸡腿',price:10,count:8},
      {name:'沙拉',price:5,count:10},
      {name:'土豆',price:13,count:2}
    ]
  },
  mutations:{
    // 定义一个增加价格的方法
    addPrice(state){
        // 先遍历数组,获取到价格属性
        state.foodlist.forEach(e => {
          //这里得到每一个对象
            //console.log(e) 
            e.price +=5; //每次点击+5
        });
    }
  }
})

Header.vue文件中调用

// 准备一个点击事件(样式代码就不贴了)
<template>
    <div class="foot">
        <span>食物</span>
        <span>价格</span>
        <span>数量</span>
        <ul>
            <li v-for="(food,index) in getList" :key="index">
               {{food.name}}———{{food.price}}————{{food.count}}    
            </li> 
        </ul>
        //按钮点击事件
        <button @click="add">点击加5</button>  
    </div>
</template>

<script>
export default {
    computed:{
        getList(){
            return this.$store.state.foodlist;
        }
    },
    methods:{
        add(){
            // 这里调用你定义的增加价格的方法
            this.$store.commit('addPrice')
        }
    }
};
</script>

有装vue-devtools插件的看的很清楚贴个图

20180502231737513.png
// 这里也是接受传参的,修改代码传个参数5
<script>
export default {
    computed:{
        getList(){
            return this.$store.state.foodlist;
        }
    },
    methods:{
        add(){
            this.$store.commit('addPrice',5)
        }
    }
};
</script>

store里的js

// mutation 默认接收的第一个参数就是state
mutations:{
  // 定义一个增加价格的方法
  addPrice(state,num){
      // 先遍历数组,获取到价格属性
      state.foodlist.forEach(e => {
        //这里得到每一个对象
          //console.log(e) 
          e.price +=num; //每次点击+5
      });
  }
}

1.png

mutation 异步操作出现的问题

上边说过,mutation里的方法不推荐进行异步操作,那会出现什么问题,
这里我们用延时模拟个异步,我们点击按钮进行+5的操作,2秒后让页面数据改变

打开store下的js文件

// 模拟延时2秒
  mutations:{
    // 定义一个增加价格的方法
    addPrice(state,num){
        // 先遍历数组,获取到价格属性
        state.foodlist.forEach(e => {
            setTimeout(function(){
              e.price +=num;
            },2000) //延时2秒
        });
    }
  }

这时候你在页面中点击按钮一次,过了两秒,数据改变了,当你连点时,你会发现你都不点了,数据还在页面中慢慢变化,
这显然不是我们想要的,这时候你打开控制台,你会看到方法都执行了,数据还没有变化,知道运行到最后一次执行的时
候,数据才变化完,这个时候我们就要用另一个属性了action

2.png

Action

action和muation很像,只不过不同的是action里提交的mutation,啥意思?
就是在action属性里调用的是mutation里的方法,而且只能对mutation进行操作

打开store下的js文件

// 添加action属性

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

Vue.use(Vuex)

export default new Vuex.Store({
  state:{
    //这里我们创建个数组
    foodlist:[
      {name:'大米',price:20,count:5},
      {name:'鸡腿',price:10,count:8},
      {name:'沙拉',price:5,count:10},
      {name:'土豆',price:13,count:2}
    ]
  },
  mutations:{
    // 定义一个增加价格的方法
    addPrice(state,num){
        // 先遍历数组,获取到价格属性
        state.foodlist.forEach(e => {
          //这里得到每一个对象
            //console.log(e) 
            e.price +=num; //每次点击+5
        });
    }
  },
  actions:{
      Moniyibu(context){
        console.log(context)
        setTimeout(function(){
          context.commit('addPrice',5)
        },2000)
      }
  }
})

header.vue中

// 在组件内触发 action 里的方法,只能通过$store.dispatch 来触发
<template>
    <div class="foot">
        <span>食物</span>
        <span>价格</span>
        <span>数量</span>
        <ul>
            <li v-for="(food,index) in getfood" :key="index">
               {{food.name}}———{{food.price}}————{{food.count}}    
            </li> 
        </ul>
        <button @click="add">+</button>  
    </div>
</template>

<script>
export default {
    computed:{
        getList(){
            return this.$store.state.foodlist;
        },
        getfood(){
            return this.$store.getters.getfoodName
        }
    },
    methods:{
        add(){
        // 触发action的方法Moniyibu
          this.$store.dispatch('Moniyibu',5)
        }
    }
};

这时候你再查看那个控制台,你会发现,点击按钮,2秒钟后方法才执行

Getter

该说的都说了,最后来说下getter,上边说了,getter也是获取数据的,但它里边的数据通常都是处理过的数据
比如有这样一个需求,我们获取state里食物价格大于10的数据

打开store下的js文件

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

Vue.use(Vuex)

export default new Vuex.Store({
  state:{
    //这里我们创建个数组
    foodlist:[
      {name:'大米',price:20,count:5},
      {name:'鸡腿',price:10,count:8},
      {name:'沙拉',price:5,count:10},
      {name:'土豆',price:13,count:2}
    ]
  },
  // getters 使用
  getters:{
      // 获取价格大于10的数据
      getfoodName:state =>{
        
        /**
         * filter 过滤,会根据你的判端条件进行筛选,把满足条件的数据返回组成一个新的数组,
         * 这里要把这个数组再return 回去,你也可以定一个变量接收这个新数组,然后return这个变量
         */
        return  state.foodlist.filter(foodname =>{
            //获取每一条对象
            console.log(foodname) 
            // 返回每条数据价格大于10的数据
            return foodname.price > 10
        })
      }
  },
  mutations:{
    // 定义一个增加价格的方法
    addPrice(state,num){
        // 先遍历数组,获取到价格属性
        state.foodlist.forEach(e => {
          //这里得到每一个对象
            //console.log(e) 
            e.price +=num; //每次点击+5
        });
    }
  }
})

Header.vue中获取getter里的数据

// 依旧写在计算属性里 使用 $store.getters.getter里的方法名
<template>
    <div class="foot">
        <span>食物</span>
        <span>价格</span>
        <span>数量</span>
        <ul>
            <li v-for="(food,index) in getfood" :key="index">
               {{food.name}}———{{food.price}}————{{food.count}}    
            </li> 
        </ul>
        <button @click="add">+</button>  
    </div>
</template>

<script>
export default {
    computed:{
        getList(){
            return this.$store.state.foodlist;
        },
        getfood(){
            return this.$store.getters.getfoodName
        }
    },
    methods:{
        add(){
            this.$store.commit('addPrice',5)
        }
    }
};
</script>

文章来源--https://blog.csdn.net/qq_36407748/article/details/80174272

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343