Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
ʹÓà Vuex + Vue.js ¹¹½¨µ¥Ò³Ó¦ÓÃ
 
  2449  次浏览      29
 2018-12-11  
 
±à¼­ÍƼö:
±¾ÎÄÀ´×Ôsegmentfault.com£¬ÔÚÕâÆª½Ì³ÌÖÐÎÒÃǽ«Í¨¹ý¹¹½¨Ò»¸ö±Ê¼ÇÓ¦ÓÃÀ´Ñ§Ï°ÈçºÎÔÚÎÒÃÇµÄ Vue ÏîÄ¿ÖÐʹÓà Vuex¡£

ÎÒÃǽ«´ó¸ÅµÄ¹ýÒ»±éʲôÊÇ Vuex.js£¬ÔÚÏîÄ¿ÖÐʲôʱºòʹÓÃËü£¬ºÍÈçºÎ¹¹½¨ÎÒÃÇµÄ Vue Ó¦Óá£

ÕâÀï·ÅÒ»ÕÅÎÒÃÇÏîÄ¿µÄÔ¤ÀÀͼƬ£º

ÏîĿԴÂ룺vuex-notes-app£»ÓÐÐèÒªµÄͬѧ¿ÉÒÔÖ±½ÓÏÂÔØÔ´Âë²é¿´¡£

Ö÷Ҫ֪ʶµã

Vuex ״̬¹ÜÀí»úÖÆµÄʹÓÃ

Vue.js µÄ»ù´¡ api

Vue-cli ½ÅÊּܵݲװ¼°Ê¹ÓÃ

vur-router µÄʹÓÃ

ES6 µÄÓï·¨£¬ÕâÀïÍÆ¼ö¿´ÏÂÈîÒ»·åµÄÈëÃŽ̳Ì

Vuex ¸ÅÊö

ÔÚÎÒÃÇÆÈ²»¼°´ýµÄ¿ªÊ¼ÏîĿ֮ǰ£¬ÎÒÃÇ×îºÃÏÈ»¨¼¸·ÖÖÓÀ´Á˽âÏ Vuex µÄºËÐĸÅÄî¡£

Vuex ÊÇÒ»¸öרÃÅΪ Vue.js Ó¦ÓÃËùÉè¼ÆµÄ¼¯ÖÐʽ״̬¹ÜÀí¼Ü¹¹¡£Ëü½è¼øÁË Flux ºÍ Redux µÄÉè¼ÆË¼Ï룬µ«¼ò»¯Á˸ÅÄ²¢ÇÒ²ÉÓÃÁËÒ»ÖÖΪÄܸüºÃ·¢»Ó Vue.js Êý¾ÝÏìÓ¦»úÖÆ¶ø×¨ÃÅÉè¼ÆµÄʵÏÖ¡£

state ÕâÑù¸ÅÄî³õ´Î½Ó´¥µÄʱºò¿ÉÄÜ»á¸Ð¾õµ½ÓеãÄ£ºý£¬¼òµ¥À´Ëµ¾ÍÊǽ« state ¿´³ÉÎÒÃÇÏîÄ¿ÖÐʹÓõÄÊý¾ÝµÄ¼¯ºÏ¡£È»ºó£¬Vuex ʹµÃ ×é¼þ±¾µØ×´Ì¬£¨component local state£©ºÍ Ó¦Óò㼶״̬(application state) ÓÐÁËÒ»¶¨µÄ²îÒì

component local state: ¸Ã״̬±íʾ½ö½öÔÚ×é¼þÄÚ²¿Ê¹ÓõÄ״̬£¬ÓеãÀàËÆÍ¨¹ýÅäÖÃÑ¡Ïî´«Èë Vue ×é¼þÄÚ²¿µÄÒâ˼¡£

application level state: Ó¦Óò㼶״̬£¬±íʾͬʱ±»¶à¸ö×é¼þ¹²ÏíµÄ״̬²ã¼¶¡£

