[Vue.js启航]——使用Vuex进行状态管理
来源:互联网 发布:知乎911是美国自导自演 编辑:程序博客网 时间:2024/05/29 16:41
Vue.js启航——英雄编辑器(五)
简介
这一篇博客将是这一系列博客的最终篇,主要探讨的是Vuex插件的使用。先介绍一下Vuex。Vuex是Vue框架的状态管理插件,采用集中式存储管理应用的所有组件的状态。状态通俗来讲就是组件中的数据,状态的管理也就是各个组件中数据的管理。当你的应用足够简单的话,我们可以使用中央事件总线的方式来实现简单的管理,具体可以参考 [Vue.js启航]——多组件应用构建 ,当我们要构建中大型的单页应用的时候我们才会考虑使用Vuex来集中管理组件的状态。这篇文章我们会继续 [Vue.js启航]——多组件应用构建,去掉中央事件总线,采用Vuex进行改造。
使用Vuex的多组件英雄编辑器
使用Vuex的多组件英雄编辑器和使用时间总线的多组件英雄编辑器实现出来的效果是一样的
最主要的改造就是将bus
换成Vuex.Store实例,将hero
Vue实例中的computed
选项作一些调整。
Vuex.Store实例
跟中央时间总线一样,使用Vuex管理状态也需要一个额外的组件实例,在中央时间总线中是一个Vue实例,而在Vuex中则是Vuex.Store实例。最简单的Vuex.Store应该包括state
和mutations
选项,其中state
选项存储的是需要管理的状态,而mutations
则是控制状态转变的一些方法,例如在官方指南中,mutations
中有一个改变state
中count
的方法
var store=new Vuex.Store({ state:.. mutations:{ increment (state){ state.count++; } }})
当我们的组件需要使用mutations
的方法更改state
的状态时只需要调用
store.commit('increment')
使用载荷传递参数
在我们的例子中需要将选中的英雄作为参数传递给mutations
中的方法。在这里就直接拿我们的代码举例子了,使用载荷的mutations
的写法是这样的
//...mutations:{ selectHero(state,selectedHero){ state.hero=selectedHero }}
在英雄列表中的调用方式是
store.commit('selectHero',this.selectedHero)
但这并不是官方推荐的写法,官方的规范中要求,载荷应该是一个对象,这样可以包含多个字段并且记录的mutation
更加易读,我们继续使用载荷对象进行改造
//...mutations:{ selectHero(state,payload){ state.hero=payload.selectedHero; }}
然后在英雄列表中的调用方式是
store.commit({ type:'selectHero', selectedHero:this.selectedHero})
组件或者实例获取状态
当我们把Vuex.Stroe实例编写好之后,已经把状态和改变状态的方法都集中起来进行管理了,那接下来我们就要获取状态的值了。获取状态值的一般方法是return store.state.xxx
xxx为状态值,例如我们在这里需要获取hero
的状态值就写return sotre.state.hero
,在这个例子中,我们只需要在hero
实例中的computed
选项中返回状态值就好
//..computed:{ hero:function(){ return store.state.hero; }}
到这里我们就完成了从中央事件总线到Vuex的转变。
模块化的Sotre
其实一些有经验的人到这里可能就会问,我们把所有的组件的状态都交由一个Store管理,那么,当我们要管理的状态很多,那Store不就会膨胀了吗?其实Vuex的设计者早就想到了这一点,所以Vuex允许使用模块化管理Store。每一个模块其实就是拥有state
和mutations
,actions
,getters
中的一个或多个选项的JS对象,这里我们只使用了state
和mutations
。构建模块化Store的代码如下:
var moduleA={ state:{...}, mutations:{...}, ...}var moduleB={ state:{...}, mutations:{...}, ...}
然后在Store实例中将各个模块组装起来
var store=new Vuex.Store({ modules:{ a:moduleA, b:moduleB }})
获取状态的话使用
store.state.a.state.xxxx
总结
这篇文章主要是介绍了Vuex的简单使用,配合Vue-Router,和Vue本身组成了Vue的核心部分。Vuex当然不止文章中用到的state
和mutations
还有包含异步操作的actions
以及用于筛选数据或者格式化输出的getters
。模块化系统还有命名空间等内容。在这里接触到关于Vuex的内容其实差不多,就不多详述了。
这一系列的文章也就结束了,接下来会新开一系列的文章,主要关于模块化构建系统构建Vue应用,使用单文件组件,和Vue-Router、Vuex的进阶使用和Vue的核心概念等。
可运行代码
hero.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="hero.css"></head><body> <div id="hero"> <hero-list v-bind:heroes="heroes" v-bind:title="title"></hero-list> <hero-detail v-bind:hero="hero"></hero-detail> </div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script src="https://unpkg.com/vuex@2.3.1"></script><script src="hero.js"></script></html>
hero.js//十位英雄数据const HEROES=[{ id: 11, name: 'Mr. Nice' },{ id: 12, name: 'Narco' },{ id: 13, name: 'Bombasto' },{ id: 14, name: 'Celeritas' },{ id: 15, name: 'Magneta' },{ id: 16, name: 'RubberMan' },{ id: 17, name: 'Dynama' },{ id: 18, name: 'Dr IQ' },{ id: 19, name: 'Magma' },{ id: 20, name: 'Tornado' }];//Vuex.Store实例var store=new Vuex.Store({ state:{ hero:"" }, mutations:{ selectHero(state,payload){ state.hero=payload.selectedHero; } }})//多个组件//英雄详情组件Vue.component("hero-detail",{ props:["hero"], template:'\ <div v-if="hero">\ <h2>{{hero.name}}</h2>\ <div><label>id:</label>{{hero.id}}</div>\ <div>\ <label>name:</label>\ <input v-model="hero.name" placeholder="name"/>\ </div>\ </div>\ ',})//英雄列表组件Vue.component("hero-list",{ props:["title","heroes"], template:'\ <div>\ <h1>{{title}}</h1>\ <h2>My Heroes</h2>\ <ul class="heroes">\ <li v-for="hero in heroes"\ v-on:click="onSelect(hero)"\ v-bind:class="{selected:hero===selectedHero}">\ <span class="badge">{{hero.id}}</span>{{hero.name}}\ </li>\ </ul>\ </div> \ ', methods:{ onSelect:function(hero){ this.selectedHero=hero //bus.$emit("selectHero",this.selectedHero); store.commit({ type:'selectHero', selectedHero:this.selectedHero }) } }, data:function(){ return {selectedHero:""}; }})var hero=new Vue({ el:"#hero", data:{ heroes:HEROES, title:"Tour of Heroes", }, computed:{ hero:function(){ return store.state.hero; } },})
hero.cssh1 { color: #369; font-family: Arial, Helvetica, sans-serif; font-size: 250%;}h2, h3 { color: #444; font-family: Arial, Helvetica, sans-serif; font-weight: lighter;}.selected { background-color: #CFD8DC !important; color: white;}body { margin: 2em;}body, input[text] { color: #888; font-family: Cambria, Georgia;}.heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em;}.heroes li { cursor: pointer; position: relative; left: 0; background-color: #EEE; margin: .5em; padding: .3em 0; height: 1.6em; border-radius: 4px;}.heroes li.selected:hover { background-color: #BBD8DC !important; color: white;}.heroes li:hover { color: #607D8B; background-color: #DDD; left: .1em;}.heroes .text { position: relative; top: -3px;}.heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0 0.7em; background-color: #607D8B; line-height: 1em; position: relative; left: -1px; top: -4px; height: 1.8em; margin-right: .8em; border-radius: 4px 0 0 4px;}[class*='col-'] { float: left; padding-right: 20px; padding-bottom: 20px;}[class*='col-']:last-of-type { padding-right: 0;}a { text-decoration: none;}h3 { text-align: center; margin-bottom: 0;}h4 { position: relative;}.grid { margin: 0;}.col-1-4 { width: 23%;}.module { padding: 20px; text-align: center; color: #eee; max-height: 120px; min-width: 120px; background-color: #607D8B; border-radius: 2px;}.module:hover { background-color: #EEE; cursor: pointer; color: #607d8b;}.grid-pad { padding: 10px 0;}.grid-pad > [class*='col-']:last-of-type { padding-right: 20px;}@media (max-width: 600px) {.module { font-size: 10px; max-height: 75px; }}@media (max-width: 1024px) {.grid { margin: 0;}.module { min-width: 60px;}}nav a { padding: 5px 10px; text-decoration: none; margin-top: 10px; display: inline-block; background-color: #eee; border-radius: 4px;}nav a:visited, a:link { color: #607D8B;}nav a:hover { color: #039be5; background-color: #CFD8DC;}nav a.router-link-active { color: #039be5;}button { margin-top: 20px; font-family: Arial; background-color: #eee; color: #888888; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; cursor: hand;}button:hover { background-color: #cfd8dc;}button:disabled { background-color: #eee; color: #ccc; cursor: auto;}
- [Vue.js启航]——使用Vuex进行状态管理
- 在Vue中使用Vuex进行状态管理指南
- Vue中状态管理——Vuex
- Vue.js数据状态管理-Vuex(-)
- [Vue.js启航]——Vue-Router的使用
- 前端框架Vue(10)——vuex 状态管理
- Vue.js数据状态管理-Vuex(二)
- vue + vuex 的状态管理的简单使用
- 简单实用vue状态管理vuex
- Vue.js状态管理工具Vuex快速上手
- [Vue.js启航]——数据的双向绑定
- [Vue.js启航]——主从结构应用构建
- [Vue.js启航]——多组件应用构建
- Vue.js启航
- vuex (状态管理)
- Vue---使用vuex
- Vue---使用vuex
- 使用 Vuex + Vue.js 构建单页应用
- 扩增子分析QIIME2. 8数据筛选Filtering data
- The 36 questions
- 使用nfs启动内核时,“Retry count exceeded; starting again”
- Android主题相关(初探)
- SequenceInputStream 实现文件的切割与合并
- [Vue.js启航]——使用Vuex进行状态管理
- C# DataGridView添加新行的2个方法
- P1192 台阶问题
- leetcode[Largest Palindrome Product]
- Dijkstra模板求单源点最短路径
- 实参和形参
- Spring —— IOC控制反转
- dos命令窗口下下java命令提示找不到或无法加载主类
- spring mvc 和struts2的区别