基于vue+vuex+localStorage的筆記app

本項(xiàng)目采用vue+vuex+localStorage共屈,實(shí)現(xiàn)一個(gè)本地存儲(chǔ)的筆記app执隧,項(xiàng)目預(yù)覽見(jiàn)demo,源碼可訪問(wèn)我的github

項(xiàng)目的下載安裝步驟

git clone https://github.com/Anticlimax/vue-note.git
cd vue-note
npm install 
npm run dev

讓我們通過(guò)這樣一個(gè)有一定數(shù)據(jù)操作要求的應(yīng)用夹纫,來(lái)學(xué)習(xí)vue和vuex的使用寸宵。

  1. 起步
    首先恤煞,通過(guò)vue-cli構(gòu)建基本應(yīng)用模板,方便開(kāi)發(fā)
npm i vue-cli -g
vue init webpack vue-note
cd vue-note
npm run dev

這樣,我們就起了一個(gè)本地的開(kāi)發(fā)服務(wù)器刊苍,而且可以實(shí)現(xiàn)熱加載,設(shè)置一下編輯器的自動(dòng)保存就能實(shí)時(shí)看到代碼變化濒析。
2.項(xiàng)目邏輯
我們開(kāi)發(fā)的項(xiàng)目的ui如下
![OHLNC51QG}K3D%7VV37Z]L1.png](http://upload-images.jianshu.io/upload_images/3599810-054054226e79bf05.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
大概分為左側(cè)工具欄正什,中間筆記列表及右側(cè)編輯欄,所以我們先構(gòu)建項(xiàng)目的基本骨架号杏。

//App.vue
<template>
  <div id="app">
    <Toolbar></Toolbar>
    <NoteList></NoteList>
    <Editor></Editor>
  </div>
</template>
<script>

  import Toolbar from './components/Toolbar.vue'
  import Editor from './components/Editor.vue'
  import NoteList from './components/NoteList.vue'
  import './assets/css/reset.css'

  export default {
    name: 'app',
    store,    //向根組件注入store埠忘,這樣所有的子組件都能夠調(diào)用store
    components: {
      Toolbar,
      NoteList,
      Editor
    }
  }
</script>

這是我們的根實(shí)例,引用了三個(gè)組件Toolbar馒索,NoteList和Editor莹妒,這樣我們只需要分別對(duì)三個(gè)組件進(jìn)行開(kāi)發(fā)就好了。
但是在此之前绰上,我們先思考一下項(xiàng)目的邏輯旨怠,我們要完成的功能如下:

  • 通過(guò)Toolbar的添加,收藏和刪除按鈕對(duì)NoteList中的列表項(xiàng)進(jìn)行操作
  • NoteList上的All和Favorites按鈕可以切換顯示所有筆記和收藏筆記
  • Ediotr上部的title區(qū)和NoteList部分筆記顯示的題目相同
  • Ediotr下部的內(nèi)容區(qū)在切換筆記后不會(huì)消失

基于這樣的功能蜈块,我們先來(lái)編寫(xiě)store.js鉴腻,在src文件夾下新建一個(gè)vuex目錄,下包含一個(gè)store.js文件

//store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

let state = {
  notes: [],
  activeNote: {}
}

const mutations = {
}


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

這里就是我們的數(shù)據(jù)中心百揭,所有的數(shù)據(jù)操作都由此流入和流出爽哎,接下來(lái)就是寫(xiě)mutations的相關(guān)邏輯,我們先來(lái)完成一個(gè)添加操作作為例子

// store.js
const mutations = {
  ADD_NOTE(state){
    const newNote = {
      title: 'New Note',
      favorite: false,
      content: '',
      id: new Date()
    }
    state.notes.push(newNote)
    state.activeNote = newNote
  }
}

這段代碼表示器一,每次添加筆記時(shí)都會(huì)向state下的notes數(shù)組push一個(gè)對(duì)象课锌,并且把激活筆記設(shè)置為新添加的這個(gè)筆記。
接下來(lái)是Toolbar的相關(guān)邏輯

//Toolbar.vue
<template>
  <div id="Toolbar">
    <ul class="btnList">
      <li @click="addNote" ><i class="iconfont icon-jiahao"></i></li>
      <li><i class="iconfont icon-wujiaoxingshixin"></i></li>
      <li><i class="iconfont icon-cheng"></i></li>
    </ul>
  </div>
</template>
<script>

  export default {
    methods:{
      addNote(){
        this.$store.commit('ADD_NOTE')
      }
  }
</script>

我們?yōu)樘砑影粹o綁定了一個(gè)addNote事件祈秕,在每次點(diǎn)擊的時(shí)候觸發(fā)渺贤,這個(gè)事件會(huì)向store提交一個(gè)觸發(fā)ADD_NOTE這個(gè)mutation的請(qǐng)求,這樣就向state下的notes新添加了一個(gè)對(duì)象请毛。接下來(lái)我們需要讓這個(gè)筆記顯示出來(lái)志鞍。

//NoteList.vue
<template>
  <div id="NoteList">
    <div class="header-wrapper">
      <h3 class="header">NOTES</h3>
      <div class="btn-wrapper">
        <a href="#">All Notes</a>
        <a href="#">Favorites</a>
      </div>
    </div>
    <ul class="list">
      <li v-for="note in noteList">
        {{ note.title }}
      </li>
    </ul>
  </div>
</template>
<script>
  export default {
    name: 'NodeList',
    computed: {
      noteList(){
          return this.$store.state.notes
        }
  }
</script>

我們?cè)谶@里先使用計(jì)算屬性取得state下的notes數(shù)組,再對(duì)這個(gè)數(shù)據(jù)進(jìn)行遍歷方仿,就能顯示所有新建的筆記固棚。接下來(lái)來(lái)看Editor中對(duì)標(biāo)題和內(nèi)容的處理

//Editor.vue
<template>
  <div id="Editor">
    <input type="text" id="EditorTitle" placeholder="請(qǐng)輸入筆記標(biāo)題"
           :value="activeNoteTitle" @input="updateTitle">
    <textarea name="editor" id="editorPanel"
              @input="updateContent" :value="activeNoteText">
    </textarea>
  </div>
</template>
<script>


  export default {
    name:'Editor',
    computed:{
      activeNoteText(){
         return this.$store.state.activeNote.content
      },
      activeNoteTitle(){
        return this.$store.state.activeNote.title
      }
    },
    methods:{
      updateContent(e){
        console.log(this.activeNoteText)
        this.$store.commit("EDIT_NOTE", e.target.value)
      },
      updateTitle(e){
        this.$store.commit("EDIT_TITLE",e.target.value)
      }
    }
  }

我們分別對(duì)兩塊輸入?yún)^(qū)域都綁定了input事件,在每次輸入的時(shí)候都會(huì)觸發(fā)相應(yīng)事件仙蚜,讓mutation進(jìn)行響應(yīng)的操作此洲。重點(diǎn)是使用了:value而不是v-model進(jìn)行輸入框數(shù)據(jù)的操作,這是由于vuex本身的設(shè)計(jì)不建議使用雙向綁定鳍征,在嚴(yán)格模式下使用v-model會(huì)報(bào)錯(cuò)黍翎。
依據(jù)以上的例子面徽,大致就可以完成整個(gè)app了艳丛,其余的只是一些邏輯的處理匣掸,接下來(lái)我們來(lái)完成本地存儲(chǔ)的功能。我們希望每次刷新頁(yè)面數(shù)據(jù)都能保存到本地而不是全部清空氮双,這樣就要用到localStorage碰酝,它有如下的基本用法

