了解vue
什么是Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态,其实指的是实例之间的共享数据,Vuex是管理应用中不同Vue实例之间数据共享的工具。
下图是Vuex官方提供的对于状态管理模式的设计理念。
为什么使用Vuex
通俗的讲,就是为了方便组件与组件之间的数据共享。
我们知道,父子组件之间想要共享数据,可以使用props属性,子父组件之间的通信可以使用$emit触发一个事件。
随着我们的web应用不断的丰富,组件之前通信采用的props和事件将会充斥着我们的整个项目,逻辑也会越来越复杂,程序员不得不将精力从业务逻辑的实现上转移到组件之间的通信上。日后的维护也会不断的复杂。
理论上,我们可以通过一个全局的共享数据来实现各个组件之间的数据共享,但是,当一个组件修改了这个全局数据时,其他组件对该全局数据的引用都会跟随者改变,并且不留下任何痕迹,这种实现方式,会导致调试变为噩梦。
这个时候,我们迫切需要一个管理组件之间数据的共享的工具,Vuex出现了。
什么情况下我该使用Vuex
虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
如何使用Vuex
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
安装
本文使用npm安装vuex,初始化一个vuex项目目录,然后:
1 |
npm install vuex --save |
也可以直接下载vuex.js,然后在script标签中引用。
开始使用
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 |
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="./node_modules/vue/dist/vue.min.js"></script> <script src="./node_modules/vuex/dist/vuex.min.js"></script></head><body> <div id="app"></div> <script> Vue.use(Vuex); const myStore = new Vuex.Store({ state: { name: "Alex", }, mutations: {}, getters: {}, actions: {} }); let App = { template: ` <div> <p>{{ name }}</p> </div> `, computed: { name: function () { return this.$store.state.name; }, } }; new Vue({ el: "#app", store: myStore, template: `<app></app>`, components: { 'app': App, }, }) </script> </body></html> |
在以上代码中,我们使用Vue.use(Vuex)告诉Vue实例使用Vuex进行状态管理,并使用Vuex.Store创建了一个Vuex实例,上文提到,Store是Vuex的核心,它是一个容器,包含了几个核心属性。打印一下Vue实例对象,我们可以看到这几个核心属性,如下图:
创建Vue实例时将新建的Vuex实例注册到Vue实例中,即可在Vue实例中查看到$store属性。四个核心属性都已经创建好了。
核心概念
接下来,我们需要理解Vuex中的几个核心概念。
State
用来存放组件之间共享的数据。他跟组件的data选项类似,只不过data选项是用来存放组件的私有数据。
Getter
有时候,我们需要对state的数据进行筛选,过滤。这些操作都是在组件的计算属性进行的。
如果多个组件需要用到筛选后的数据,那我们就必须到处重复写该计算属性函数,或者将其提取到一个公共的工具函数中,并将公共函数多处导入 - 两者都不太理想。
如果把数据筛选完在传到计算属性里就不用那么麻烦了,这就是getter的作用,来看下面的代码:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="./node_modules/vue/dist/vue.min.js"></script> <script src="./node_modules/vuex/dist/vuex.min.js"></script></head><body> <div id="app"></div> <script> Vue.use(Vuex); const store = new Vuex.Store({ state: { name: "Pizza", age: 22, }, getters: { getAge: function (state) { return state.age + 1; } } }); let App = { template: ` <div> <span>{{ name }}</span> <span>{{ age }}</span> </div> `, computed: { name: function () { return this.$store.state.name; }, age: function () { return this.$store.getters.getAge; } }, }; new Vue({ el: "#app", template: `<App></App>`, store: store, components: { App } }) </script> </body></html> |
注意在getters中getAge必须使用state访问数据,而不是this。
在计算属性中,我们使用this.$store.getters.getAge来访问需要计算的数据。
Mutation
前面讲到的都是如何获取state的数据,那如何把数据存储到state中呢?
在 Vuex store 中,实际改变状态(state) 的唯一方式是通过提交(commit) 一个 mutation。
mutations下的函数接收state作为第一个参数,接收payload作为第二个参数,payload是用来记录开发者使用该函数的一些信息,有一点需要注意:mutations方法必须是同步方法!
请看下面的代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="./node_modules/vue/dist/vue.min.js"></script> <script src="./node_modules/vuex/dist/vuex.min.js"></script></head><body> <div id="app"></div> <script> Vue.use(Vuex); const store = new Vuex.Store({ state: { name: "Pizza", age: 18, score: 100, hobby: ["girls", "books"] }, mutations: { score: function (state, payload) { console.log("state: ", state); console.log("payload: ", payload); return state.score -= 10; }, hobby: function (state, payload) { return state.hobby.push(payload); } }, getters: { getAge: function (state) { return state.age + 1; } } }); let App = { template: ` <div> <p>{{ name }}</p> <p>{{ age }}</p> <p>{{ score }}</p> <p>{{ hobby }}</p> <button @click="changeScore">点击修改分数</button> <button @click="changeHobby">点击修改爱好</button> `, computed: { name: function () { return this.$store.state.name; }, age: function () { return this.$store.state.age; }, score: function () { return this.$store.state.score; }, hobby: function () { return this.$store.state.hobby; } }, methods: { changeScore: function () { this.$store.commit('score', 10); }, changeHobby: function () { this.$store.commit('hobby', 'movie') } } }; new Vue({ el: "#app", template: `<App></App>`, components: { App }, store }) </script> </body></html> |
我们提交了一个this.$store.commit(“score”, 10),传入的第一个参数指的是mutations中定义的参数,第二个参数是需要变更的数据。
Action
Actions用来处理异步事务。
Actions 提交的是 mutations,而不是直接变更状态。也就是说,actions会通过mutations,让mutations帮他提交数据的变更。
Action 可以包含任意异步操作。比如ajax、setTimeout、setInterval。继续看下面的代码:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="./node_modules/vue/dist/vue.min.js"></script> <script src="./node_modules/vuex/dist/vuex.min.js"></script></head><body> <div id="app"></div> <script> Vue.use(Vuex); const store = new Vuex.Store({ state: { name: 'Pizza', age: 18, score: 90, }, mutations: { changeScoreAsync: function (state, payload) { return state.score += payload; } }, actions: { addScore: function (context, payload) { setTimeout(() => context.commit("changeScoreAsync", payload), 3000); } } }); let App = { template: ` <div> <span>{{ name }}</span> <span>{{ age }}</span> <span>{{ score }}</span> <button @click="changeScore">点击一会儿修改数据</button> `, computed: { name: function () { return this.$store.state.name; }, age: function () { return this.$store.state.age; }, score: function () { return this.$store.state.score; }, }, methods: { changeScore: function () { this.$store.dispatch("addScore", 1); } } }; new Vue({ el: "#app", template: `<App></App>`, store, components: { App } }) </script> </body></html> |
点击修改数据后,this.$store.dispatch找到actions中定义的方法,并将当前状态的store对象封装,传递给actions中函数的第一个参数context,随后由context.commit提交修改。
项目结构
Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
- 应用层级的状态应该集中到单个 store 对象中;
- 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的;
- 异步逻辑都应该封装到 action 里面。
只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
了解vue的更多相关文章
- Vue.js 和 MVVM 小细节
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
- Vue + Webpack + Vue-loader 系列教程(2)相关配置篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ 使用预处理器 在 Webpack 中,所有的预处理器需要和一个相应的加载器一同使用.vue- ...
- Vue + Webpack + Vue-loader 系列教程(1)功能介绍篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue-loader 是一个加载器,能把如下格式的 Vue ...
- 关于Vue.js 2.0 的 Vuex 2.0,你需要更新的知识库
应用结构 实际上,Vuex 在怎么组织你的代码结构上面没有任何限制,相反,它强制规定了一系列高级的原则: 应用级的状态集中放在 store 中. 改变状态的唯一方式是提交mutations,这是个同步 ...
- Vue.js 2.0 和 React、Augular等其他框架的全方位对比
引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那么你就来对了. 客观来说,作为核心团队成员,显然我们会 ...
- 窥探Vue.js 2.0 - Virtual DOM到底是个什么鬼?
引言 你可能听说在Vue.js 2.0已经发布,并且在其中新添加如了一些新功能.其中一个功能就是"Virtual DOM". Virtual DOM是什么 在之前,React和Em ...
- 初探Vue
Vue.js(读音/vju:/,类似于view),是近来比较火的前端框架,但一直没有怎么具体了解.实现过,就知道个啥的MVVM啦,数据驱动啦,等这些关于Vue的虚概念. 由于最近,小生在公司中,负责开 ...
随机推荐
- 批处理设置IP地址 - imsoft.cnblogs
批处理设置IP地址 不知朋友们是否有这样的经历,把本本带到单位上网时,由于单位需要配固定IP地址,而家里是自动获得IP地址的,所以每天都要对这个IP地址设置来设置去,那么有没有简单方便的办法呢?其实我 ...
- 20分钟打造你的Bootstrap站点
来源:http://www.w3cplus.com/css/twitter-bootstrap-tutorial.html 特别声明:此篇文章由白牙根据Leon Revill的英文文章原名<Tw ...
- 在word文档里提取出所有的邮箱地址
怎样在word文档里提取出所有的邮箱地址 文档内容太多,邮箱也有很多,一个个复制粘贴太浪费时间,怎样把这些邮箱简单的提取出来 答案:用查找功能. 查找目标:[A-z,0-9]{1,}\@[A-z,0 ...
- with() {} 的用法
var use = "other"; var katana = { isSharp: true, use: function(){ this.isSharp = !!this.is ...
- UVA 156:Ananagrams (vector+map+sort)
题意:一大堆单词中间有空格隔开,以'#'结束输出,问只出现一次的的单词有哪些(如果两个具有相同的长度,相同的字母也算是相同的,不区分大小写,如:noel和lone属于一个单词出现两次).最后按照字典序 ...
- 关于凑数问题的dfs
https://www.nowcoder.com/acm/contest/42/F 首先由于是单一解问题,所以使用返回值类型为bool的dfs 然后为了保证dfs的效率性,应该把加数dfs放在前面,不 ...
- 动态绑定AJAX,获取下级分类并延迟执行
HTML: <div id='allType'> <div class='allTypeHead'><span>所有分类</span></div& ...
- yarn 知识点
yarn 与 npm 功能对应表格: 命令 yarn npm 初始化 yarn init npm init 安装项目所有包(注意) yarn npm install 添加 dependencies y ...
- winform自定义控件 (转帖)
定义控件 本文以按钮为例,制作一个imagebutton,继承系统button, 分四种状态 1,正常状态 2,获得焦点 3,按下按钮 4,禁用 当然你得准备一张图片,包含四种状态的样式,同样你也可以 ...
- IE 10 如何设置支持CRM4 正常浏览
通过工具—> 选择兼容性视图 就可以了.具体如下图: