vuex-stepbystep 經典案例,詳細註釋一步到位

系列文章

Vuex

是什麼(官網已經很完善了)

  • Vuex 是一個 Vue 中的狀態管理工具
  • 狀態,即數據(data)
  • 狀態管理工具就是用來管理 Vue 項目中組件中的數據的

爲何要使用 Vuex

  • Vuex 只應該在中大型複雜的 Vue 項目中使用
  • 小項目中不須要使用 Vuex

Vuex 的說明

  • Vuex 採用集中的方式統一管理了項目中全部須要共享的數據,只要組件之間相同共享數據就要經過 Vuex 才能實現
  • 可預測性
  • 能夠簡單理解爲 Vuex 是一個加強版的 bus

狀態管理

  • 前端最先的狀態管理思想是由 React 的 Flux 提出來的
  • Flux 不只提出了 前端狀態管理的思想,也提供對應的實現
  • 其餘狀態管理庫:Flux / Redux / Mobx / Vuex

actions 和 mutations 的區別

Vuex 中的核心概念

  • store

Vuex 的特色

  • Vuex 中的數據也是響應式的(雙向綁定的)

案例搭建

  • 技術點
    • vuex
    • vue-cli 2.0
    • todos 模板
  • 項目目錄

  • 而後咱們開始搭建項目,使用vue-cli的步驟,就跳上過了,樓主在vue-admin教程中有詳細步驟,如今咱們在src目錄下新建store文件夾,而後新建index.js文件,而後咱們初始化store,代碼以下

import Vue from 'vue'//引入vue
import Vuex from 'vuex'//引入vuex

// 安裝
Vue.use(Vuex)

// 初始化state
const state = {}

// mutations
const mutations = {}

// 建立store把state和mutation 寫入Vuex.store中
const store = new Vuex.Store({
  state,
  mutations
})

export default store //導出store
複製代碼
  • 而後咱們在main.js引入,掛載到vue的實例中
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'

// 導入樣式
import '@/assets/index.css'

// 導入store
import store from './store'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  // 將 Vuex(store) 和 Vue實例關聯到一塊兒
  store,
  components: { App },
  template: '<App/>'
})

複製代碼
  • 而後配置App.vue,把todos模板組件導入App.vue中,咱們的store就配置好了

功能完成

  • 效果圖 (ps:經典到吐)
  • 咱們如今完善store,把數據填入,進行增刪更新的一些狀態的統一操做。
import Vue from 'vue'//引入vue
import Vuex from 'vuex'//引入vuex

// 安裝
Vue.use(Vuex)

// 初始化state
const state = {
  todos: [
    { id: 1, name: '禿頭', done: false },
    { id: 2, name: '女友跑了', done: false },
    { id: 3, name: '左手更加的有力', done: true }
  ]
}

// mutations配置
const mutations = {
  // 根據id修改完任務的成狀態
  changeDone(state, payload) {
    // 1 根據id找到當前任務
    const curTodo = state.todos.find(item => item.id === payload.id) //箭頭函數了解下
    // 2 狀態直接取反便可
    curTodo.done = !curTodo.done
  },

  // 添加任務方法
  addTodo(state, payload) {
    const length = state.todos.length
    const id = length === 0 ? 1 : state.todos[length - 1].id + 1

    state.todos.push({
      id,
      name: payload.name,
      done: false
    })
  },

  // 刪除任務方法
  delTodo(state, payload) {
    state.todos.splice(payload.index, 1)
  },

  // 更新任務方法
  updateTodo(state, payload) {
    // 查找到當前要更新的任務
    const curTodo = state.todos.find(item => item.id === payload.id)
    // 修更名稱
    curTodo.name = payload.name
  },

  // 清除已完成任務
  clearAllDone(state) {
    state.todos = state.todos.filter(item => !item.done)
  }
}

// actions 異步操做(面試考察點)
// 內部仍是提交的 mutations
const actions = {
  // 異步添加任務
  addTodoAsync(context, payload) {
    // setTimeout就是一個異步操做, 內部仍是提交的 mutations
    setTimeout(() => {
      context.commit('addTodo', {
        name: payload.name
      })
    }, 2000)
  }
}

// getters
// 至關於Vue組件中的 計算屬性 ,用法徹底相同
// 當須要從現有的state中獲得一些新的數據(好比:從 todos 集合中,獲得未完成任務數量)
// 就要使用 getters ,也就是計算屬性
const getters = {
  // 未完成任務數量
  unDoneCount(state) {
    return state.todos.filter(item => !item.done).length
  },

  // 控制清除已完成任務按鈕的展現和隱藏
  showClearDone(state) {
    return state.todos.some(item => item.done)
  }
}