window.localStorage.setItem('name',data) //保存數(shù)據(jù),放在name鍵下
window.localStorage.getItem('name') // 取出name鍵的數(shù)據(jù)
window.localStorage.removeItem('name') //刪除name字段的數(shù)據(jù)

接下來(lái)需要思考的是戴差,我們改在什么時(shí)候存取數(shù)據(jù)呢送爸?每次數(shù)據(jù)更新都保存顯得有點(diǎn)傻,我決定在頁(yè)面刷新之前來(lái)保存數(shù)據(jù)暖释,在頁(yè)面創(chuàng)建后就獲取數(shù)據(jù)袭厂。所以進(jìn)行如下處理

//Appd.vue
<script>
...
created(){

      window.onbeforeunload = ()=>{
        this.$store.commit('SAVE_DATA')
      }

      this.$store.commit('INIT_DATA')

    }
...
</script>
//store.js
...
const mutations = {
...
  INIT_DATA(state){
    if (window.localStorage.getItem('vue-note')) {
     this.state = window.localStorage.getItem('vue-note')

    }
  },
  SAVE_DATA(state){
    window.localStorage.setItem('vue-note', JSON.stringify(state))
  }
}
...

這樣就實(shí)現(xiàn)了在頁(yè)面刷新前保存數(shù)據(jù),在頁(yè)面載入后讀取數(shù)據(jù)球匕,看起來(lái)很美好纹磺,但是實(shí)際操作后發(fā)現(xiàn)問(wèn)題。
雖然我們重寫(xiě)了state為保存的數(shù)據(jù)亮曹,但是視圖并沒(méi)有更新橄杨,這是為什么?四處尋找后終于找到了答案照卦,就在vue的文檔中
深入響應(yīng)式原理
簡(jiǎn)單來(lái)講就是式矫,vue不能檢測(cè)到對(duì)象屬性的添加與刪除,也不允許在已經(jīng)創(chuàng)建的實(shí)例上動(dòng)態(tài)添加新的根級(jí)響應(yīng)式屬性役耕。如果需要修改以及實(shí)例化的屬性采转,需要使用vue.set()方法。所以我們對(duì)store.js進(jìn)行如下的修改