¼ÙÉèÓÐÕâÑùÒ»¸ö³¡¾°£ºÎÒÃÇÓÐÒ»¸ö¸¸×é¼þ£¬Í¬Ê±°üº¬Á½¸ö×Ó×é¼þ¡£¸¸×é¼þ¿ÉÒÔºÜÈÝÒ×µÄͨ¹ýʹÓà props ÊôÐÔÀ´Ïò×Ó×é¼þ´«µÝÊý¾Ý¡£

µ«ÊÇÎÊÌâÀ´ÁË£¬µ±ÎÒÃǵÄÁ½¸ö×Ó×é¼þÈçºÎºÍ¶Ô·½»¥ÏàͨÐŵģ¿ »òÕß×Ó×é¼þÈçºÎ´«µÝÊý¾Ý¸øËû¸¸×é¼þµÄ£¿ÔÚÎÒÃǵÄÏîÄ¿ºÜСµÄʱºò£¬Õâ¸öÁ½¸öÎÊÌâ¶¼²»»áÌ«ÄÑ£¬ÒòΪÎÒÃÇ¿ÉÒÔͨ¹ýʼþÅÉ·¢ºÍ¼àÌýÀ´Íê³É¸¸×é¼þºÍ×Ó×é¼þµÄͨÐÅ¡£

È»¶ø£¬Ëæ×ÅÎÒÃÇÏîÄ¿µÄÔö³¤£º

±£³Ö¶ÔËùÓеÄʼþ×·×Ù½«±äµÃºÜÀ§ÄÑ¡£µ½µ×ÄĸöʼþÊÇÄĸö×é¼þÅÉ·¢µÄ£¬Äĸö×é¼þ¸Ã¼àÌýÄĸöʼþ£¿

ÏîÄ¿Âß¼­·ÖÉ¢ÔÚ¸÷¸ö×é¼þµ±ÖУ¬ºÜÈÝÒ×µ¼ÖÂÂß¼­µÄ»ìÂÒ£¬²»ÀûÓÚÎÒÃÇÏîÄ¿µÄά»¤¡£

¸¸×é¼þ½«±äµÃºÍ×Ó×é¼þñîºÏÔ½À´Ô½ÑÏÖØ£¬ÒòΪËüÐèÒªÃ÷È·µÄÅÉ·¢ºÍ¼àÌý×Ó×é¼þµÄijЩʼþ¡£

Õâ¾ÍÊÇ 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/ ¸ÃÎļþ¼ÐÒ»¿ªÊ¼ÊDz»´æÔÚ£¬ÔÚÎÒÃǵÄÏîÄ¿¾­¹ý 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 Îļþ

rt Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

// ÐèҪά»¤µÄ״̬
const state = {
notes: [],
activeNote: {},
show: ''
};

const mutations = {
// ³õʼ»¯ state
INIT_STORE(state, data) {
state.notes = data.notes,
state.show = data.show;
state.activeNote = data.activeNote;
},
// ÐÂÔö±Ê¼Ç
NEW_NOTE(state) {
var newNote = {
id: +new Date(),
title: '',
content: '',
favorite: false
};
state.notes.push(newNote);
state.activeNote = newNote;
},
// Ð޸ıʼÇ
EDIT_NOTE(state, note) {
state.activeNote = note;
// ÐÞ¸ÄԭʼÊý¾Ý
for (var i = 0; i < state.notes.length; i++) {
if(state.notes[i].id === note.id){
state.notes[i] = note;
break;
}
};
},
// ɾ³ý±Ê¼Ç
DELETE_NOTE(state) {
state.notes.$remove(state.activeNote);
state.activeNote = state.notes[0] || {};
},
// Çл»±Ê¼ÇµÄÊÕ²ØÓëÈ¡ÏûÊÕ²Ø
TOGGLE_FAVORITE(state) {
state.activeNote.favorite = !state.activeNote.favorite;
},
// Çл»ÏÔʾÊý¾ÝÁбíÀàÐÍ£ºÈ«²¿ or ÊÕ²Ø
SET_SHOW_ALL(state, show){
state.show = show;
// Çл»Êý¾Ýչʾ£¬ÐèҪͬ²½¸üРactiveNote
if(show === 'favorite'){
state.activeNote = state.notes.filter(note => note.favorite)[0] || {};
}else{
state.activeNote = state.notes[0] || {};
}
},
// ÉèÖõ±Ç°¼¤»îµÄ±Ê¼Ç
SET_ACTIVE_NOTE(state, note) {
state.activeNote = note;
}
};