// 建立store
const store = new Vuex.Store({
  // 開啓嚴格模式
  // 開發期間 NODE_ENV 的值爲: 'development'
  // 生成環境中 NODE_ENV 的值爲: 'production'
  strict: process.env.NODE_ENV !== 'production',
  state,
  mutations,
  actions,
  getters
})

export default store

複製代碼
  • 而後咱們進行TodoHeader的添加操做
<template>
  <header class="header">
    <h1>todos</h1>
    <input 
      <!--數據綁定,對應data中的數據-->
		v-model="todoName" 
		<!--enter修飾符,綁定時間-->
		@keyup.enter="addTodo"
		 class="new-todo" 
		 placeholder="What needs to be done?"
		 <!--自動聚焦-->
		 autofocus>
  </header>
</template>

<script>
export default {
  data() {
    return {
      // 由於這個數據只會在當前組件中使用
      // 所以,就不須要放到 Vuex 中
      todoName: ''
    }
  },

  methods: {
    // 添加任務
    addTodo() {
    //input輸入框一般咱們會trim一下,把空格幹掉
      if (this.todoName.trim() === '') {
        return
      }

      // 調用 Vuex 中提供的 mutations 便可(在組件中,經過$store.commit方法來執行mutation)
      // this.$store.commit('addTodo', {
      //   name: this.todoName
      // })

      // 調用 actions 來完成,異步添加(action在組件內經過$store.dispatch觸發)
      this.$store.dispatch('addTodoAsync', {
        name: this.todoName
      })

      this.todoName = ''//完成以後,清空input框的內容
    }
  }
}
</script>
複製代碼
  • 而後咱們操做列表組件TodoList

<template>
  <section class="main">
    <input id="toggle-all" class="toggle-all" type="checkbox">
    <label for="toggle-all">Mark all as complete</label>
    <ul class="todo-list">
      <!--
        完成狀態: completed
        編輯狀態: editing
       -->
      <li 
			:class="{ completed: todo.done, editing: todo.id === editId }"
			 v-for="(todo, index) in $store.state.todos" 
			 :key="todo.id">
        <div class="view">
          <!--
            前提:由於咱們知道 Vuex 中的數據,只能經過 mutations 中提供的方法來修改
            由於在 checkbox 中使用了 v-model,v-model是雙向綁定的,當點擊 複選框 的時候,會將其對應的數據修改,
            這樣就違背了 Vuex 中數據只能由 mutations 修改這個原則了!!!

            數據 -> 視圖: :checked="todo.done" (單向)
            視圖 -> 數據: 先綁定一個事件,在事件中調用 mutations 來完成數據修改
           -->
          <input 
					class="toggle"
					 type="checkbox"
					 :checked="todo.done"
					 @change="changeDone(todo.id)">
          <!-- <input class="toggle" type="checkbox" v-model="todo.done"> -->
          <label @dblclick="showEditStatus(todo.id)">{{ todo.name }}</label>
          <button class="destroy" @click="delTodo(index)"></button>
        </div>
        <input class="edit" :value="todo.name" @keyup.enter="updateTodo(todo.id, index)" ref="todoUpdate">
      </li>
    </ul>
  </section>
</template>

<script>
export default {
  data() {
    return {
      // 臨時變量,用來處理編輯狀態
      editId: -1
    }
  },
  methods: {
    // 出現編輯狀態
    showEditStatus(id) {
      this.editId = id
    },

    // 更新任務名稱
    updateTodo(id, index) {
      // 根據索引號找到對應的文本框
      const name = this.$refs.todoUpdate[index].value

      this.$store.commit('updateTodo', {
        id,
        name
      })

      // 去掉編輯狀態
      this.editId = -1
    },

    // 切換完成狀態
    changeDone(id) {
      // 調用 mutations 中提供的方法,來修改state中的數據
      this.$store.commit('changeDone', {
        id
      })
    },

    // 刪除任務
    delTodo(index) {
      this.$store.commit('delTodo', {
        index
      })
    }
  }
}
</script
<style>
</style>

複製代碼
  • 底部就一個清除,直接貼代碼了
export default {
  methods: {
    // 清除全部已完成任務
    clearAllDone() {
      this.$store.commit('clearAllDone')
    }
  }
}
複製代碼

結語

  • 我看了有些,博文,感受把vueX都神話了,各位小夥伴把我這篇教程看完,其實就這些東西。
  • 大項目確實很方便,具體使用:按需使用。
相關文章
相關標籤/搜索