//store.js
  INIT_DATA(state){
    if (window.localStorage.getItem('vue-note')) {
      const oldState = JSON.parse(window.localStorage.getItem('vue-note'))
      Vue.set(state, 'notes', oldState.notes)
      Vue.set(state, 'activeNote', oldState.activeNote)
    }
  },
  SAVE_DATA(state){
    window.localStorage.setItem('vue-note', JSON.stringify(state))
  }

這樣瞬痘,就完美實(shí)現(xiàn)了本地存儲(chǔ)功能氏义。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市图云,隨后出現(xiàn)的幾起案子惯悠,更是在濱河造成了極大的恐慌,老刑警劉巖竣况,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件克婶,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡丹泉,警方通過(guò)查閱死者的電腦和手機(jī)情萤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)摹恨,“玉大人筋岛,你說(shuō)我怎么就攤上這事∩购澹” “怎么了睁宰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵肪获,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我柒傻,道長(zhǎng)孝赫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任红符,我火速辦了婚禮青柄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘预侯。我一直安慰自己致开,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布萎馅。 她就那樣靜靜地躺著喇喉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪校坑。 梳的紋絲不亂的頭發(fā)上拣技,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音耍目,去河邊找鬼膏斤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邪驮,可吹牛的內(nèi)容都是我干的莫辨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼毅访,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沮榜!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起喻粹,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蟆融,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后守呜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體型酥,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年查乒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弥喉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡玛迄,死狀恐怖由境,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蓖议,我是刑警寧澤虏杰,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布讥蟆,位于F島的核電站,受9級(jí)特大地震影響嘹屯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜从撼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一州弟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧低零,春花似錦婆翔、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至雄妥,卻和暖如春最蕾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背老厌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工瘟则, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枝秤。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓醋拧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親淀弹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子丹壕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容