成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用

UsherChen / 474人閱讀

摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國外一篇講述了如何使用和來構(gòu)建一個(gè)簡單筆記的單頁應(yīng)用的文章。

鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】

-------------------- 華麗的分割線 --------------------

原文地址:https://coligo.io/learn-vuex-by-building-notes-app/

前言:在最近學(xué)習(xí) Vue.js 的時(shí)候,看到國外一篇講述了如何使用 Vue.js 和 Vuex 來構(gòu)建一個(gè)簡單筆記的單頁應(yīng)用的文章。感覺收獲挺多,自己在它的例子的基礎(chǔ)上進(jìn)行了一些優(yōu)化和自定義功能,在這里和大家分享下學(xué)習(xí)心得。

在這篇教程中我們將通過構(gòu)建一個(gè)筆記應(yīng)用來學(xué)習(xí)如何在我們的 Vue 項(xiàng)目中使用 Vuex。我們將大概的過一遍什么是 Vuex.js,在項(xiàng)目中什么時(shí)候使用它,和如何構(gòu)建我們的 Vue 應(yīng)用。

這里放一張我們項(xiàng)目的預(yù)覽圖片:

項(xiàng)目源碼:vuex-notes-app;有需要的同學(xué)可以直接下載源碼查看。

主要知識點(diǎn)

Vuex 狀態(tài)管理機(jī)制的使用

Vue.js 的基礎(chǔ) api

Vue-cli 腳手架的安裝及使用

vur-router 的使用

ES6 的語法,這里推薦看下阮一峰的入門教程

Vuex 概述

在我們迫不及待的開始項(xiàng)目之前,我們最好先花幾分鐘來了解下 Vuex 的核心概念。

Vuex 是一個(gè)專門為 Vue.js 應(yīng)用所設(shè)計(jì)的集中式狀態(tài)管理架構(gòu)。它借鑒了 Flux 和 Redux 的設(shè)計(jì)思想,但簡化了概念,并且采用了一種為能更好發(fā)揮 Vue.js 數(shù)據(jù)響應(yīng)機(jī)制而專門設(shè)計(jì)的實(shí)現(xiàn)。

state 這樣概念初次接觸的時(shí)候可能會感覺到有點(diǎn)模糊,簡單來說就是將 state 看成我們項(xiàng)目中使用的數(shù)據(jù)的集合。然后,Vuex 使得 組件本地狀態(tài)(component local state)和 應(yīng)用層級狀態(tài)(application state) 有了一定的差異。

component local state:該狀態(tài)表示僅僅在組件內(nèi)部使用的狀態(tài),有點(diǎn)類似通過配置選項(xiàng)傳入 Vue 組件內(nèi)部的意思。

application level state:應(yīng)用層級狀態(tài),表示同時(shí)被多個(gè)組件共享的狀態(tài)層級。

假設(shè)有這樣一個(gè)場景:我們有一個(gè)父組件,同時(shí)包含兩個(gè)子組件。父組件可以很容易的通過使用 props 屬性來向子組件傳遞數(shù)據(jù)。

但是問題來了,當(dāng)我們的兩個(gè)子組件如何和對方互相通信的? 或者子組件如何傳遞數(shù)據(jù)給他父組件的?在我們的項(xiàng)目很小的時(shí)候,這個(gè)兩個(gè)問題都不會太難,因?yàn)槲覀兛梢酝ㄟ^事件派發(fā)和監(jiān)聽來完成父組件和子組件的通信。

然而,隨著我們項(xiàng)目的增長:

保持對所有的事件追蹤將變得很困難。到底哪個(gè)事件是哪個(gè)組件派發(fā)的,哪個(gè)組件該監(jiān)聽哪個(gè)事件?

項(xiàng)目邏輯分散在各個(gè)組件當(dāng)中,很容易導(dǎo)致邏輯的混亂,不利于我們項(xiàng)目的維護(hù)。

父組件將變得和子組件耦合越來越嚴(yán)重,因?yàn)樗枰鞔_的派發(fā)和監(jiān)聽子組件的某些事件。

這就是 Vuex 用來解決的問題。 Vuex 的四個(gè)核心概念分別是:

The state tree:Vuex 使用單一狀態(tài)樹,用一個(gè)對象就包含了全部的應(yīng)用層級狀態(tài)。至此它便作為一個(gè)『唯一數(shù)據(jù)源(SSOT)』而存在。這也意味著,每個(gè)應(yīng)用將僅僅包含一個(gè) store 實(shí)例。單狀態(tài)樹讓我們能夠直接地定位任一特定的狀態(tài)片段,在調(diào)試的過程中也能輕易地取得整個(gè)當(dāng)前應(yīng)用狀態(tài)的快照。

