1. 程式人生 > 實用技巧 >【Vue】Re19 VueX 第一部分(共享資料,Getters)

【Vue】Re19 VueX 第一部分(共享資料,Getters)

一、概述

專門為VueJS應用程式開發的狀態管理模式

集中式儲存管理應用的所有元件的狀態,按照相應的規則保證狀態以一種可預測的方式發生變化

VueX也整合到了官方除錯工具devtools extension中

狀態共享問題:

類似JavaWeb中的Session,每一個資源共同需要的變數

二、案例演示

首先需要安裝VueX,CLI2的安裝是沒有提供VueX的

npm install vuex --save

App.vue

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <
p> <button @click="$store.state.count --"> - </button> <span>{{$store.state.count}}</span> <button @click="$store.state.count ++"> + </button> </p> <vuex-comp></vuex-comp> </div> </template> <!-- Actions行為 + View檢視 + State狀態
--> <script> import VueXComp from "./components/VueX"; export default { name: 'App', data () { return { message : 'sss', // count : 0 } }, components : { vuexComp : VueXComp }, } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif
; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

VueX.vue

<template>
  <div>
    <h3>VueX Component</h3>
    <p>{{$store.state.count}}</p>
  </div>
</template>

<script>

export default {
  name: "VueX"

}
</script>

<style scoped>

</style>

store目錄的Index.js

import Vue from 'vue';
import VueX from 'vuex';

/* 安裝VueX */
Vue.use(VueX);

const store = new VueX.Store({
  state : { /* 狀態儲存,存放所有元件共享的物件 */
    count : 0
  },
  mutations : {

  },
  actions : {

  },
  modules : {

  }
});

export default store;

main.js引入VueX的初始化:

// 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 router from './router'
import Store from './store';

Vue.config.productionTip = false

// Vue.use(VueX);

/* eslint-disable no-new */

new Vue({
  el: '#app',
  router,
  store : Store,
  components: { App },
  template: '<App/>'
})

兩個元件是共用store中的state屬性的count

變數引用依靠$store

$store.state.定義的屬性

但是官方不推薦使用上面這樣的直接引用獲取

因為在devtools的除錯外掛中可以發現這樣的問題:

在介面中的點選,共享的count資料更新了,但是在除錯外掛中的vuex屬性狀態列中,

資料是沒有發生變化的。

使用mutations實現,並且可以被devtools跟蹤

至少使用先使用mutations呼叫,如果還有請求的操作,那還需要actions中呼叫

store/index.js

import Vue from 'vue';
import VueX from 'vuex';

/* 安裝VueX */
Vue.use(VueX);

const store = new VueX.Store({
  state : { /* 狀態儲存,存放所有元件共享的物件 */
    count : 0
  },
  mutations : { /*  */
    increment (state) {
      state.count ++
    },
    decrement (state) {
      state.count --
    }
  },
  actions : {

  },
  modules : {

  }
});

export default store;

首頁App.vue

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <p>
<!--      <button @click="$store.state.count &#45;&#45;"> - </button>-->
      <button @click="aaa"> - </button>
      <span>{{$store.state.count}}</span>
      <button @click="bbb"> + </button>
<!--      <button @click="$store.state.count ++"> + </button>-->
    </p>
    <vuex-comp></vuex-comp>
  </div>
</template>
<!-- Actions行為 + View檢視 + State狀態 -->
<script>
import VueXComp from "./components/VueX";
export default {
  name: 'App',
  data () {
    return {
      message : 'sss',
      // count : 0
    }
  },
  methods : {
    aaa () {
      this.$store.commit('decrement');
    },
    bbb () {
      this.$store.commit('increment');
    }
  },
  components : {
    vuexComp : VueXComp
  },

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

修改預覽的效果可以跟蹤Mutations的方法執行

但是state變數不知道為什麼對不上值:

三、使用Getters計算複雜的需求

現在Store中多了一組學生資訊,需求是獲取某一屬性的某一範圍的所有學生資訊

例如年齡大於20或者小於20

store/index.js

import Vue from 'vue';
import VueX from 'vuex';

/* 安裝VueX */
Vue.use(VueX);

const store = new VueX.Store({
  state : { /* 狀態儲存,存放所有元件共享的物件 */
    count : 0,
    str : 'sss',
    students : [
      { id : 110, name : '學生110', age : 28, gender : true, },
      { id : 111, name : '學生111', age : 18, gender : true, },
      { id : 112, name : '學生112', age : 38, gender : false, },
      { id : 113, name : '學生113', age : 14, gender : true, },
      { id : 114, name : '學生114', age : 44, gender : false, },
      { id : 115, name : '學生115', age : 10, gender : true, },
    ]
  },
  mutations : { /*  */
    increment (state) {
      state.count ++
    },
    decrement (state) {
      state.count --
    },
  },
  actions : {

  },
  modules : {

  },
  getters : {
    getStringJoin (state) {
      return state.str + 'saa';
    },
    getCount (state) {
      return state.count;
    },
    large20Age (state) {
      return state.students.filter(student => student.age > 20);
    }
  }
});

export default store;

App.vue

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <p>
<!--      <button @click="$store.state.count &#45;&#45;"> - </button>-->
      <button @click="aaa"> - </button>
      <!--<span>{{$store.state.count}}</span>-->
      <strong>{{$store.getters.getCount}}</strong>
      <button @click="bbb"> + </button>
<!--      <button @click="$store.state.count ++"> + </button>-->
    </p>

    <ul> <!-- 使用store的getters屬性呼叫 -->
      <li v-for="student in $store.getters.large20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <ul> <!-- 使用當前元件computed屬性呼叫 -->
      <li v-for="student in largeThan20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <p>
      {{$store.getters.getStringJoin}}
    </p>
    <vuex-comp></vuex-comp>
  </div>
</template>
<!-- Actions行為 + View檢視 + State狀態 -->
<script>
import VueXComp from "./components/VueX";
export default {
  name: 'App',
  data () {
    return {
      message : 'sss',
      // count : 0
    }
  },
  methods : {
    aaa () {
      this.$store.commit('decrement');
    },
    bbb () {
      this.$store.commit('increment');
    }
  },
  computed : {
    // largeThan20Age () {
    //   return this.$store.state.students.filter(student => {
    //     return student.age >= 20;
    //   });
    // }

    largeThan20Age () {
      return this.$store.state.students.filter(student => student.age >= 20);
    }

  },
  components : {
    vuexComp : VueXComp
  },

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

getters屬性支援內嵌式呼叫,提高了其他getters方法的可重用性

  getters : {
    getStringJoin (state) {
      return state.str + 'saa';
    },
    getCount (state) {
      return state.count;
    },
    large20Age (state) {
      return state.students.filter(student => student.age > 20);
    },
    large20AgeLength (state, getters) {
      return getters.large20Age.length;
    }
  }

年齡限制條件交給引數決定,更靈活的需求:

getters方法無法自定義我們希望的引數【已經固定了引數格式,第一state、第二getters】

解決方案是先返回一個函式,在這個函式的形參就可以獲取了,然後裡面再寫需求邏輯

    largeAgeBy (state) {
      return age => {
        return state.students.filter(student => student.age > age);
      }
    }

App.vue呼叫

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <p>
<!--      <button @click="$store.state.count &#45;&#45;"> - </button>-->
      <button @click="aaa"> - </button>
      <!--<span>{{$store.state.count}}</span>-->
      <strong>{{$store.getters.getCount}}</strong>
      <button @click="bbb"> + </button>
<!--      <button @click="$store.state.count ++"> + </button>-->
    </p>

    <ul> <!-- 使用store的getters屬性呼叫 -->
      <li v-for="student in $store.getters.large20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <ul> <!-- 使用當前元件computed屬性呼叫 -->
      <li v-for="student in largeThan20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <p>{{$store.getters.large20AgeLength}}</p>

    <p>
      {{$store.getters.getStringJoin}}
    </p>

    <ul>
      <li v-for="student in $store.getters.largeAgeBy(0)">
        {{student.id}} {{student.name}} {{student.age}} {{student.gender}}
      </li>
    </ul>

    <vuex-comp></vuex-comp>
  </div>
</template>
<!-- Actions行為 + View檢視 + State狀態 -->
<script>
import VueXComp from "./components/VueX";
export default {
  name: 'App',
  data () {
    return {
      message : 'sss',
      // count : 0
    }
  },
  methods : {
    aaa () {
      this.$store.commit('decrement');
    },
    bbb () {
      this.$store.commit('increment');
    }
  },
  computed : {
    // largeThan20Age () {
    //   return this.$store.state.students.filter(student => {
    //     return student.age >= 20;
    //   });
    // }

    largeThan20Age () {
      return this.$store.state.students.filter(student => student.age >= 20);
    }

  },
  components : {
    vuexComp : VueXComp
  },

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>