首頁  >  文章  >  web前端  >  使用Vuex實作一個筆記應用的方法

使用Vuex實作一個筆記應用的方法

亚连
亚连原創
2018-05-30 15:36:381608瀏覽

這篇文章主要介紹了使用Vuex實現一個筆記應用的方法,現在分享給大家,也給大家做個參考。

最近開始著手學習 Vue,先大略的過了一遍官方文檔,跟著敲過一部分官方文檔中的 DEMO,然而還是不甚了。在網路上找到了一個入門的筆記應用,即使是入門級的應用,在學習途中依舊困難重重。特將學習作此筆記,方便今後回看,也希望能夠幫到剛開始學習Vue 的女同學

預期目標

##筆記具備如下基本功能

1.新增
2.刪除
3.收藏
4.在全部筆記和收藏筆記間切換
5.在目前清單中進行搜尋

#賣家秀


買家節目


準備工作

1.新建項目

選個資料夾存放項目,這裡我用的是Git Bush 執行語句($ 符號是Git Bush 中自帶的),你也可以使用命令列,一樣的


選擇項目存放位置


#2.查看模組(愛看不看)

看看全域安裝的模組  npm list --depth=0 -global


檢視全域安裝的模組


3.建立專案

在命令列輸入vue init webpack vuex-note 並做好設置,建立一個專案


這都什麼鬼


4.簡單解釋一下各個設定都是幹嘛的

  1. #vue init webpack vuex-note:初始化(init)一個使用webpack 建置工具建構的vue 項目,項目名為vuex-note

  2. Project name:項目名稱

  3. Project description:專案描述

  4. Author:朕

  5. Vue build:建置方式,分為獨立建置和運行時構建,具體說明請參見如下鏈接,這裡選擇獨立構建standalone https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only

  6. #Install vue-router:是否需要安裝vue-router ,跳轉頁面用的,這裡用不著,我過會學

  7. Use ESLint to lint your code:ESLint 規範與法用的,可能你熟悉的寫法都是不標準的,如果採用ESLint 則可能報錯,這裡選擇n

  8. 剩下的都是測試用的,一路n

  9. Should we run 'npm install' for you after the project has been created:是否需要直接替你安裝(npm install)相關的依賴,回車就行,之後會替你安裝各種玩意

5.安裝完後會有提示,我們接著按照提示走

先是cd vuex-note 進入剛剛建立的vue專案資料夾


安裝完成


#再透過npm run dev 跑起專案





##後續操作

6.存取頁面

#此時透過瀏覽器存取localhost:8080 就可以開啟一個新的vue 頁面

嶄新的vue 頁面

7.專案結構

##截止目前的專案結構如圖


專案結構######由於是初學,為了先搞個東西出來,所以暫時先不管一些亂七八糟的配置,只挑跟這次相關的說(其實多了我也沒學到...)#########8.查看Vuex#########既然是使用Vuex 來實現筆記應用,我們就應該先查看一下建置的專案是否包含Vuex 模組。 #########node_modules 資料夾包含了現有的模組,然而裡面並沒有我們想要的 Vuex,不信自己去看######

package.json 文件描述了專案包含的文件,專案如何運行等資訊

package.json



#9.安裝Vuex

在命令列中輸入npm install vuex --save:--save 是將安裝資訊寫入package.json

已安裝了Vuex

至此,所有前期工作已經準備完成,遺漏的部分將在實作過程中逐一解釋


搞起
  1. 零、想法
  2. 整個應用程式可拆分為三個元件
  3. 每個筆記包括編號(ID),標題(title),內容(content),是否已收藏(fav) 四個資訊

Vuex 中的state 得有個地方存放所有的筆記(notes)

而收藏,刪除操作只能對當前的筆記進行操作,因此我還需要一個標識用來記錄當前的筆記(activeNote) 是哪個

包含全部和收藏兩種切換方式,因此還需要有一個標識來進行區分,就叫show 吧,all 代表全部,fav 就代表已收藏

元件==> actions.js ==> mutations.js = > state:透過元件呼叫actions 中的方法( dispatch),透過actions 中的方法呼叫mutations 中的方法(commit),透過mutations 中的方法去操作state 中的筆記清單(notes),當前筆記(activeNote)等等

