作者:小土豆biubiubiu

博客园:www.cnblogs.com/HouJiao/

掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d

简书:https://www.jianshu.com/u/cb1c3884e6d5

微信公众号:土豆妈的碎碎念(扫码关注,一起吸猫,一起听故事,一起学习前端技术)

码字不易,点赞鼓励哟~

一.前言

  vuex被称为是专为vue应用程序开发的的状态管理模式。它的作用使用一句话描述就是:让组件之间可以共享数据

  话不多少,先抛开概念,我们写一个简单的示例感受一波。

二.项目开发环境

  项目开发环境搭建请移步作者的另外一篇文章《使用vue-cli搭建项目开发环境》

  本次的项目目录如下:

  

三.安装vuex

  使用vuex前需要先进行安装,安装命令:npm install vuex --save--dev

  

四.创建和访问共享数据

1.使用vuex创建全局共享数据

  我们先需要在E:\MyStudy\test\VueDemo\src\目录下新建一个目录vuex和文件store.js

  

  现在在store中使用vuex创建一个全局的共享数据

E:\MyStudy\test\VueDemo\src\vuex\store.js

import Vue from 'vue'
import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({
// 在state中创建一个全局共享的数据 counter
state: {
counter: 0
}
})

  可以看到使用vuex创建一个共享数据的语法也比较简单,即在new Vuex.Store中定义state对象,在state对象中就可以创建全局的共享对象,本次我们创建了一个counter数据。

2.入口文件中配置vuex

  共享数据前面我们已经创建好了,接着需要在入口文件main.js中配置vuex

    1.引入我们编写的关于vuex的代码模块store.js

    2.在根实例上配置vuex