export default new Vuex.Store({
state,
mutations
});

´´½¨ Vuex Actions

ÔÚ Vuex/ ÏÂÃæ½¨Á¢Ò»¸ö action.js£¬ÓÃÀ´¸ø×é¼þʹÓõĺ¯Êý

eAction(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.show;
};

// »ñÈ¡µ±Ç°¼¤»î note
export const activeNote = (state) => {
return state.activeNote;
};

 

ÒÔÉϾÍÊÇÎÒÃÇ Vuex µÄËùÓÐÂß¼­ÁË£¬ÔÚ¶¨ÏÂÁËÎÒÃÇÐèÒªÍê³ÉµÄ¹¦ÄÜÖ®ºó£¬½ÓÏÂÀ´¾ÍÊÇÖ»ÐèÒªÔÚ×é¼þÖÐÈ¥µ÷Óà action À´ÊµÏÖ¶ÔÓ¦µÄ¹¦ÄÜÁË¡£

·ÓÉÅäÖÃ

ÔÚÕâÀïÎÒÃǽ«Ê¹Óà vue-router À´×ö·ÓÉ£¬ÒýÓà bootstrap Ñùʽ¡£

index.html

<html>
<head>
<meta charset="utf-8">
<title>vuex-notes-app</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

 

ËùÓеÄÈë¿ÚÂß¼­ÎÒÃǶ¼½«ÔÚ main.js Öбàд

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>
<notes-list></notes-list>
<editor></editor>
</div>
</template>

<style>
html, #app {
height: 100%;
}

body {
margin: 0;
padding: 0;
border: 0;
height: 100%;
max-height: 100%;
position: relative;
}
</style>

<script>

 

ÔÚ¸ù×é¼þÖÐÒýÓÃÁËÈý¸ö×Ó×é¼þ£ºToolbar.vue, NotesList.vue, Editor.vue¡£

×¢Ò⣺ÎÒÃÇÔÚÅäÖÃÀïÃæ¼ÓÈëÁË vuex Õâôһ¸öÑ¡ÏÕâÀïÓÃÀ´½«ÎÒÃÇ action ÀïÃæ¶¨ÒåµÄ·½·¨¸ø±©Â¶³öÀ´£¬ÎÒÃÇÔÚ¸ù×é¼þÖÐÖ»×öÁËÒ»¼þÊÂÇ飬ÄǾÍÊdzõʼ»¯Ä£ÄâÊý¾Ý£¬Òò´ËÎÒÃÇÔÚ×é¼þÉúÃüÖÜÆÚµÄ 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>
</div>
</template>

<script>
import { newNote, deleteNote, toggleFavorite } from '../vuex/actions';
import { activeNote } from '../vuex/getters';

export default {
vuex: {
getters: {
activeNote
},
actions: {
newNote,
deleteNote,
toggleFavorite
}
}
}
</script>

<style lang="scss" scoped>
#toolbar{
float: left;
width: 80px;
height: 100%;
background-color: #30414D;
color: #767676;
padding: 35px 25px 25px 25px;

.starred {
color: #F7AE4F;
}

