如何使用Vuex+Vue.js构建单页应用

2024-11-24 18:24:37
推荐回答(1个)
回答1:

按照上面我们列出来的功能模块,我们在 Vuex/ 下面建立一个 store.js 文件
import 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,用来给组件使用的函数
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.show;
};

// 获取当前激活 note
export const activeNote = (state) => {
return state.activeNote;
};

以上就是我们 Vuex 的所有逻辑了,在定下了我们需要完成的功能之后,接下来就是只需要在组件中去调用 action 来实现对应的功能了。
路由配置
在这里我们将使用 vue-router 来做路由,引用 bootstrap 样式。
index.html




vuex-notes-app








所有的入口逻辑我们都将在 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






在根组件中引用了三个子组件:Toolbar.vue, NotesList.vue, Editor.vue。
注意:我们在配置里面加入了 vuex 这么一个选项,这里用来将我们 action 里面定义的方法给暴露出来,我们在根组件中只做了一件事情,那就是初始化模拟数据,因此我们在组件生命周期的 ready 阶段调用了 actions 里面的 initStore 来初始化我们的 store 里面的 state
Toolbar.vue






在这里,我们用到了 Vuex 的一个案例就是我们需要知道当前的激活的笔记是否是收藏类别的,如果是,我们需要高亮收藏按钮,那么如何知道呢?那就是通过 vuex 里面的 getters 获取当前激活的笔记对象,判断它的 favorite 是否为 true。
始终牢记一个概念,vuex 中数据是单向的,只能从 store 获取,而我们这个例子中的 activeNote 也是始终都在 store.js 中维护的,这样子就可以给其他组件公用了
// 需要维护的状态
const state = {
notes: [],
activeNote: {},
show: ''
};

NotesList.vue




笔记列表组件,主要有三个操作
渲染笔记
切换渲染笔记
点击列表 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




在 Editor.vue 组件中,我们需要能够实时的更新当前的 activeNote 组件和列表中对应的我们正在修改的笔记对象的内容。
由于我们前面提到过,在组件中是不允许直接修改 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;
}
};
},