您好,登錄后才能下訂單哦!
小編給大家分享一下如何使用vuejs2.0+vuex 2.0構建記事本應用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
開始吧
以下是 notes-vuex-app 的源文件目錄:
在使用 vue 2 重寫這個 app 之前,我在想能不能不改變文件目錄結構以及配置位置呢?就是用比較生硬的方式重寫,或者說單純的語法修改。事實是可行的,否則我就不會寫這篇文章了。然而面對的問題非常多,但卻因此深入的理解了 vue 以及 vuex。最大的問題是 webpack 的構建,如果使用 webpack 2.0+的話,坑比較多。本人是菜鳥,所以最終選擇了 vue-cli 提供的兩個 webpack 的模板,分別是 webpack-simple 和 webpack,我先使用 webpack-simple,它和原 app 的結構基本吻合。目錄如下:
使用 vue-cli 生成基本目錄之后,再安裝 vuex2 。
main.js 的小改動
原示例 main.js 如下所示,但運行出錯了,主要是 Vue 2 的根實例渲染稍有變化
import Vue from 'vue' import store from './vuex/store' import App from './components/App.vue' new Vue({ store, // 注入到所有子組件 el: 'body', components: { App } })
改正之后:
import Vue from 'vue' import store from './vuex/store' import App from './components/App.vue' new Vue({ store, // inject store to all children el: '#app', template: '<App/>', components: { App } })
或者
import Vue from 'vue' import store from './vuex/store' import App from './components/App.vue' new Vue({ store, // inject store to all children el: '#app', render: h => h(App) })
vuex 2 的變化
這個應用改寫的主要問題集中在 vuex 2 的變化上,這些變化確實會讓人感到凌亂,我無數次抓耳撓腮的罵娘。不過通過官方給出的示例也可以看出一些端倪。
首先是 action.js,只需注意一點,所有的 dispatch 都要改成 commit。
export const addNote = ({ commit }) => { commit('ADD_NOTE') } export const editNote = ({ commit }, e) => { commit('EDIT_NOTE', e.target.value) } export const deleteNote = ({ commit }) => { commit('DELETE_NOTE') } export const updateActiveNote = ({ commit }, note) => { commit('SET_ACTIVE_NOTE', note) } export const toggleFavorite = ({ commit }) => { commit('TOGGLE_FAVORITE') }
store.js 變化也不大,但是要注意幾個地方:
import Vue from 'vue' import Vuex from 'vuex' import * as actions from './actions' Vue.use(Vuex) const state = { notes: [], activeNote: {} } const mutations = { ADD_NOTE (state) { const newNote = { text: 'New note', favorite: false } state.notes.push(newNote) state.activeNote = newNote }, EDIT_NOTE (state, text) { state.activeNote.text = text }, DELETE_NOTE (state) { state.notes.splice(state.notes.indexOf(state.activeNote),1) state.activeNote = state.notes[0] || {} }, TOGGLE_FAVORITE (state) { state.activeNote.favorite = !state.activeNote.favorite }, SET_ACTIVE_NOTE (state, note) { state.activeNote = note } } const getters = { notes: state => state.notes, activeNote: state => state.activeNote, activeNoteText: state => state.activeNote.text } export default new Vuex.Store({ state, mutations, actions, getters })
原示例文件中沒有將 getters 寫到 store.js 中,而是直接在組件中定義的。為了更清晰,我仿照官方示例也提取出來寫在了 store.js 中,這樣在組件中調用時比較方便。其次也引入了 action.js,并作為 actions 對象傳遞給 Vuex.store(),這算是 vuex 的標準寫法吧,對于后面在組件中調用比較有利。
其中要注意 DELETE_NOTE (state){} 這個方法,原示例使用了 vue1 提供的 remove 方法,但是 vue2 中去掉了這個方法。仔細想想就會明白,這個函數的作用就是刪除 notes 數組中的元素。可以使用原生的 splice 方法。如果 JS 基礎扎實的話,這里應該很好理解,沒有什么大問題。其次相比原示例,添加一個刪除后操作的判斷。
我之前一直不太理解 flux 的概念,感覺像是新東西,完全不知道它的目的及作用。換成 Vuex,還是有點稀里糊涂。但是通過修改這個示例,基本算是開竅了。這些東西本身并沒有玄機奧妙,想一想,如果我們不用框架,而是自己手寫一個 todoMVC 時要怎么做?應該也是這樣的思路,定義一個 notes 數組變量以及 activeNote 的變量。然后在創建一些改變狀態的方法。我在面試中遇到過一個情況,面試官反復問我為什么需要使用框架,用 jQuery 不是也可以實現嗎?這樣說確實沒錯,用比較原始的方法當然可以做,只是代碼結構會冗余或者凌亂,缺少小而美的特點。框架以及設計模式對代碼做了整合封裝,對于一個 CURD 應用比較友好,實現起來更方便更簡單。我對于 Vuex 的理解就是,它是一個對象,封裝了與狀態相關的方法和屬性。而所謂的狀態就是點擊、按鍵等操作之后的變化。
組件中使用 vuex
先看一下 Toolbar.vue 這個組件。修改后的代碼如下:
<template> <div id="toolbar"> <i @click="addNote" 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 { mapGetters, mapActions } from 'vuex' export default { computed: mapGetters([ 'activeNote' ]), methods: { ...mapActions([ 'addNote', 'deleteNote', 'toggleFavorite' ]) } } </script>
通過和原示例代碼對比,這里的區別一目了然。我通過在控制臺打印 Vue 實例,折騰很長時間才大體明白怎么回事。vuex 1 在組件中使用時會直接將 getters 以及 actions 掛到 vuex 這個屬性上,沒有提供 mapGetters 及 mapActions 等一些方法。而 vuex2 使用 mapGetters 及 mapActions 等一些方法將 actions 的方法掛到 Vue 實例上。總的來說,都是把 actions 的方法掛到 Vue 實例上。我們從這個層面上談談 Vue 實例,Vue 2 的變化就是其屬性的變化。比如 Vue1 中在 methods 中添加的方法可以在 vue 實例的 $options 屬性中查看,而 vue2 中這些方法可以直接在第一級屬性中查找或者在 $options 屬性下的原型方法中 __proto__ 尋找。在 vue1 中可以查看 vuex 這個屬性,但是 vue2 中移除了。至于其它的不同,大家可以自己對比,通過這種方式,可以深入理解 vue 的設計思想。
下圖是 Vue1 實例截圖:
ES5 實現擴展運算符
假設其它組件都以這種方式改好了,就在我們滿心歡喜地運行示例時,又報錯了。問題出在擴展運算符 ... 上,webpack-simple 這個模板無法解析 ES6 的 ...。為此,我又折騰了很久,想試著修改 webpack 的配置文件,但改動太大。我妥協了,決定拋棄擴展運算符,手寫這個方法。當然如果使用 webpack 的模板就沒有問題,這個比較簡單,我們最后再說。
手寫擴展運算符 ... 之前,我們先看一下 mapActions 這個方法。對于 mapGetters 以及 mapActions 這兩個函數,最簡單的理解辦法就是查看 vuex 的源碼,最終返回的是一個對象。也就是根據需要獲取 store.js 中 actions 對象的某些方法。然后通過擴展運算符把返回的對象拆開然后掛到 Vue 實例上。舉例來說(以下只是擴展運算符的用法之一,別的用法可以參考其它的文章):
var obj = { a: 1, b: 2, } var methods = { ...obj } // console.log(methods) { a: 1, b: 2 }
明白擴展運算符的用法之后就好辦了。為了簡單一點,我直接使用 babel 官網的在線解析器,查看擴展運算符的 ES5 寫法。
// ES5 實現擴展運算符... var _extends = Object.assign || function(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
完整的 Toolbar.vue 組件代碼如下:
<template> <div id="toolbar"> <i @click="addNote" 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> <i @click="_test" class="glyphicon glyphicon-remove"></i> </div> </template> <script> import { mapGetters, mapActions } from 'vuex' // ES5 實現擴展運算符... var _extends = Object.assign || function(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var actions = mapActions([ 'addNote', 'deleteNote', 'toggleFavorite' ]); var methodsObj = _extends({},actions) export default { computed: mapGetters([ 'activeNote' ]), methods:methodsObj } </script>
其余兩個子組件類似,相信大家已經明白了我的思路,具體代碼如下:
NotesList.vue
<template> <div id="notes-list"> <div id="list-header"> <h3>Notes | coligo</h3> <div class="btn-group btn-group-justified" role="group"> <!-- All Notes button --> <div class="btn-group" role="group"> <button type="button" class="btn btn-default" @click="show = 'all'" :class="{active: show === 'all'}"> All Notes </button> </div> <!-- Favorites Button --> <div class="btn-group" role="group"> <button type="button" class="btn btn-default" @click="show = 'favorites'" :class="{active: show === 'favorites'}"> Favorites </button> </div> </div> </div> <!-- render notes in a list --> <div class="container"> <div class="list-group"> <a v-for="note in filteredNotes" class="list-group-item" href="#" rel="external nofollow" :class="{active: activeNote === note}" @click="updateActiveNote(note)"> <h5 class="list-group-item-heading"> {{note.text.trim().substring(0, 30)}} </h5> </a> </div> </div> </div> </template> <script> import { mapGetters, mapActions } from 'vuex' // ES5 實現擴展運算符... var _extends = Object.assign || function(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var getters = mapGetters([ 'activeNote' ]); var filters = { filteredNotes: function () { if (this.show === 'all'){ return this.$store.state.notes } else if (this.show === 'favorites') { return this.$store.state.notes.filter(note => note.favorite) } } } var actions = mapActions(['updateActiveNote']) var computedObj = _extends({},getters,filters); var methodsObj = _extends({},actions); export default { data () { return { show: 'all' } }, computed:computedObj, methods:methodsObj } </script>
Editor.vue
<template> <div id="note-editor"> <textarea :value="activeNoteText" @input="editNote" class="form-control"> </textarea> </div> </template> <script> import { mapGetters, mapActions } from 'vuex' export default { computed:mapGetters(['activeNoteText']), methods:mapActions(['editNote']) } </script>
Webpack 模板
直接使用 vue-cli 的 webpack 模板就會簡單很多,可以直接解析擴展運算符,代碼也會比較簡潔。
以上是“如何使用vuejs2.0+vuex 2.0構建記事本應用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。