Getters:用來從 store 獲取 Vue 組件數(shù)據(jù)。

Mutators:事件處理器用來驅(qū)動(dòng)狀態(tài)的變化。

Actions:可以給組件使用的函數(shù),以此用來驅(qū)動(dòng)事件處理器 mutations

如何你暫時(shí)還不太理解這個(gè)四個(gè)概念,不用著急,我們將在后面的項(xiàng)目實(shí)戰(zhàn)中詳細(xì)的解釋。

下面這張圖詳細(xì)的解釋了 Vuex 應(yīng)用中數(shù)據(jù)的流向(Vuex 官方圖)

簡單解釋下:

Vuex 規(guī)定,屬于應(yīng)用層級的狀態(tài)只能通過 Mutation 中的方法來修改,而派發(fā) Mutation 中的事件只能通過 action。

從左到又,從組件出發(fā),組件中調(diào)用 action,在 action 這一層級我們可以和后臺數(shù)據(jù)交互,比如獲取初始化的數(shù)據(jù)源,或者中間數(shù)據(jù)的過濾等。然后在 action 中去派發(fā) Mutation。Mutation 去觸發(fā)狀態(tài)的改變,狀態(tài)的改變,將觸發(fā)視圖的更新。

注意事項(xiàng)

數(shù)據(jù)流都是單向的

組件能夠調(diào)用 action

action 用來派發(fā) Mutation

只有 mutation 可以改變狀態(tài)

store 是響應(yīng)式的,無論 state 什么時(shí)候更新,組件都將同步更新

環(huán)境安裝

這個(gè)應(yīng)用將使用 webpack 來做模塊打包,處理和熱重啟。使用 Vue 官方提供的腳手架 vue-cli。

安裝 vue-cli
npm install -g vue-cli

注:Node.js >= 4.x, 5.x 最好

初始化應(yīng)用
vue init webpack vue-notes-app
cd vue-notes-app
npm install // 安裝依賴包
npm run dev // 啟動(dòng)服務(wù)

初始化一個(gè)項(xiàng)目名為vue-notes-app的應(yīng)用,并選擇使用 webpack 打包方式。在命令行中按照提示選擇初始化配置項(xiàng)。其中在選擇 JSLint 校驗(yàn)的時(shí)候,推薦選擇 AirBNB 規(guī)范。

使用你最喜歡的編輯器打開我們剛剛新建的項(xiàng)目,項(xiàng)目的結(jié)構(gòu)大概如下圖:

components/ 文件夾用來存放我們的 Vue 組件

vuex/ 文件夾存放的是和 Vuex store 相關(guān)的東西(state object,actions,mutators)

build/ 文件是 webpack 的打包編譯配置文件

config/ 文件夾存放的是一些配置項(xiàng),比如我們服務(wù)器訪問的端口配置等

dist/ 該文件夾一開始是不存在,在我們的項(xiàng)目經(jīng)過 build 之后才會產(chǎn)出

App.vue 根組件,所有的子組件都將在這里被引用

index.html 整個(gè)項(xiàng)目的入口文件,將會引用我們的根組件 App.vue

main.js 入口文件的 js 邏輯,在 webpack 打包之后將被注入到 index.html 中

功能模塊

新增筆記,新增一篇筆記,編輯區(qū)顯示空的筆記內(nèi)容

刪除筆記,刪除一篇筆記之后,編輯區(qū)域顯示當(dāng)前筆記類別的第一項(xiàng)

筆記列表切換,分為全部筆記和收藏筆記兩種,在切換之后,編輯區(qū)域顯示當(dāng)前列表的第一條筆記

收藏筆記,給當(dāng)前激活的筆記打上收藏的標(biāo)簽

項(xiàng)目組件劃分

在這個(gè)項(xiàng)目中,我們將總共使用四個(gè)組件:根組件 App.vue,操作欄組件 Toolbar.vue,別表組件 NotesList.vue,筆記編輯組件 Editor.vue。

創(chuàng)建 Vuex Store

按照上面我們列出來的功能模塊,我們在 Vuex/ 下面建立一個(gè) store.js 文件。

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