E:\MyStudy\test\VueDemo\src\main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router/router'
//1.引入vuex
import store from './vuex/store'
Vue.config.productionTip = false /* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
router: router,
// 2.根实例上配置vuex
store: store
})

3.组件中获取共享数据

  前面我们已经完成了两件事:使用vuex创建了共享数据counter和配置了vuex。

  接着我们就需要在组件中访问这个共享数据counter

  我们先新建一个Index.vue组件,在该组件中编写访问counter的代码

E:\MyStudy\test\VueDemo\src\components\Index.vue

 <template>
<div>
<h1>这里是Index.vue组件</h1>
<h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>
</div>
</template>
<script>
export default {
name: 'Index'
}
</script>

  访问共享数据counter的代码为:

<h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>

  接着在App.vue中编写同样的代码访问这个counter,并且在App.vue组件中将Index.vue组件引入并展示。

E:\MyStudy\test\VueDemo\src\App.vue

 <template>
<div id="app">
<img src="./assets/logo.png">
<!-- 获取共享数据 -->
<h1>这里是App组件</h1>
<h1> App组件获取共享数据 : {{ $store.state.counter }} </h1>
<hr/>
<Index></Index>
</div>
</template> <script>
import Index from './components/Index'
export default {
name: 'App',
components: { Index }
}
</script> <style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

4.浏览器查看结果

  我们分别在App.vue组件和Index.vue组件中访问了共享数据counter,现在我们启动项目在浏览器中看下结果。

  

  可以看到,App组件和Index组件均可以访问到counter的值。

  

  到此,我们简单的创建一个共享数据并且在组件中成功的访问到了这个共享数据,这里我们做一个小总结

    1.安装vuex:npm install vuex

    2.全局配置vuex:创建vuex实例,调用store方法配置在state中创建共享数据。

    3.组件中使用$store.state.counter可以访问到共享数据

五.修改共享数据

1.在store定义共享数据的修改状态

  vuex中,假如需要改变共享数据,必须在vuex实例对象的Store方法中约定这个变化。

  我们在store.js中对counter做两个约束:递增和递减。

E:\MyStudy\test\VueDemo\src\vuex\store.js

 import Vue from 'vue'
import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({
// 在state中创建一个全局共享的数据 counter
state: {
counter: 0
},
mutations: {
// 递增
increase(state) {
state.counter++
},
// 递减
decrement(state) {
state.counter--
}
}
})

  其中13行的increase方法就是约定共享数据counter每次递增1;

  17行的decrement方法约定共享数据counter每次递减1。  

2.组件中触发counter递增和递减

  我们在App.vue组件中触发counter递减,在Index.vue中触发counter递增

E:\MyStudy\test\VueDemo\src\App.vue

 <template>
<div id="app">
<img src="./assets/logo.png">
<!-- 获取共享数据 -->
<h1>这里是App组件</h1>
<h1> App组件获取共享数据 : {{ $store.state.counter }} </h1>
<button v-on:click="$store.commit('decrement')">点击触发共享数据counter递减1</button>
<hr/>
<Index></Index>
</div>
</template> <script>
import Index from './components/Index'
export default {
name: 'App',
components: { Index }
}
</script> <style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

E:\MyStudy\test\VueDemo\src\components\Index.vue

<template>
<div>
<h1>这里是Index.vue组件</h1>
<h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>
<button v-on:click="$store.commit('increase')">点击该组件触发共享数据counter递增1</button>
</div>
</template>
<script>
export default {
name: 'Index'
}
</script>

  可以看到在组件中触发共享数据counter递增和递减的逻辑分别为:$store.commit('increase') 和 $store.commit('decrement'),即使用$store.commit方法并传递对应的函数名称。

3.浏览器查看结果

  

  可以看到,点击App组件中的按钮,成功的将counter加1,且Index组件中的数据也自动更新;

  点击Index组件中的按钮,成功的将counter加1,App组件中的数据也自动更新

六.异步修改共享数据

  假设我们上面的递增递减的需求变成:点击按钮后,过3秒再去修改counter的值。那么这个时候应该怎么实现呢?我们直接上代码。

E:\MyStudy\test\VueDemo\src\vuex\store.js 

import Vue from 'vue'
import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({
// 在state中创建一个全局共享的数据 counter
state: {
counter: 0
},
mutations: {
// 递增
increase(state) {
state.counter++
},
// 递减
decrement(state) {
state.counter--
}
},
actions: {
increaseAction(context){
setTimeout(function(){
context.commit('increase')
}, 3000);
},
decrementAction(context){
setTimeout(function(){
context.commit('decrement')
}, 3000);
}
}
})

  这里我们有几点需要总结:

  1.异步修改数据定义在actions中,并且通过提交mutations改变共享数据的状态

  2.在组件中需要使用$store.dispatch去触发共享数据的改变

E:\MyStudy\test\VueDemo\src\App.vue  

 <template>
<div id="app">
<img src="./assets/logo.png">
<!-- 获取共享数据 -->
<h1>这里是App组件</h1>
<h1> App组件获取共享数据 : {{ $store.state.counter }} </h1>
<button v-on:click="$store.dispatch('decrement')">点击等待3秒触发共享数据counter递减1</button>
<hr/>
<Index></Index>
</div>
</template> <script>
import Index from './components/Index'
export default {
name: 'App',
components: { Index }
}
</script> <style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

E:\MyStudy\test\VueDemo\src\components\Index.vue  

<template>
<div>
<h1>这里是Index.vue组件</h1>
<h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>
<button v-on:click="$store.dispatch('increase')">点击等待3秒触发共享数据counter递增1</button>
</div>
</template>
<script>
export default {
name: 'Index'
}
</script>

  浏览器查看结果:

  

  可以看到,setTimeout这个异步逻辑成功执行。

  看这里!!!   

  关于上面想要实现的异步递增和递减,我们的第一反应可能就是在mutations中的递增递减函数添setTimeout延迟执行函数,我们来实践一下。

  App.vue和Index.vue不做任何修改,还是前面的内容,只修改store.js。

E:\MyStudy\test\VueDemo\src\vuex\store.js

import Vue from 'vue'
import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({
// 在state中创建一个全局共享的数据 counter
state: {
counter: 0
},
mutations: {
// 递增
increase(state) {
// 添加定时器执行
setTimeout(function(){
state.counter++
},3000); },
// 递减
decrement(state) {
//添加定时器
setTimeout(function(){
state.counter--
},3000); }
}
})

  浏览器看下结果:

  

  

  可以看到效果和actions一样!!!

  没办法,我这人就是想多造作造作,对于mutations官网确实有明确的说明,mutations必须是同步函数。

  

  emmmmm,先抛开官方文档的说法,我们的示例跑出来的结果确实是说明了mutations可以是异步函数。

  那么如何解释官方文档的说法呢?我还是一遍一遍的看了下文档,找到了一些重要的信息:

  

  当我仔细读了红色框里面的内容后,我大概理解了官方文档的为什么说mutation必须是同步函数了。

  原因一:如果是异步函数,在触发mutation的时候,浏览器的调试功能看不到数据的变化;

  原因二:mutation中异步函数中的数据变化无法追踪。

  到这里呢,我们就不继续往下探究了,因为基础的还没有总结完,基础总结完后在探究这个问题。

七.共享数据的计算属性

vue组件中的计算属性想必大家都知道,那么vuex中共享数据的计算属性的用途和原理也是同vue组件中的计算属性。

我们假设vue组件中需要对共享数据做一些其他的转换:将某个字符串进行翻转,并且转为大写。(这个场景项目中几乎不会用到,仅仅为了演示而编造的。)

$store.state.split("").reverse().join("").toUpperCase();

当多个组件都需要这样的转化时,想必写起来也会比较繁琐,因此vuex共享数据的计算属性就帮了我们解决这个问题。下面我们使用vuex的共享数据的计算属性来实现这个需求

E:\MyStudy\test\VueDemo\src\vuex\store.js  在该文件中已经将前面定义的counter删除,重新定义了一个共享数据str

import Vue from 'vue'
import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({
// 在state中创建一个全局共享的数据 str
state: {
str: 'hello'
},
getters: {
reverseAndToUpper(state){
return state.str.split("").reverse().join("");
}
}
})

  关于共享数据的计算属性的访问,我们只在App组件中添加访问代码

E:\MyStudy\test\VueDemo\src\App.vue 在App组件中,将Index组件的引入代码已经删除

 <template>
<div id="app">
<img src="./assets/logo.png">
<!-- 获取共享数据 -->
<h1>这里是App组件</h1>
<h1> App组件获取共享数据 : {{ $store.getters.reverseAndToUpper }} </h1>
</div>
</template> <script>
import Index from './components/Index'
export default {
name: 'App',
components: { Index }
}
</script> <style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

  浏览器查看一下结果:

  

  可以看到,已经成功的访问到了str的计算属性。

八.总结

  前面我们一共实践了vuex的这些内容:

    1.在state中定义共享属性,在组件中可使用[$store.state.属性名]访问共享属性

    2.在mutations可中定义修改共享数据的方法,在组件中可使用[$store.commit('方法名')]同步修改共享属性

    3.在actions中可定义异步修改共享数据的方法,在组件中可使用[$store.dispatch('方法名')]异步修改共享属性

    4.在getters中可定义共享数据的计算属性,在组件中可使用[$store.getters.计算属性名]访问共享数据的计算属性

  后面会继续更新vuex中常用的内容


声明:转载请说明出处

Vuex入门实践(上)的更多相关文章

  1. Vuex入门实践(中)-多module中的state、mutations、actions和getters

    一.前言 上一篇文章<Vuex入门实践(上)>,我们一共实践了vuex的这些内容: 1.在state中定义共享属性,在组件中可使用[$store.state.属性名]访问共享属性 2.在m ...

  2. sass、less和stylus的安装使用和入门实践

    刚 开始的时候,说实话,我很反感使用css预处理器这种新玩意的,因为其中涉及到了编程的东西,私以为很复杂,而且考虑到项目不是一天能够完成的,也很少是 一个人完成的,对于这种团队的项目开发,前端实践用c ...

  3. 全文搜索引擎Elasticsearch入门实践

    全文搜索引擎Elasticsearch入门实践 感谢阮一峰的网络日志全文搜索引擎 Elasticsearch 入门教程 安装 首先需要依赖Java环境.Elasticsearch官网https://w ...

  4. 微服务 + Docker + Kubernetes 入门实践 目录

    微服务 + Docker + Kubernetes 入门实践: 微服务概念 微服务的一些基本概念 环境准备 Ubuntu & Docker 本文主要讲解在 Ubuntu 上安装和配置 Dock ...

  5. Jsp入门实战上

    前面讲了servlet入门实践现在开始介绍jsp入门实践,开发环境的搭建请参考我前面的tomcat的文章,jsp入门教程分为上下两部分,第一部分简单讲解:jsp语法的规范,以及三大编译指令,七个动作指 ...

  6. vuex入门教程和思考 [转] 里面有几个实例

    Vuex基础概念 vuex中涉及的概念主要有下面几点,下面做个简单的介绍和理解. Vuex 官方文档:https://vuex.vuejs.org/zh-cn/ 官网有介绍,也有个demo shopp ...

  7. 0.Python 爬虫之Scrapy入门实践指南(Scrapy基础知识)

    目录 0.0.Scrapy基础 0.1.Scrapy 框架图 0.2.Scrapy主要包括了以下组件: 0.3.Scrapy简单示例如下: 0.4.Scrapy运行流程如下: 0.5.还有什么? 0. ...

  8. Rxjs入门实践-各种排序算法排序过程的可视化展示

    Rxjs入门实践-各种排序算法排序过程的可视化展示 这几天学习下<算法>的排序章节,具体见对排序的总结,想着做点东西,能将各种排序算法的排序过程使用Rxjs通过可视化的方式展示出来,正好练 ...

  9. webpack的入门实践,看这篇就够了

    webpack的入门实践 我会将所有的读者概括为初学者,即使你可能有基础,学习本节之前我希望你具有一定的JavaScript和node基础 文中的 ... ...代表省略掉部分代码,和上面的代码相同 ...

随机推荐

  1. 关于Java语言for循环内外变量定义的问题

    今天看书时,看到一个代码,一个在循环外面没有用的变量,后即有了我的问题,在后面: 我的问题: 变量循环内定义,例如:while(true){String splitStr = null;}这“些”个s ...

  2. 第三期 预测——Frenet 坐标

    Frenet坐标 在讨论过程模型之前,我们应该提到“Frenet Coordinates”,它是一种以比传统x,y笛卡尔坐标更直观的方式表示道路位置的方式. 用Frenet坐标,我们使用变量 s和d描 ...

  3. Java Annotation详解(二): 反射和Annotation

    前面一篇文<Java Annotation详解(一): 理解和使用Annotation>中,我们或许会觉得,Annotation注释其实并没有多大的作用,除了几个内建的Annotation ...

  4. H3C 配置CHAP验证

  5. 最小生成树prim、

    过年那几天确实没好好学习.在老家闲着也是闲着.可是就是没看书. 回来这几天又一直在弄个人博客.买域名云服务器备案什么的- -. 麻烦死了呢. 在腾讯花1块钱备案了一个网站www.goodgoodstu ...

  6. cfp大纲

    AFP基础知识 本章共14个考点,考试考15分左右. 本章重点: .职业道德准则 .家庭财务分析:净值的计算.储蓄的计算 .简单的财务比率分析 .金融理财和法律:企业组织形式.夫妻公共财产制度.财产分 ...

  7. python基础十之装饰器

    1,装饰器的形成 编程原则:开放封闭原则. 开放:对扩展是开放的 封闭:对修改是封闭的 因为修改是封闭的,所以为了对函数进行功能的扩展,就使用装饰器! 2,装饰器的定义 # wrapper就是一个装饰 ...

  8. 设置html各元素不可点击(持续更新)

    1.span <span id="nextStep" onclick="right">下一页</span> $("#nextS ...

  9. win10 uwp release 因为 Entry Point Not Found 无法启动

    本文告诉大家如果在使用 release 编译时,无法启动应用,出现 Entry Point Not Found 如何让应用运行. 程序"[30760] xx.exe"已退出,返回值 ...

  10. Codeforces Beta Round #4 (Div. 2 Only) D. Mysterious Present(LIS)

    传送门 题意: 现在我们有 n 个信封,然后我们有一张卡片,并且我们知道这张卡片的长和宽. 现给出这 n 个信封的长和宽,我们想形成一个链,这条链的长度就是这条链中所含有的信封的数量: 但是需要满足① ...