面试官:请你说一说vuex的五个属性,分别是什么,区别和用途说一下
面試的時候,你有可能會被問到
- vuex的五個屬性,分別是什么,區別和用途說一下
這個地方回答還是需要細思斟酌的
如果隨性回答,思路可能會混亂
查了一下官網,關于vuex的五個屬性還是有很多知識點的
官網:https://vuex.vuejs.org/zh/guide/
01 前言
當我們用 Vue.js 開發一個中到大型的單頁應用時,經常會遇到如下問題:
- 如何讓多個 Vue 組件共享狀態??
- Vue 組件間如何通訊??
通常,在項目不是很復雜的時候,我們會利用全局事件總線 (global event bus)解決,但是隨著復雜度的提升,這些代碼將變的難以維護。因此,我們需要一種更加好用的解決方案,于是,Vuex 誕生了。
02 什么是vuex?
- VueX 是一個專門為 Vue.js 應用設計的狀態管理架構,統一管理和維護各個vue組件的可變化狀態(你可以理解成 vue 組件里的某些 data )。
- 它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。
- Vue有五個核心概念,state, getters, mutations, actions, modules。
- Vuex 也集成到 Vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel調試、狀態快照導入導出等高級調試功能。
- 狀態管理: 簡單理解就是統一管理和維護各個vue組件的可變化狀態(你可以理解成vue組件里的某些data)
- vuex借鑒了 Flux、Redux、和 The Elm Architecture。與其他模式不同的是,Vuex 是專門為 Vue.js 設計的狀態管理庫,以利用 Vue.js 的細粒度數據響應機制來進行高效的狀態更新。
學習資料:
官網文檔:http://vuex.vuejs.org/en/
中文文檔:https://github.com/vuejs/vuex/tree/dev/docs/zh-cn
官網是這樣說的:
每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含著你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有以下兩點不同:
- Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
- 你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit)mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。
03 什么情況下我應該使用 Vuex?
- 雖然 Vuex 可以幫助我們管理共享狀態,但也附帶了更多的概念和框架。這需要對短期和長期效益進行權衡。
- 如果您不打算開發大型單頁應用,使用 Vuex 可能是繁瑣冗余的。確實是如此——如果您的應用夠簡單,您最好不要使用 Vuex。一個簡單的
global event bus就足夠您所需了。但是,如果您需要構建是一個中大型單頁應用,您很可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成為自然而然的選擇。
04 安裝
- NPM安裝
- 在一個模塊化的打包系統中,您必須顯式地通過 Vue.use() 來安裝 Vuex:
05 最簡單的 Store
安裝 Vuex 之后,讓我們來創建一個 store。創建過程直截了當——僅需要提供一個初始 state 對象和一些 mutations:
const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count++}} })在 src 下新建文件夾 vuex,進入 vuex 新建 store.js,
在store.js中添加代碼如下:
現在,你可以通過 store.state 來獲取狀態對象,以及通過 store.commit 方法觸發狀態變更:
store.commit('increment') console.log(store.state.count) // -> 1在App.vue文件中添加代碼,在templete模板中添加一個按鈕和點擊事件
<button v-on:click="addClick">加</button>在<script>中引入store及添加方法(methods與data同級)
import store from './vuex/store' methods:{addClick:function(){store.commit('increment')console.log(store.state.count) // -> 1}}06 核心概念:state、 getter 、mutations 、 actions
mutations
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutations 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,并且它會接受 state 作為第一個參數:
const store = new Vuex.Store({state: {count: 1},mutations: {increment (state) {// 改變狀態state.count++}} })你不能直接調用一個 mutation 回調函數。要喚醒一個 mutation,你調用 store.commit 方法(參數為回調函數名):
store.commit('increment')mutation回調函數的第一個參數始終為store,你可以向 store.commit 傳入額外的參數,即 mutation 的 載荷(playload):
// ... mutations: {increment (state, n) {state.count += n} } store.commit('increment', 10)在大多數情況下,載荷應該是一個對象,這樣可以包含多個字段并且記錄的 mutation 會更易讀:
// ... mutations: {increment (state, payload) {state.count += payload.amount} } store.commit('increment', {amount: 10 })mutations對象風格的提交方式
提交 mutation 的另一種方式是直接使用包含 type 屬性的對象:
store.commit({type: 'increment',amount: 10 })當使用對象風格的提交方式,整個對象都作為載荷傳給 mutation 函數,因此 handler 保持不變:
mutations: {increment (state, payload) {state.count += payload.amount} }你可以在組件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 輔助函數將組件中的 methods 映射為 store.commit 調用(需要在根節點注入 store)。
import { mapMutations } from 'vuex' export default {// ...methods: {...mapMutations(['increment' // 映射 this.increment() 為 this.$store.commit('increment')]),...mapMutations({add: 'increment' // 映射 this.add() 為 this.$store.commit('increment')})} }actions
action 類似于 mutation,不同在于:
- action 提交的是 mutation,而不是直接變更狀態。
- action 可以包含任意異步操作。
在 vuex 里面 actions 只是一個架構性的概念,并不是必須的,本質上就是一個函數,你在里面想干嘛都可以,可以通過異步方式執行各種任務,要修改state數據還是需要通過commit觸發 mutation 。
可以把mutation比作倉庫的管理員,負責倉庫管理,而把action比作領導,可以命令倉庫管理員作操作,但不會親自動手。
注冊一個簡單的 action:
const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count++}}, actions: {increment (context) {context.commit('increment')}} })actions 的第一個參數是 context,它向外暴露一組與 store 實例相同的方法/屬性,所以可以直接調用 context.commit 或者訪問 context.state 或者 context.getters 。我們通常使用 es6 的參數解構來簡化我們的代碼,直接寫成{ commit }
actions: {increment ({ commit }) {commit('increment')} }Action 通過 store.dispatch 方法觸發:
- store.dispatch(‘increment’)
乍一眼看上去感覺多此一舉,我們直接分發 mutation 豈不更方便?實際上并非如此,還記得 mutation 必須同步執行這個限制么?Action 就不受約束!我們可以在 action 內部執行異步操作:
actions: {incrementAsync ({ commit }) {setTimeout(() => {commit('increment')}, 1000)} }Actions 支持同樣的載荷方式和對象方式進行分發:
- 以載荷形式分發
- 以對象形式分發
在組件中分發 Action
在組件中使用 this.$store.dispatch('xxx') 分發 action,或者使用 mapActions 輔助函數將組件的 methods 映射為 store.dispatch 調用(需要先在根節點注入 store):
import { mapActions } from 'vuex' export default {// ...methods: {...mapActions(['increment' // 映射 this.increment() 為 this.$store.dispatch('increment')]),...mapActions({add: 'increment' // 映射 this.add() 為 this.$store.dispatch('increment')})} }組合 Actions
Action 通常是異步的,那么如何知道 action 什么時候結束呢?更重要的是,我們如何才能組合多個 action,以處理更加復雜的異步流程?
第一件事你需要清楚的是 store.dispatch 的返回的是被觸發的 action 函數的返回值,因此你可以在 action 中返回 Promise:
actions: {actionA ({ commit }) {return new Promise((resolve, reject) => {setTimeout(() => {commit('someMutation')resolve()}, 1000)})} }現在你可以:
store.dispatch('actionA').then(() => {// ... })在另外一個 action 中也可以:
actions: {// ...actionB ({ dispatch, commit }) {return dispatch('actionA').then(() => {commit('someOtherMutation')})} }最后,如果我們利用 [async / await] 這個 JavaScript 即將到來的新特性,我們可以像這樣組合 action:
假設 getData() 和 getOtherData() 返回的是 Promise
Modules
使用單一狀態樹,導致應用的所有狀態集中到一個很大的對象。但是,當應用變得很大時,store 對象會變得臃腫不堪。
為了解決以上問題,Vuex 運行我們將 store 分割到多個模塊(module)。每個模塊擁有自己的 state、mutation、action、getters、甚至是嵌套子模塊——從上至下進行類似的分割:
const moduleA = {state: { ... },mutations: { ... },actions: { ... },getters: { ... } } onst moduleB = {state: { ... },mutations: { ... },actions: { ... } } const store = new Vuex.Store({modules: {a: moduleA,b: moduleB} })store.state.a // -> moduleA 的狀態 store.state.b // -> moduleB 的狀態模塊的局部狀態
對于模塊內部的 mutation 和 getter,接收的第一個參數是模塊的局部狀態。
const moduleA = {state: { count: 0 },mutations: {increment: (state) {// state 模塊的局部狀態state.count++}}, getters: {doubleCount (state) {return state.count * 2}} }同樣,對于模塊內部的 action,context.state 是局部狀態,根節點的狀態是 context.rootState:
const moduleA = {// ...actions: {incrementIfOdd ({ state, commit }) {if (state.count % 2 === 1) {commit('increment')}}} }對于模塊內部的 getter,根節點狀態會作為第三個參數:
const moduleA = {// ...getters: {sumWithRootCount (state, getters, rootState) {return state.count + rootState.count}} }07 項目結構
對于大型應用,我們會希望把 Vuex 相關代碼分割到模塊中。下面是項目結構示例:
├── index.html ├── main.js ├── api │ └── ... # 抽取出API請求 ├── components │ ├── App.vue │ └── ... └── store├── index.js # 我們組裝模塊并導出 store 的地方├── actions.js # 根級別的 action├── mutations.js # 根級別的 mutation└── modules├── cart.js # 購物車模塊└── products.js # 產品模塊08 vuex簡單應用實例
創建一個用來共享的存儲,在這個例子中它將通過 vue/vuex 注入到組件當中。
定義組件可以調用的 actions,它們仍然是集中定義的。
定義實際接觸存儲狀態的 mutations。我們這么做,actions 就可以形成不止一個 mutation,或者執行邏輯去決定調用哪一個 mutation。這意味著你再也不用擔心組件當中的業務邏輯了,成功!
當狀態更新時,任何擁有 getter,動態屬性和映射到 store 的組件都會被立即更新。
main.js
用 Vuex 創建了一個存儲并將其直接傳入應用程序當中
import Vue from 'vue' import App from './App.vue'import store from './vuex/store'new Vue({el: '#app',store,render: h => h(App) })store.js
export default new Vuex.Store({state: {messages: []},actions: {newMessage ({commit}, msg) {commit('NEW_MESSAGE', msg)}},mutations: {NEW_MESSAGE (state, msg) {state.messages.push(msg)}} })Client.vue
<template><div><h1>{{ clientid }}</h1><div><ul><li v-for="message in messages"><label>{{ message.sender }}:</label> {{ message.text }}</li></ul><div><input v-model="msg" placeholder="Enter a message, then hit [enter]" @keyup.enter="trySendMessage"></div></div></div> </template> <script>import { mapState, mapActions } from 'vuex'export default {data() {return {msg: ''}},props: ['clientid'],computed:{...mapState({messages: state => state.messages})},methods: {trySendMessage() {this.newMessage({text: this.msg,sender: this.clientid})this.resetMessage()},resetMessage() {this.msg = ''},...mapActions(['newMessage'])}} </script> <style> </style>App.vue
<div><client clientid="Client A"></client> </div> <div><client clientid="Client B"></client> </div> <script>import client from './components/Client.vue'import store from './vuex/store' export default {name: 'app',data () {return {msg: 'Welcome to Your Vue.js App'}},components:{client} } </script>
參考鏈接:
https://www.cnblogs.com/y896926473/articles/6709733.html
總結
以上是生活随笔為你收集整理的面试官:请你说一说vuex的五个属性,分别是什么,区别和用途说一下的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LintCode : 木材加工
- 下一篇: arcengin交互式动图制作