i{
font-size: 30px;
margin-bottom: 35px;
cursor: pointer;
opacity: 0.8;
transition: opacity 0.5s ease;

&:hover{
opacity: 1;
}
}
}
</style>

 

ÔÚÕâÀÎÒÃÇÓõ½ÁË Vuex µÄÒ»¸ö°¸Àý¾ÍÊÇÎÒÃÇÐèÒªÖªµÀµ±Ç°µÄ¼¤»îµÄ±Ê¼ÇÊÇ·ñÊÇÊÕ²ØÀà±ðµÄ£¬Èç¹ûÊÇ£¬ÎÒÃÇÐèÒª¸ßÁÁÊղذ´Å¥£¬ÄÇôÈçºÎÖªµÀÄØ£¿ÄǾÍÊÇͨ¹ý vuex ÀïÃæµÄ getters »ñÈ¡µ±Ç°¼¤»îµÄ±Ê¼Ç¶ÔÏó£¬ÅжÏËüµÄ favorite ÊÇ·ñΪ true¡£

ʼÖÕÀμÇÒ»¸ö¸ÅÄvuex ÖÐÊý¾ÝÊǵ¥ÏòµÄ£¬Ö»ÄÜ´Ó store »ñÈ¡£¬¶øÎÒÃÇÕâ¸öÀý×ÓÖÐµÄ activeNote Ò²ÊÇʼÖÕ¶¼ÔÚ store.js ÖÐά»¤µÄ£¬ÕâÑù×ӾͿÉÒÔ¸øÆäËû×é¼þ¹«ÓÃÁË

// ÐèҪά»¤µÄ״̬
const state = {
notes: [],
activeNote: {},
show: ''
};

NotesList.vue

<template>
<div id="notes-list">
<div id="list-header">
<h2>Notes | heavenru.com</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>
</div>

<!-- favorites -->
<div class="btn-group" role="group">
<button type="button" class="btn btn-default"
@click="toggleShow('favorite')"
:class="{active: show === 'favorite'}">Favorites</button>
</div>
</div>
</div>

<!-- äÖȾ±Ê¼ÇÁбí -->
<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)}}
</h4>
</a>
</div>
</div>
</div>
</template>

<script>
import { updateActiveNote, updateShow } from '../vuex/actions';
import { show, filteredNotes, activeNote } from '../vuex/getters';

export default {
vuex: {
getters: {
show,
filteredNotes,
activeNote
},
actions: {
updateActiveNote,
updateShow
}
},
methods: {
toggleShow(show) {
this.updateShow(show);
}
}
}
</script>

 

±Ê¼ÇÁбí×é¼þ£¬Ö÷ÒªÓÐÈý¸ö²Ù×÷

äÖȾ±Ê¼Ç

Çл»äÖȾ±Ê¼Ç

