背景:小型應用裏的每一個組件維護着自有的狀態,即當前應用的狀態的一部分,因此整個應用的狀態被分散在了各個角落,可是咱們常常遇到要把
狀態的一部分
共享給多個組件的狀況。
狀態其實能夠形象地想成咱們的 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