// 需要維護(hù)的狀態(tài)
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;
    // 修改原始數(shù)據(jù)
    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;
  },
  // 切換顯示數(shù)據(jù)列表類型:全部 or 收藏
  SET_SHOW_ALL(state, show){
    state.show = show;
    // 切換數(shù)據(jù)展示,需要同步更新 activeNote
    if(show === "favorite"){
      state.activeNote = state.notes.filter(note => note.favorite)[0] || {};
    }else{
      state.activeNote = state.notes[0] || {};
    }
  },
  // 設(shè)置當(dāng)前激活的筆記
  SET_ACTIVE_NOTE(state, note) {
    state.activeNote = note;
  }
};

export default new Vuex.Store({
  state,
  mutations
});
創(chuàng)建 Vuex Actions

在 Vuex/ 下面建立一個(gè) action.js,用來給組件使用的函數(shù)。

function makeAction(type) {
  return ({ dispatch }, ...args) => dispatch(type, ...args);
};

const initNote = {
  id: +new Date(),
  title: "我的筆記",
  content: "第一篇筆記內(nèi)容",
  favorite: false
};

// 模擬初始化數(shù)據(jù)
const initData = {
  show: "all",
  notes: [initNote],
  activeNote: initNote
};

export const initStore = ({ dispatch }) => {
  dispatch("INIT_STORE", initData);
};
// 更新當(dāng)前activeNote對象
export const updateActiveNote = makeAction("SET_ACTIVE_NOTE");

// 添加一個(gè)note對象
export const newNote = makeAction("NEW_NOTE");

// 刪除一個(gè)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");
創(chuàng)建 Vuex Getters

在 vuex/ 下面建立一個(gè) getter.js 文件,用來從 store 獲取數(shù)據(jù)。

// 獲取 noteList,這里將會根據(jù) state.show 的狀態(tài)做數(shù)據(jù)過濾
export const filteredNotes = (state) => {
  if(state.show === "all"){
    return state.notes || {};
  }else if(state.show === "favorite"){
    return state.notes.filter(note => note.favorite) || {};
  }
};


// 獲取列表展示狀態(tài) : all or favorite
export const show = (state) => {
  return state.show;
};

// 獲取當(dāng)前激活 note
export const activeNote = (state) => {
  return state.activeNote;
};

以上就是我們 Vuex 的所有邏輯了,在定下了我們需要完成的功能之后,接下來就是只需要在組件中去調(diào)用 action 來實(shí)現(xiàn)對應(yīng)的功能了。

路由配置

在這里我們將使用 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





在根組件中引用了三個(gè)子組件:Toolbar.vue, NotesList.vue, Editor.vue。

注意:我們在配置里面加入了 vuex 這么一個(gè)選項(xiàng),這里用來將我們 action 里面定義的方法給暴露出來,我們在根組件中只做了一件事情,那就是初始化模擬數(shù)據(jù),因此我們在組件生命周期的 ready 階段調(diào)用了 actions 里面的 initStore 來初始化我們的 store 里面的 state

Toolbar.vue




在這里,我們用到了 Vuex 的一個(gè)案例就是我們需要知道當(dāng)前的激活的筆記是否是收藏類別的,如果是,我們需要高亮收藏按鈕,那么如何知道呢?那就是通過 vuex 里面的 getters 獲取當(dāng)前激活的筆記對象,判斷它的 favorite 是否為 true。

始終牢記一個(gè)概念,vuex 中數(shù)據(jù)是單向的,只能從 store 獲取,而我們這個(gè)例子中的 activeNote 也是始終都在 store.js 中維護(hù)的,這樣子就可以給其他組件公用了

// 需要維護(hù)的狀態(tài)
const state = {
  notes: [],
  activeNote: {},
  show: ""
};
NotesList.vue


筆記列表組件,主要有三個(gè)操作

渲染筆記

切換渲染筆記

點(diǎn)擊列表 title,切換 activeNote

我們通過 getters 中的 filteredNotes 方法獲取筆記列表

// 獲取 noteList,這里將會根據(jù) state.show 的狀態(tài)做數(shù)據(jù)過濾
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 這個(gè)狀態(tài)的。而我們的切換列表操作恰好就是調(diào)用 actions 里面的方法來更新 state.show,這樣一來,實(shí)現(xiàn)了數(shù)據(jù)列表的動(dòng)態(tài)刷新,而且我們對樹的操作都是通過調(diào)用 actions 的方法來實(shí)現(xiàn)的。