µã»÷Áбí 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 = show;
// Çл»Êý¾Ýչʾ£¬ÐèҪͬ²½¸üРactiveNote
if(show === 'favorite'){
state.activeNote = state.notes.filter(note => note.favorite)[0] || {};
}else{
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">
<textarea
v-model="currentNote.content" name="content"
class="form-control" row="3" placeholder="ÇëÊäÈëÕýÎÄ"
@input="updateNote"></textarea>
</div>
</div>
</template>

<script>
import { editNote } from '../vuex/actions';
import { activeNote } from '../vuex/getters';

export default {
vuex: {
getters: {
activeNote
},
actions: {
editNote
}
},
computed: {
// ͨ¹ý¼ÆËãÊôÐԵõ½µÄÒ»¸ö¶ÔÏó£¬ÕâÑù×ÓÎÒÃǾÍÄÜÓä¿ìµÄʹÓà v-model ÁË
currentNote: activeNote
},
methods: {
// ΪʲôÕâô×ö£¿ ÒòΪÔÚÑϸñģʽÖв»ÔÊÐíÖ±½ÓÔÚÄ£°å²ãÃæÈ¥ÐÞ¸Ä state ÖеÄÖµ
updateNote() {
this.editNote(this.currentNote);
}
}
}
</script>

 

ÔÚ Editor.vue ×é¼þÖУ¬ÎÒÃÇÐèÒªÄܹ»ÊµÊ±µÄ¸üе±Ç°µÄ activeNote ×é¼þºÍÁбíÖжÔÓ¦µÄÎÒÃÇÕýÔÚÐ޸ĵıʼǶÔÏóµÄÄÚÈÝ¡£

ÓÉÓÚÎÒÃÇÇ°ÃæÌáµ½¹ý£¬ÔÚ×é¼þÖÐÊDz»ÔÊÐíÖ±½ÓÐÞ¸Ä store.jsÔÚÀïÃæµÄ״ֵ̬µÄ£¬ËùÒÔÔÚÕâÀïµÄʱºò£¬ÎÒÃÇͨ¹ýÒ»¸ö¼ÆËãÊôÐÔ£¬½« store ÀïÃæµÄ״ֵ̬¸³Öµ¸øÒ»¸ö¶ÔÏó£¬È»ºóÔÚ×Ô¶¨ÒåµÄ updateNotes() ·½·¨ÖУ¬È¥µ÷Óà action,ͬʱ´«Èë currentNote ¶ÔÏó¡£

ÔÚ store.js ÖУ¬ÎÒÃÇÊÇÕâô×öµÄ£¬ÕÒµ½¶ÔÓ¦µÄ id µÄ¶ÔÏó£¬ÖØÐ¸³Öµ£¬ÒòÎªÇ°ÃæÌáµ½¹ý£¬ÎÒÃǵÄÊý¾ÝÊÇÏìӦʽµÄ£¬ÔÚÕâÀï½øÐÐÁ˸ı䣬¶ÔÓ¦µÄÊÓͼҲ½«Ë¢Ð¸ı䣬ÕâÑùÒ»À´¾ÍʵÏÖÁËʵʱ±à¼­£¬ÊµÊ±äÖȾµÄ¹¦ÄÜÁË¡£

// Ð޸ıʼÇ
EDIT_NOTE(state, note) {
state.activeNote = note;
// ÐÞ¸ÄԭʼÊý¾Ý
for (var i = 0; i < state.notes.length; i++) {
if(state.notes[i].id === note.id){
state.notes[i] = note;
break;
}
};
},

Q&A

ÔÚÕâ¸öÏîÄ¿ÖУ¬ÎÒÃDz¢Ã»ÓÐÒýÈë vue-resource ²å¼þ£¬Ö»ÊÇ×Ô¼ºÄ£ÄâÁ˲¿·ÖµÄÊý¾Ý£¬ÓÐÐËȤµÄͬѧ¿ÉÒÔ×Ô¼ºÈ¥ÊÔÊÔ¡£

ÓÉÓÚÎÒÃǵÄÀý×ÓÏà¶Ô¼òµ¥£¬Ã»ÓÐÉæ¼°µ½ºÜÉîÈëµÄ¶«Î÷£¬¸üÉî²ã´ÎµÄÑо¿ÐèÒª´ó¼Ò»¨¸ü¶àµÄʱ¼äȥʵ¼ùÁË¡£

×îºó£¬ÔÙ˵һ¾ä£¬ÔÚ action ÀïÃæ£¬ÎÒÃÇÆäʵ¿ÉÒÔ×öµÄ»¹Óиü¶à£¬±ÈÈç¸ù¾Ý id ¶¯Ì¬µÄÒì²½»ñÈ¡±Ê¼ÇÄÚÈݵȵȣ¬ÕâЩÓÐÐËȤµÄͬѧ¿ÉÒÔ×Ô¼ºÈ¥³¢ÊÔ£¬Ò»µãµãµÄ·á¸»Õâ¸öÀý×Ó¡£

   
2449 ´Îä¯ÀÀ       29
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì