背景:小型应用里的每一个组件维护着自有的状态,即当前应用的状态的一部分,因此整个应用的状态被分散在了各个角落,可是咱们常常遇到要把
状态的一部分
共享给多个组件的状况。
状态其实能够形象地想成咱们的 data 里面的各个属性。
Vuex 使用了单状态树(single state tree),一个 store 对象就存储了整个应用层的状态。它让咱们能够更方便地定位某一具体的状态,而且在调试时能简单地获取到当前整个应用的快照。
先埋个伏笔。Vuex 使用的这种 single state tree 与 modularity 模块化是不冲突的,问题是,如何将 state 与 mutation 分到子模块中?
要使用 store ,首先必须
Vue.use(Vuex)
,而后将 store
const store = new Vuex.store()
inject 定义到 Vue 实例 app 中
new Vue({store})
,实现从根组件注入到全部子组件中,接着就能够在子组件中使用
this.$store
当一个组件须要使用多个某 store 的状态属性或 getters ,可使用 shared helper ---- 共享帮手
,它会返回一个对象 。
it('helper: mapState (object)', () =& {
conststore =newVuex.Store({
getters: {
constvm =newVue({
computed: mapState({
// 在 mapState 里面咱们既能够调用 store 的 state ,也能够调用 store 的 getters
a: (state, getters) =&{
returnstate.a + getters.b
expect(vm.a).toBe(3)
store.state.a++
expect(vm.a).toBe(4)
那么如何将它与本地的计算属性结合使用呢?通常咱们会使用一个工具,将多个对象合而为一,再把这个最终的对象传递给 computed。可是这里咱们能够直接使用 es6 的 stage 3 的 object spread operator ---- 对象扩展操做符,来超简洁地实现这一功能。
computed: {
localComputed () {}
// 将其中的属性与本地的计算属性合并在一块儿
...mapState({
message:state=&state.obj.message
有时候咱们须要从 store 的状态派生出其余状态,而后对这个状态(的方法)在多个组件中加以利用。一般咱们的作法是复制这个方法,或者将它封装为一个公用的方法,而后在须要的时候导入,可是二者其实都不甚理想。Vuex 提供了 getters 属性,用途相似 stores 中的计算属性。
getters 中的方法接受两个参数,分别为 state 以及 getters(其余 getters),用法以下。
getters: {
doneTodosCount: (state, getters) =&{
returngetters.doneTodos.length
那么咱们在其余组件内部使用 getters 也变得十分简单
computed: {
doneTodosCount () {
returnthis.$store.getters.doneTodosCount
mapGetters
能够将 store 的 getters 映射到本地的计算属性中来,除了可使用数组以外,还可使用对象起别名。
...mapGetters([
'doneTodosCount',
'anotherGetter',
能改变 Vuex store 中的 state 状态的惟一方法是提交 mutation 变动。mutation 和事件很像:都有字符串类型的 type 以及 handler 句柄。咱们在 handler 中实际修改 state,state 为每一个 mutation 的第一个参数。
conststore =newVuex.Store({
mutations: {
increment (state) {
// mutate state
state.count++
// call, 只有在使用 type increment 调用 mutation 时才能称为 mit('increment')
commit 的第二个可选参数为 payload 有效载荷,能够为普通类型或对象类型等等。
commit 方法还能够经过对象形式调用,这种状况下,这个对象都会被当成 payload 。
type:'increment',
little tips
建议使用大写命名 Mutation
将全部大写变量存放在一个文件中,须要的时候引入。使用 es6 的计算属性名新特性来使用常量做为方法名。
// mutation-types.js
exportconstSOME_MUTATION ='SOME_MUTATION'
// store.js
importVuexfrom'vuex'
import{ SOME_MUTATION }from'./mutation-types'
conststore =newVuex.Store({
state: { ... },
mutations: {
// we can use the ES2015 computed property name feature
// to use a constant as the function name
[SOME_MUTATION] (state) {
// mutate state
es6 计算属性名
// e.g: 使用含有空格的变量做为属性名会报错,此时能够将它存为字符串或者存在中括号包裹的变量中
varlastName ="last name";
varperson = {
"first name":"Nicholas",
// 中括号包裹的变量
[lastName]: "Zakas"
console.log(person["last name"]);// Zakas
mutations 必须都是同步的,它的改变必须在调用以后当即执行
由于它是惟一能够修改 state 的,若是它使用了异步方法,将会使咱们的 state 变得没法追踪,定位问题也变得是否困难
在组件中 commit mutation 时
可使用 this.$mit() 或者使用 mapMutations 方法,后者能够将组件中的方法映射到 mit 调用(须要在根组件注入 store)。
import{ mapMutations }from'vuex'
exportdefault{
methods: {
// 传入数组
...mapMutations([
'increment'// map this.increment() to this.$mit('increment')
// 传入对象,可使用 alias
...mapMutations({
add:'increment'// map this.add() to this.$mit('increment')
actions 是提交 mutations 的,它能够有任意的异步操做。
actions 的第一个参数是 context,它向外暴露一组与 store 实例相同的方法/属性,因此能够直接调用 mit 或者访问 context.state 或者 context.getters 。咱们一般使用 es6 的参数解构来简化咱们的代码,直接写成
{ commit }
actions: {
increment ({ commit }) {
commit('increment')
如何触发 Actions?
actions 经过
store.dispatch('actionName')
触发,其方法体中再触发 mutation,可是 mutations 是能够直接经过 mit 触发的,那么为何不直接使用 mit(‘mutationName’) 呢?由于,actions 是能够异步执行的,而 mutations 只能够同步。因此这种 dispatch 调用能够在 action 内执行异步操做,也就是说能够执行异步 mutation。
可使用 payload 格式或者对象形式触发。两者等价
// dispatch with a payload
store.dispatch('incrementAsync', {
// dispatch with an object
store.dispatch({
type:'incrementAsync',
shopping cart 中的实际应用,既调用了异步 API,又提交了多个 mutation。
actions: {
checkout ({ commit, state }, payload) {
// save the items currently in the cart
constsavedCartItems = [...state.cart.added]
// send out checkout request, and optimistically
// clear the cart
commit(types.CHECKOUT_REQUEST)
// the 异步 shop API accepts a success callback and a failure callback
shop.buyProducts(
// handle success
() =& commit(types.CHECKOUT_SUCCESS),
// handle failure
() =& commit(types.CHECKOUT_FAILURE, savedCartItems)
在组件中分发 Actions
this.$store.dispatch()
mapActions
映射组件方法到
store.dispatch
中调用(须要注入 root)。同
mapMutations
Actions 组合,怎么控制 actions 执行呢?
因为 actions 是异步的,所以咱们就很难知道一个 action 何时完成,以及该怎么把多个 action 组合起来,处理复杂的异步工做流?
store.dispatch()
方法返回了咱们定义的 action handler 的返回值,因此咱们能够直接返回一个 Promise 呀~
actions: {
actionA ({ commit }) {
returnnewPromise((resolve, reject) =&{
setTimeout(()=&{
commit('someMutation')
能够这么用
store.dispatch('actionA').then(()=&{
而后在另外一个 action 中
actions: {
actionB ({ dispatch, commit }) {
returndispatch('actionA').then(()=&{
commit('someOtherMutation')
因为 Vuex 使用了单状态树,因此随着咱们应用的规模逐渐增大, store 也愈来愈膨胀。为了应对这个问题,Vuex 容许咱们将 store 分红多个 modules。每一个 module 有着本身的 state, mutations, actions, getters, 甚至能够有嵌套( nested )的 modules。好比说:
constmoduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
constmoduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
conststore =newVuex.Store({
modules: {
a: moduleA,
b: moduleB
// 注意,调用的时候,多个模块都在 state 对象中,而非 modules 中
store.state.a // -& moduleA's state
store.state.b // -& moduleB's state
modules 中的各类 state , local or root?
mutations 和 getters 中,接受的第一个参数是 modules 的本地 state
constmoduleA = {
state: {count:0},
mutations: {
increment: (state) {
// state is the local module state
state.count++
getters: {
doubleCount (state) {
returnstate.count *2
类似地,在 actions 中,
context.state
为本地 state,而
context.rootState
为根 state
constmoduleA = {
actions: {
incrementIfOdd ({ state, commit }) {
if(state.count %2===1) {
commit('increment')
getters 的第三个参数才是 root state
constmoduleA = {
getters: {
sumWithRootCount (state, getters, rootState) {
returnstate.count + rootState.count
Strict Mode & Form Handling
严格模式下,若是在 mutation handler 以外修改了 Vuex 的 state,应用就会抛错。好比咱们将 Vuex 中的某个数据,用 Vue 的 v-model 绑定到 input 时,一旦感应到 input 改动,就会尝试去直接修改这个数据,严格模式下就会报错。因此建议是绑定 value 值,而后在 input 时调用 action 。
&input:value="message"@input="updateMessage"&
computed: {
...mapState({
message:state=&state.obj.message
methods: {
updateMessage (e) {
this.$mit('updateMessage', e.target.value)
mutation 能够这么处理
mutations: {
updateMessage (state, message) {
state.obj.message = message
诚然,这样作是很仔细明了的,可是咱们也不能用 v-model 这么好用的方法了,另一个方法就是继续使用 v-model ,并配套使用 双向计算属性和 setter 。
computed: {
message: {
returnthis.$store.state.obj.message
set (value) {
// 直接 commit 到 mutation,type 为 updateMessage
this.$mit('updateMessage', value)
建议部署到开发环境的时候必定必定要关掉严格模式。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅本身可见
正文不许确
标题不许确
排版有问题
主题不许确
没有分页内容
图片没法显示
视频没法显示
与原文不一致如何使用Vuex+Vue.js构建单页应用
做者:懂懂懂懂懂懂懂涛大人
字体:[ ] 类型:转载 时间:
这篇文章主要教你们如何使用Vuex+Vue.js构建单页应用,具备必定的参考价值,感兴趣的小伙伴们能够参考一下
前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和 Vuex 来构建一个简单笔记的单页应用的文章。感受收获挺多,本身在它的例子的基础上进行了一些优化和自定义功能,在这里和你们分享下学习心得。
在这篇教程中咱们将经过构建一个笔记应用来学习如何在咱们的 Vue 项目中使用 Vuex。咱们将大概的过一遍什么是 Vuex.js,在项目中何时使用它,和如何构建咱们的 Vue 应用。
这里放一张咱们项目的预览图片:
项目源码:;有须要的同窗能够直接下载源码查看。
主要知识点
状态管理机制的使用
的基础 api
脚手架的安装及使用
的语法,这里推荐看下阮一峰的入门教程
在咱们火烧眉毛的开始项目以前,咱们最好先花几分钟来了解下 Vuex 的核心概念。
Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构。它借鉴了 Flux 和 Redux 的设计思想,但简化了概念,而且采用了一种为能更好发挥 Vue.js 数据响应机制而专门设计的实现。
state 这样概念初次接触的时候可能会感受到有点模糊,简单来讲就是将 state 当作咱们项目中使用的数据的集合。而后,Vuex 使得 组件本地状态(component local state)和 应用层级状态(application state) 有了必定的差别。
component local state:该状态表示仅仅在组件内部使用的状态,有点相似经过配置选项传入 Vue 组件内部的意思。
application level state:应用层级状态,表示同时被多个组件共享的状态层级。
假设有这样一个场景:咱们有一个父组件,同时包含两个子组件。父组件能够很容易的经过使用 props 属性来向子组件传递数据。
可是问题来了,当咱们的两个子组件如何和对方互相通讯的? 或者子组件如何传递数据给他父组件的?在咱们的项目很小的时候,这个两个问题都不会太难,由于咱们能够经过事件派发和监听来完成父组件和子组件的通讯。
然而,随着咱们项目的增加:
一、保持对全部的事件追踪将变得很困难。到底哪一个事件是哪一个组件派发的,哪一个组件该监听哪一个事件?
二、项目逻辑分散在各个组件当中,很容易致使逻辑的混乱,不利于咱们项目的维护。
三、父组件将变得和子组件耦合愈来愈严重,由于它须要明确的派发和监听子组件的某些事件。
这就是 Vuex 用来解决的问题。 Vuex 的四个核心概念分别是:
The state tree:Vuex 使用单一状态树,用一个对象就包含了所有的应用层级状态。至此它便做为一个『惟一数据源(SSOT)』而存在。这也意味着,每一个应用将仅仅包含一个 store 实例。单状态树让咱们可以直接地定位任一特定的状态片断,在调试的过程当中也能轻易地取得整个当前应用状态的快照。
Getters:用来从 store 获取 Vue 组件数据。
Mutators:事件处理器用来驱动状态的变化。
Actions:能够给组件使用的函数,以此用来驱动事件处理器 mutations
如何你暂时还不太理解这个四个概念,不用着急,咱们将在后面的项目实战中详细的解释。
下面这张图详细的解释了 Vuex 应用中数据的流向(Vuex 官方图)
简单解释下:
Vuex 规定,属于应用层级的状态只能经过 Mutation 中的方法来修改,而派发 Mutation 中的事件只能经过 action。
从左到又,从组件出发,组件中调用 action,在 action 这一层级咱们能够和后台数据交互,好比获取初始化的数据源,或者中间数据的过滤等。而后在 action 中去派发 Mutation。Mutation 去触发状态的改变,状态的改变,将触发视图的更新。
数据流都是单向的
组件可以调用 action
action 用来派发 Mutation
只有 mutation 能够改变状态
store 是响应式的,不管 state 何时更新,组件都将同步更新
这个应用将使用 webpack 来作模块打包,处理和热重启。使用 Vue 官方提供的脚手架 vue-cli。
安装 vue-cli
npm install -g vue-cli
注:Node.js &= 4.x, 5.x 最好
初始化应用
vue init webpack vue-notes-app
cd vue-notes-app
npm install // 安装依赖包
npm run dev // 启动服务
初始化一个项目名为vue-notes-app的应用,并选择使用 webpack 打包方式。在命令行中按照提示选择初始化配置项。其中在选择 JSLint 校验的时候,推荐选择 AirBNB 规范。
使用你最喜欢的编辑器打开咱们刚刚新建的项目,项目的结构大概以下图:
components/ 文件夹用来存放咱们的 Vue 组件
vuex/ 文件夹存放的是和 Vuex store 相关的东西(state object,actions,mutators)
build/ 文件是 webpack 的打包编译配置文件
config/ 文件夹存放的是一些配置项,好比咱们服务器访问的端口配置等
dist/ 该文件夹一开始是不存在,在咱们的项目通过 build 以后才会产出
App.vue 根组件,全部的子组件都将在这里被引用
index.html 整个项目的入口文件,将会引用咱们的根组件 App.vue
main.js 入口文件的 js 逻辑,在 webpack 打包以后将被注入到 index.html 中
新增笔记,新增一篇笔记,编辑区显示空的笔记内容
删除笔记,删除一篇笔记以后,编辑区域显示当前笔记类别的第一项
笔记列表切换,分为所有笔记和收藏笔记两种,在切换以后,编辑区域显示当前列表的第一条笔记
收藏笔记,给当前激活的笔记打上收藏的标签
项目组件划分
在这个项目中,咱们将总共使用四个组件:根组件 App.vue,操做栏组件 Toolbar.vue,别表组件 NotesList.vue,笔记编辑组件 Editor.vue。
建立 Vuex Store
按照上面咱们列出来的功能模块,咱们在 Vuex/ 下面创建一个 store.js 文件。
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
// 须要维护的状态
const state = {
notes: [],
activeNote: {},
const mutations = {
// 初始化 state
INIT_STORE(state, data) {
state.notes = data.notes,
state.show = data.
state.activeNote = data.activeN
// 新增笔记
NEW_NOTE(state) {
var newNote = {
id: +new Date(),
title: '',
content: '',
favorite: false
state.notes.push(newNote);
state.activeNote = newN
// 修改笔记
EDIT_NOTE(state, note) {
state.activeNote =
// 修改原始数据
for (var i = 0; i & state.notes. i++) {
if(state.notes[i].id === note.id){
state.notes[i] =
// 删除笔记
DELETE_NOTE(state) {
state.notes.$remove(state.activeNote);
state.activeNote = state.notes[0] || {};
// 切换笔记的收藏与取消收藏
TOGGLE_FAVORITE(state) {
state.activeNote.favorite = !state.activeNote.
// 切换显示数据列表类型:所有 or 收藏
SET_SHOW_ALL(state, show){
state.show =
// 切换数据展现,须要同步更新 activeNote
if(show === 'favorite'){
state.activeNote = state.notes.filter(note =& note.favorite)[0] || {};
state.activeNote = state.notes[0] || {};
// 设置当前激活的笔记
SET_ACTIVE_NOTE(state, note) {
state.activeNote =
export default new Vuex.Store({
建立 Vuex Actions
在 Vuex/ 下面创建一个 action.js,用来给组件使用的函数。
function makeAction(type) {
return ({ dispatch }, ...args) =& dispatch(type, ...args);
const initNote = {
id: +new Date(),
title: '个人笔记',
content: '第一篇笔记内容',
favorite: false
// 模拟初始化数据
const initData = {
show: 'all',
notes: [initNote],
activeNote: initNote
export const initStore = ({ dispatch }) =& {
dispatch('INIT_STORE', initData);
// 更新当前activeNote对象
export const updateActiveNote = makeAction('SET_ACTIVE_NOTE');
// 添加一个note对象
export const newNote = makeAction('NEW_NOTE');
// 删除一个note对象
export const deleteNote = makeAction('DELETE_NOTE');
export const toggleFavorite = makeAction('TOGGLE_FAVORITE');
export const editNote = makeAction('EDIT_NOTE');
// 更新列表展现
export const updateShow = makeAction('SET_SHOW_ALL');
建立 Vuex Getters
在 vuex/ 下面创建一个 getter.js 文件,用来从 store 获取数据。
// 获取 noteList,这里将会根据 state.show 的状态作数据过滤
export const filteredNotes = (state) =& {
if(state.show === 'all'){
return state.notes || {};
}else if(state.show === 'favorite'){
return state.notes.filter(note =& note.favorite) || {};
// 获取列表展现状态 : all or favorite
export const show = (state) =& {
return state.
// 获取当前激活 note
export const activeNote = (state) =& {
return state.activeN
以上就是咱们 Vuex 的全部逻辑了,在定下了咱们须要完成的功能以后,接下来就是只须要在组件中去调用 action 来实现对应的功能了。
在这里咱们将使用 vue-router 来作路由,引用 bootstrap 样式。
index.html
&!DOCTYPE html&
&meta charset="utf-8"&
&title&vuex-notes-app&/title&
&link rel="stylesheet" href="/bootstrap/3.3.6/css/bootstrap.min.css"&
&div id="app"&&/div&
&!-- built files will be auto injected --&
全部的入口逻辑咱们都将在 main.js 中编写
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import VueResource from 'vue-resource';
// 路由模块和HTTP模块
Vue.use(VueResource);
Vue.use(VueRouter);
const router = new VueRouter();
router.map({
'/index': {
component: App
router.redirect({
'*': '/index'
router.start(App, '#app');
根组件 App.vue
&template&
&div id="app" class="app"&
&toolbar&&/toolbar&
¬es-list&&/notes-list&
&editor&&/editor&
&/template&
html, #app {
height: 100%;
margin: 0;
padding: 0;
border: 0;
height: 100%;
max-height: 100%;
import Toolbar from './components/Toolbar';
import NotesList from './components/NotesList';
import Editor from './components/Editor';
import store from './vuex/store';
import { initStore } from './vuex/actions';
export default {
components: {
NotesList,
actions: {
this.initStore()
在根组件中引用了三个子组件:Toolbar.vue, NotesList.vue, Editor.vue。
注意:咱们在配置里面加入了 vuex 这么一个选项,这里用来将咱们 action 里面定义的方法给暴露出来,咱们在根组件中只作了一件事情,那就是初始化模拟数据,所以咱们在组件生命周期的 ready 阶段调用了 actions 里面的 initStore 来初始化咱们的 store 里面的 state
Toolbar.vue
&template&
&div id="toolbar"&
&i class="glyphicon logo"&&img src="../assets/logo.png" width="30" height="30"&&/i&
&i @click="newNote" class="glyphicon glyphicon-plus"&&/i&
&i @click="toggleFavorite" class="glyphicon glyphicon-star" :class="{starred: activeNote.favorite}"&&/i&
&i @click="deleteNote" class="glyphicon glyphicon-remove"&&/i&
&/template&
import { newNote, deleteNote, toggleFavorite } from '../vuex/actions';
import { activeNote } from '../vuex/getters';
export default {
getters: {
activeNote
actions: {
deleteNote,
toggleFavorite
&style lang="scss" scoped&
height: 100%;
color: #767676;
padding: 35px 25px 25px 25
.starred {
color: #F7AE4F;
font-size: 30
margin-bottom: 35
opacity: 0.8;
transition: opacity 0.5
opacity: 1;
在这里,咱们用到了 Vuex 的一个案例就是咱们须要知道当前的激活的笔记是不是收藏类别的,若是是,咱们须要高亮收藏按钮,那么如何知道呢?那就是经过 vuex 里面的 getters 获取当前激活的笔记对象,判断它的 favorite 是否为 true。
始终牢记一个概念,vuex 中数据是单向的,只能从 store 获取,而咱们这个例子中的 activeNote 也是始终都在 store.js 中维护的,这样子就能够给其余组件公用了
// 须要维护的状态
const state = {
notes: [],
activeNote: {},
NotesList.vue
&template&
&div id="notes-list"&
&div id="list-header"&
&h2&Notes | &/h2&
&div class="btn-group btn-group-justified" role="group"&
&!-- all --&
&div class="btn-group" role="group"&
&button type="button" class="btn btn-default"
@click="toggleShow('all')"
:class="{active: show === 'all'}"&All Notes&/button&
&!-- favorites --&
&div class="btn-group" role="group"&
&button type="button" class="btn btn-default"
@click="toggleShow('favorite')"
:class="{active: show === 'favorite'}"&Favorites&/button&
&!-- 渲染笔记列表 --&
&div class="container"&
&div class="list-group"&
&a v-for="note in filteredNotes"
class="list-group-item" href="#"
:class="{active: activeNote === note}"
@click="updateActiveNote(note)"&
&h4 class="list-group-item-heading"&
{{note.title.trim().substring(0,30)}}
&/template&
import { updateActiveNote, updateShow } from '../vuex/actions';
import { show, filteredNotes, activeNote } from '../vuex/getters';
export default {
getters: {
filteredNotes,
activeNote
actions: {
updateActiveNote,
updateShow
methods: {
toggleShow(show) {
this.updateShow(show);
笔记列表组件,主要有三个操做
切换渲染笔记
点击列表 title,切换 activeNote
咱们经过 getters 中的 filteredNotes 方法获取笔记列表
// 获取 noteList,这里将会根据 state.show 的状态作数据过滤
export const filteredNotes = (state) =& {
if(state.show === 'all'){
return state.notes || {};
}else if(state.show === 'favorite'){
return state.notes.filter(note =& note.favorite) || {};
能够看到,咱们获取的列表是依赖于 state.show 这个状态的。而咱们的切换列表操做刚好就是调用 actions 里面的方法来更新 state.show,这样一来,实现了数据列表的动态刷新,并且咱们对树的操做都是经过调用 actions 的方法来实现的。
咱们再看,在切换列表的时候,咱们还须要动态的更新 activeNote。看看咱们在 store.js 中是如何作的:
// 切换显示数据列表类型:所有 or 收藏
SET_SHOW_ALL(state, show){
state.show =
// 切换数据展现,须要同步更新 activeNote
if(show === 'favorite'){
state.activeNote = state.notes.filter(note =& note.favorite)[0] || {};
state.activeNote = state.notes[0] || {};
触发这些操做的是咱们给两个按钮分别绑定了咱们自定义的函数,经过给函数传入不一样的参数,而后调用 actions 里面的方法,来实现对数据的过滤,更新。
Editor.vue
&template&
&div id="note-editor"&
&div class="form-group"&
&input type="text" name="title"
class="title form-control"
placeholder="请输入标题"
@input="updateNote"
v-model="currentNote.title"&
v-model="currentNote.content" name="content"
class="form-control" row="3" placeholder="请输入正文"
@input="updateNote"&&/textarea&
&/template&
import { editNote } from '../vuex/actions';
import { activeNote } from '../vuex/getters';
export default {
getters: {
activeNote
actions: {
computed: {
// 经过计算属性获得的一个对象,这样子咱们就能愉快的使用 v-model 了
currentNote: activeNote
methods: {
// 为何这么作? 由于在严格模式中不容许直接在模板层面去修改 state 中的值
updateNote() {
this.editNote(this.currentNote);
在 Editor.vue 组件中,咱们须要可以实时的更新当前的 activeNote 组件和列表中对应的咱们正在修改的笔记对象的内容。
因为咱们前面提到过,在组件中是不容许直接修改 store.js在里面的状态值的,因此在这里的时候,咱们经过一个计算属性,将 store 里面的状态值赋值给一个对象,而后在自定义的 updateNotes() 方法中,去调用 action,同时传入 currentNote 对象。
在 store.js 中,咱们是这么作的,找到对应的 id 的对象,从新赋值,由于前面提到过,咱们的数据是响应式的,在这里进行了改变,对应的视图也将刷新改变,这样一来就实现了实时编辑,实时渲染的功能了。
// 修改笔记
EDIT_NOTE(state, note) {
state.activeNote =
// 修改原始数据
for (var i = 0; i & state.notes. i++) {
if(state.notes[i].id === note.id){
state.notes[i] =
在这个项目中,咱们并无引入 vue-resource 插件,只是本身模拟了部分的数据,有兴趣的同窗能够本身去试试。css