#一、index.html

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>vuex-note</title>
 </head>
 <body>
  <p id="app"></p>
  <!-- built files will be auto injected -->
 </body>
</html>

這個沒什麼說的,注意p 的ID 就行

二、main.js


#
import Vue from &#39;vue&#39;
import App from &#39;./App&#39;
import store from &#39;./store&#39;     

Vue.config.productionTip = false

new Vue({
 el: &#39;#app&#39;,
 store,        
 components: { App },
 template: &#39;<App/>&#39;
})

1.import 時什麼時候需要' ./ '?

從專案模組匯出,引入時不需要./,而從自己寫的元件中引入時需要./

2.什麼時候需要import { aaa} from abc 這種加大括號的引進?什麼時候不需要?

當abc 中被導出的部分是export aaa 時

當import 的是被export default 導出的部分時不加{},並且可以起個別名3.專案結構中並沒有store 文件,只有store 資料夾,那import store from './store' 是什麼意思?

不知道,求指教

4. new Vue 中單獨的 store 是什麼意思?

ES6 的一種簡寫方式,縮寫之前是store:store,這句話的意思是為全域注入Vuex,這樣在各個元件中都可以透過this.$store 去呼叫狀態庫,如果不在全域注入,則需要在每個元件中單獨引入,多了會很麻煩

三、store 下的index.js

import Vue from &#39;vue&#39;
import Vuex from &#39;vuex&#39;
import getters from &#39;./getters&#39;
import mutations from &#39;./mutations&#39;
import actions from &#39;./actions&#39;

Vue.use(Vuex)    

const defaultNote = {
  id: +new Date(),    
  title: &#39;新建笔记&#39; + new Date().getMilliseconds(),    // 加时间是为了做一下区分
  content: &#39;笔记内容&#39;,
  fav: false
}

// 可以理解为一个状态的仓库  
const state = {
  notes: [defaultNote],      // 以数组方式存放所有的笔记
  activeNote: defaultNote,    // 用来记录当前笔记  
  show: &#39;all&#39;           // 用于切换 全部 / 已收藏 两种不同列表的标识
}

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

1. Vue.use(Vuex) 是什麼意思?

使用Vuex,今後用Vue-router 時也得來這麼一出,只是得寫在route 資料夾下的index.js 檔案中

2. new Date() 是什麼意思?

取得時間戳記的另一種寫法,等同於new Date().getTime()

    3.state,getters,mutations,actions 之間的關係?
  1. state:如上所言狀態倉庫
  2. getters:state 的修飾,例如state 中有str:"abc" 這麼個屬性,而在許多元件中需要進行str "def" 的操作,如果在每個元件都進行str "def" 的操作未免太麻煩,因此可以在getters 中增加:

  3. ##
    strAdd(){
      return this.str + "abc"
    }

#今後在元件中使用strAdd 就可以了

mutations:簡單講就是用來修改state 的,同步方法.常規呼叫this.$store.commit

#actions:簡單講用來呼叫mutations 的,非同步方法.常規呼叫this.$store.dispatch



四、tool.vue


<template>
  <p id="tool">
    <button class="add" @click="add_note">新增</button>
    <button class="fav" @click="fav_note">收藏</button>
    <button class="del" @click="del_note">删除</button>
  </p>