我們再看,在切換列表的時(shí)候,我們還需要?jiǎng)討B(tài)的更新 activeNote??纯次覀冊?store.js 中是如何做的:

// 切換顯示數(shù)據(jù)列表類型:全部 or 收藏
SET_SHOW_ALL(state, show){
  state.show = show;
  // 切換數(shù)據(jù)展示,需要同步更新 activeNote
  if(show === "favorite"){
    state.activeNote = state.notes.filter(note => note.favorite)[0] || {};
  }else{
    state.activeNote = state.notes[0] || {};
  }
}

觸發(fā)這些操作的是我們給兩個(gè)按鈕分別綁定了我們自定義的函數(shù),通過給函數(shù)傳入不同的參數(shù),然后調(diào)用 actions 里面的方法,來實(shí)現(xiàn)對數(shù)據(jù)的過濾,更新。

Editor.vue


在 Editor.vue 組件中,我們需要能夠?qū)崟r(shí)的更新當(dāng)前的 activeNote 組件和列表中對應(yīng)的我們正在修改的筆記對象的內(nèi)容。

由于我們前面提到過,在組件中是不允許直接修改 store.js在里面的狀態(tài)值的,所以在這里的時(shí)候,我們通過一個(gè)計(jì)算屬性,將 store 里面的狀態(tài)值賦值給一個(gè)對象,然后在自定義的 updateNotes() 方法中,去調(diào)用 action,同時(shí)傳入 currentNote 對象。

在 store.js 中,我們是這么做的,找到對應(yīng)的 id 的對象,重新賦值,因?yàn)榍懊嫣岬竭^,我們的數(shù)據(jù)是響應(yīng)式的,在這里進(jìn)行了改變,對應(yīng)的視圖也將刷新改變,這樣一來就實(shí)現(xiàn)了實(shí)時(shí)編輯,實(shí)時(shí)渲染的功能了。

// 修改筆記
EDIT_NOTE(state, note) {
  state.activeNote = note;
  // 修改原始數(shù)據(jù)
  for (var i = 0; i < state.notes.length; i++) {
    if(state.notes[i].id === note.id){
      state.notes[i] = note;
      break;
    }
  };
},
Q&A

在這個(gè)項(xiàng)目中,我們并沒有引入 vue-resource 插件,只是自己模擬了部分的數(shù)據(jù),有興趣的同學(xué)可以自己去試試。

由于我們的例子相對簡單,沒有涉及到很深入的東西,更深層次的研究需要大家花更多的時(shí)間去實(shí)踐了。

最后,再說一句,在 action 里面,我們其實(shí)可以做的還有更多,比如根據(jù) id 動(dòng)態(tài)的異步獲取筆記內(nèi)容等等,這些有興趣的同學(xué)可以自己去嘗試,一點(diǎn)點(diǎn)的豐富這個(gè)例子。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79916.html

相關(guān)文章

  • 使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】

    摘要:使用構(gòu)建單頁應(yīng)用新篇在去年的七月六號的時(shí)候,發(fā)布了一篇使用構(gòu)建單頁應(yīng)用的文章,文章主要是介紹的基本使用方法,發(fā)現(xiàn)對大部分的入門同學(xué)有很大的幫助,時(shí)至今日還有很多同學(xué)不斷的點(diǎn)贊與收藏,瀏覽量最高達(dá)到。 使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 在去年的七月六號的時(shí)候,發(fā)布了一篇 使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用 的文章,文章主要是介紹 vuex 的基本使用方法...

    crelaber 評論0 收藏0
  • 使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用

    摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國外一篇講述了如何使用和來構(gòu)建一個(gè)簡單筆記的單頁應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 ---------...

    tomorrowwu 評論0 收藏0
  • 使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用

    摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國外一篇講述了如何使用和來構(gòu)建一個(gè)簡單筆記的單頁應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 ---------...

    cnsworder 評論0 收藏0
  • 使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用

    摘要:鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇下的使用方法,傳送門使用構(gòu)建單頁應(yīng)用新篇華麗的分割線原文地址前言在最近學(xué)習(xí)的時(shí)候,看到國外一篇講述了如何使用和來構(gòu)建一個(gè)簡單筆記的單頁應(yīng)用的文章。 鑒于該篇文章閱讀量大,回復(fù)的同學(xué)也挺多的,特地抽空寫了一篇 vue2.0 下的 vuex 使用方法,傳送門:使用 Vuex + Vue.js 構(gòu)建單頁應(yīng)用【新篇】 ---------...

    levius 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<