Vue 高級-Vuex

介紹

vuex是一種狀態(tài)管理模式,它保存著組件的公用的狀態(tài),并且以相應(yīng)的規(guī)則保證狀態(tài)變化。

vuex的核心就是一個store,它相當(dāng)于是一個容器,里面包含有state,action,mutation,getter,modules。

  • state:用于數(shù)據(jù)的存儲,是store中的唯一數(shù)據(jù)源

  • getters:如vue中的計(jì)算屬性一樣,基于state數(shù)據(jù)的二次包裝,常用于數(shù)據(jù)的篩選和多個數(shù)據(jù)的相關(guān)性計(jì)算

  • mutation:類似函數(shù),改變state數(shù)據(jù)的唯一途徑,且不能用于處理異步事件

  • action:類似于mutation,用于提交mutation來改變狀態(tài),而不直接變更狀態(tài),可以包含任意異步操作

  • modules:類似于命名空間,用于項(xiàng)目中將各個模塊的狀態(tài)分開定義和操作,便于維護(hù)

特點(diǎn)

  • Vuex 的狀態(tài)存儲是響應(yīng)式的。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時候,若 store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會相應(yīng)地得到高效更新。

  • 你不能直接改變 store 中的狀態(tài)。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態(tài)的變化,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用。

  • vuex是單一狀態(tài)樹

vuex的流程

image.png

vuex的整體流程是:

  1. 在組件內(nèi)部,通過dispatch來分發(fā)action。

  2. 再通過action來第調(diào)用mutation

  3. 進(jìn)而觸發(fā)mutation內(nèi)部的commit來修改state

  4. 最后state改變,導(dǎo)致頁面重新render。

使用

vuex的使用場景

  • 大型應(yīng)用中,用于全局共享的data,例如全局消息提醒、控件權(quán)限控制等等。

  • vuex可配合sessionStorage做用戶基本信息的持久化存儲。

  • 多級組件的數(shù)據(jù)需要共享或多個頁面之間的數(shù)據(jù)存在因果關(guān)系時,可以使用vuex。

在state中定義了count、userInfo、students三個屬性,state里面的數(shù)據(jù)狀態(tài)可以在全局中被訪問,在任意組件中通過this.$store.state.attrName訪問,在demo.vue的computed屬性里面,我們獲取了以上三個屬性

getter中可以自定義一些函數(shù)對state屬性里面的數(shù)據(jù)進(jìn)行過濾,并且在任意組件中可以通過this.$store.gettter.functionName的方式獲取

mutaions用來更新state里面的狀態(tài),我們可以定義一些方法對數(shù)據(jù)進(jìn)行操作,在里面的方法中至少有state和value兩個參數(shù),state就是上面所說的state對象(屬性),value就是從組件傳遞來的值??梢钥吹?,在demo.vue中點(diǎn)擊加號按鈕或者減號按鈕,通過this.$store.commit('getUserInfo',count的方式向vuex提交了一個事件,在store.js中mutaions里面的updateCount將提交過值接收并進(jìn)行處理,state里面的count狀態(tài)被更新,這是demo組件的computed屬性中的number被執(zhí)行,然后緊接著dom被更新。

actions也是對state狀態(tài)進(jìn)行更新,但是是間接的,一些異步的操作先交給actions里面的函數(shù)執(zhí)行,拿到結(jié)果后在交給mutaions中相應(yīng)的處理函數(shù)處理,接下來的操作就跟上面講的一樣。 點(diǎn)擊獲取用戶信息按鈕,通過this.$store.dispatch('getUserInfo',this)向vuex提交了一個事件,store.js中actions的getUserInfo函數(shù)處理了這個事件,向本地一個user.json文件發(fā)了一個異步請求,難道結(jié)果后將返回的用戶信息交給了mutaions的getUserInfo函數(shù)處理,state的userInfo屬性被改變,userInfo的變化導(dǎo)致demo.vue中computed屬性的userInfo被執(zhí)行,接著dom更新,用戶信息被顯示。

代碼如下:

// store/store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
    state:{
        count:0,
        userInfo:{},
        students:[]
    },
    getters:{
      
    },
    mutations:{
        updateCount(state,count){
            state.count = count
        },
        getUserInfo(state,userInfo){
            state.userInfo = userInfo
        },
        getStudents(state,students){
            state.students = students
        }
    },
    actions:{
        updateCountAsync({commit,state},count){
            setTimeout(function() {
                console.log('count:'+count)
                commit('updateCount',count)
            }, 1000);
        },
        getUserInfo({commit,state},_this){
            let _vm = _this
            console.log(_vm)
            _vm.$http.get('http://localhost:8080/static/data/user.json').then(res=>{
                console.log(res)
                commit('getUserInfo',res.data)
            })
        },
        getStudents({commit,state},_this){
            let _vm = _this
            _vm.$http.get('/api/students').then(res=>{
                console.log(res)
                commit('getStudents',res.data.data.students)
            })
        }
    }
})
// demo.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
      
    <div class="number-box" style="margin:20px 0;">
      <button @click="plus">加 一</button>
      <input type="text" v-model="number" style="padding-left:20px;">
      <button @click="minus">減 一</button>
    </div>

    <button @click="getUserInfo">獲取用戶信息</button>
    <div class="user-info" v-if="userInfo">
      <span class="name" >{{userInfo.name}}</span>
      <span class="gender" >{{userInfo.gender}}</span>
      <span class="age">{{userInfo.age}}</span>
    </div>
    
    <button @click="getStudentList">獲取成績榜單</button>
    <div v-if="students.length>0">
      <h4 >成績榜單</h4>
      <ul>
        <li v-for="item in students" :key="item.id">
          <span>{{item.name}}</span>
          <span>{{item.score}}</span>
        </li>
      </ul>
    </div>
  </div>
</template>

<style>

</style>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  mounted() {
    
  },
  computed:{
    number(){
      return this.$store.state.count
    },
    userInfo(){
      return this.$store.state.userInfo
    },
    students(){
      return this.$store.state.students
    }
  },
  methods:{
    plus(){
      // this.number++
      let count = Number(this.number)+1
      console.log('plus:'+count)
      this.$store.dispatch('updateCountAsync',count)
    },
    minus(){
      // this.number--
      let count = Number(this.number)-1
      console.log('minus:'+count)
      this.$store.dispatch('updateCountAsync',count)
    },
    getUserInfo(){
      this.$store.dispatch('getUserInfo',this)
    },
    getStudentList(){
      this.$store.dispatch('getStudents',this)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
.user-info{
  margin-top:20px;
  margin-bottom:20px;
}
.name{
  color:blue;margin-right:20px
}
.gender{
  color:red;margin-right:20px
}
.age{
  color:blue;margin-right:20px
}
</style>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容