</template>
<script type="text/javascript">
  import { mapState, mapGetter, mapActions } from &#39;vuex&#39;
  export default {
    name: &#39;tool&#39;,
    methods:{      
      ...mapActions([&#39;add_note&#39;,&#39;del_note&#39;,&#39;fav_note&#39;])
    }
  }
</script>
<style type="text/css" scoped>
  #tool {
    width: 200px;
    height: 600px;
    border: 2px solid #ccc;
    float: left;
  }
  
  button {
    width: 100%;
    height: calc(100% / 3);    
    font-size: 60px;
  }
</style>

#1.mapState, mapGetter, mapActions 都是什麼?

這裡有個非常好的解釋http://www.imooc.com/article/14741#########此外,當methods 和Vuex 的actions 中具有同名的屬性A 時,可使用mapActions(['A']) 這種方式簡寫#########注意:1、中括號不能省略;2、中括號內是字串;3、展開運算子...不能省略#########也可以取個別名,寫法如下,注意[] 變成了{}:########
...map({
 本组件的属性 : Vuex 中 actions 中的属性
})
#######

需要传入参数时,前提是 actions 中的属性(方法)能接收参数:

methods:{
 ...mapActions([&#39;abc&#39;])
 // 自定义一个方法,通过触发这个方法调用之前重名的方法并传入参数
 tragger_abc(参数){
  this.abc(参数)
 }
}

2.scoped

对当前组件生效的 CSS

3.calc

使用时记得在运算符前后各加一个空格

五、list.vue

<template>
  <p id="list">
    <p class="switch">
      <button class="all" @click=&#39;get_switch_note("all")&#39;>全部</button><button class="fav" @click=&#39;get_switch_note("fav")&#39;>已收藏</button>
    </p>
    <p class="search">
      <input type="text" placeholder="在这里搜索" v-model="search" />
    </p>
    <p class="noteList">
      <p class="note" v-for="note in search_filteredNote" :class="{favColor:note.fav===true,active:note.id===activeNote.id}" @click=&#39;get_select_note(note)&#39;>
        <p class="title">
          <p>{{note.title}}</p>
        </p>
        <p class="content">
          <p>{{note.content}}</p>
        </p>
      </p>
    </p>
  </p>
</template>
<script type="text/javascript">
  import { mapState, mapGetters, mapActions } from &#39;vuex&#39;
  export default {
    name: &#39;list&#39;,
    data: function() {
      return {
        search: "" 
      }
    },
    computed: {
      ...mapState([&#39;notes&#39;, &#39;activeNote&#39;]),
      ...mapGetters([&#39;filteredNote&#39;]),
      // 二次过滤:在当前列表(全部 或 已收藏)中进行筛选,返回值被用在组件的 v-for 中 
      search_filteredNote() {
        if(this.search.length > 0) {    // 如果输入框有值,返回二次过滤的结果并加载
          return this.filteredNote.filter(note => {
            if(note.title.indexOf(this.search) > 0) {
              return note
            }
          })
        } else {      // 输入框没值,不过滤,直接拿来加载
          return this.filteredNote
        }
      }
    },
    methods: {
      ...mapActions([&#39;select_note&#39;, &#39;switch_note&#39;]), 
      get_select_note(note) {
        this.select_note(note)
      },
      get_switch_note(type) {
        this.switch_note(type)
      }
    }
  }
</script>
<style type="text/css" scoped="scoped">
  #list {
    width: 300px;
    height: 600px;
    border: 2px solid #ccc;
    float: left;
    margin-left: 10px;
    display: flex;
    flex-direction: column;
  }
  
  p {
    margin: 0;
  }
  
  .switch {}
  
  .switch button {
    height: 60px;
    width: 50%;
    font-size: 40px;
  }
  
  .search {
    border: 1px solid #CCCCCC
  }
  
  input {
    width: 100%;
    box-sizing: border-box;
    height: 50px;
    line-height: 50px;
    padding: 10px;
    outline: none;
    font-size: 20px;
    border: none;
  }
  
  .noteList {
    flex-grow: 1;
    overflow: auto;
  }
  
  .note {
    border: 1px solid #CCCCCC;
  }
  
  .favColor {
    background: pink;
  }
  
  .active {
    background: lightblue
  }
</style>

1.data 中的 search 是干嘛的?可不可以写在 computed 中?

用来与搜索框进行关联。可以写在 computed 中,但 computed 中的属性默认都是 getter ,就是只能获取值,如果想修改,需要设置 setter ,详见官方文档

六、edit.vue

<template>
  <p id="edit">
    <p class="title">
      <input type="text" placeholder="在这里输入标题" v-model="activeNote.title"/>
    </p>
    <p class="content">
      <textarea name="" placeholder="在这里吐槽" v-model="activeNote.content"></textarea>
    </p>
  </p>
</template>
<script type="text/javascript">
  import { mapState, mapGetter, mapActions } from &#39;vuex&#39;
  export default {
    name: &#39;edit&#39;,
    computed:{
      ...mapState([&#39;activeNote&#39;])   // 当本组件中 computed 中的属性名与 Vuex 中的 state 属性名相同时,就可以在 mapState() 中简写
    }
  }
</script>
<style type="text/css" scoped="scoped">
  #edit {
    width: 300px;
    height: 600px;
    border: 2px solid #ccc;
    float: left;
    margin-left: 10px;
    display: flex;
    flex-direction: column;
  }
  
  .title {
    border: 1px solid #CCCCCC;
  }
  
  input {
    width: 100%;
    box-sizing: border-box;
    height: 50px;
    line-height: 50px;
    padding: 10px;
    outline: none;
    font-size: 20px;
    border: none;
  }
  
  .content {
    flex-grow: 1;
    background: orange;
    display: flex;
    flex-direction: column;
  }
  
  textarea {
    width: 100%;
    box-sizing: border-box;
    flex-grow: 1;
    resize: none;
    padding: 10px;
    font-size: 20px;
    outline: none;
    font-family: inherit;
  }
</style>

七、actions.js

export default {
  add_note({commit}) {
    commit(&#39;ADD_NOTE&#39;)
  },
  select_note({commit}, note) {
    commit("SELECT_NOTE", note)
  },
  del_note({commit}) {
    commit("DEL_NOTE")
  },
  fav_note({commit}) {
    commit("FAV_NOTE")
  },
  switch_note({commit}, type) {
    commit("SWITCH_NOTE", type)
  }
}

1.这是干什么?

这里的每个方法实际上是通过 commit 调用 mutations.js 中的方法;

举个栗子:tool.vue 的 新增 按钮上绑了一个 add_note 自定义方法,在 actions.js 中也定义一个同名的方法,这样就可以在 tool.vue 中的 mapActions 中简写,就是下面这句:

# tool.vue
...mapActions([&#39;add_note&#39;,&#39;del_note&#39;,&#39;fav_note&#39;])

而 actions.js 中的 add_note 去调用 mutations.js 中写好的 ADD_NOTE 方法,而实际的添加操作也是在 ADD_NOTE 中,组件也好,actions 也好,最终只是调用 ADD_NOTE 。之所以这么做是因为 mutations 中的方法都是同步的,而 actions 中的方法是异步的,不过在本例里没啥区别

八、getters.js

export default {
  filteredNote: (state) => {
    if(state.show === &#39;all&#39;) {
      return state.notes
    } else {
      return state.notes.filter((note) => {
        if(note.fav === true) {
          return note
        }
      })
    }
  }
}

实现一个过滤,根据 show 来判断展示 全部笔记 还是 已收藏笔记

九、mutations.js

import { SWITCH_NOTE, ADD_NOTE, SELECT_NOTE, DEL_NOTE, FAV_NOTE } from &#39;./mutation-types&#39;

export default {
  [ADD_NOTE](state, note = {
    id: +new Date(),
    title: &#39;新建笔记&#39; + new Date().getMilliseconds(),
    content: &#39;笔记内容&#39;,
    fav: false
  }) {
    state.notes.push(note)
    state.activeNote = note
  },
  [SELECT_NOTE](state, note) {
    state.activeNote = note
  },
  [DEL_NOTE](state) {
    for(let i = 0; i < state.notes.length; i++) {
      if(state.notes[i].id === state.activeNote.id) {
        state.notes.splice(i, 1)
        state.activeNote = state.notes[i] || state.notes[i - 1] || {}
        return
      }
    }
  },
  [FAV_NOTE](state) {
    state.activeNote.fav = !state.activeNote.fav
  },
  [SWITCH_NOTE](state, type) {
    state.show = type
  }
}

1.export default 那里看着好熟悉

ES6 函数的一种写法,中括号 + 常量 作为函数名,这里常量从其它文件引入

十、mutation-types.js

export const ADD_NOTE = "ADD_NOTE"
export const SELECT_NOTE = "SELECT_NOTE"
export const DEL_NOTE = "DEL_NOTE"
export const FAV_NOTE = "FAV_NOTE"
export const SWITCH_NOTE = "SWITCH_NOTE"

抛出常量,mutations.js 中的函数常量就是这里抛出的,查资料说是这么做便于一目了然都有那些方法。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

分析javascript原型及原型链

jQuery中each方法的使用详解

jquery 实现拖动文件上传加载进度条功能

以上是使用Vuex實作一個筆記應用的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn