vuex起步 (三、異步管理數(shù)據(jù))

異步管理數(shù)據(jù)就是有發(fā)請(qǐng)求,我們這里異步請(qǐng)求用axios,這個(gè)也是第三方的庫(kù),所以我們要在當(dāng)前項(xiàng)目yarn add axios或者npm i axios,然后再store.js文件里面導(dǎo)入

import axios from  'axios'

在來到組件文件里面的template組件這里添加一個(gè)事件觸發(fā)源

 <button @click="clickHandler">獲取電影</button>

然后再export default這里派發(fā)一個(gè)action

clickHandler: function () {
              // 獲取異步數(shù)據(jù)  希望通過倉(cāng)庫(kù)進(jìn)行 異步數(shù)據(jù)的管理
              this.$store.dispatch('getMovie'); // 派發(fā) action 。 同步:commit,異步 action

          }

然后異步請(qǐng)求不能在store.js的 mutations里面修改數(shù)據(jù)咯,要在const store = new Vuex.Store先加一個(gè)action

actions: {
        getMovie: function (store, payload) {
            var url = 'https://movie.52kfw.cn/index.php/Api/Movie/alst?page=1&size=20';

           

            axios.get(url).then(response => {
                console.log(response);
                if( response.status === 200 && response.data.error_code === 0 ){
                    // 把返回的數(shù)據(jù)交給倉(cāng)庫(kù)里面的 state 里面的 movieData
                    // response.data.result;
                    // 當(dāng)前 store 對(duì)象
                    store.commit('saveMovieData', response.data.result);

                }
            }).catch( error => {
                console.log(error);
            })

            console.log('getMovie');
        }
    },

如上里面也有 store.commit('saveMovieData', response.data.result);response.data.result就是要傳過去的payload值

因?yàn)榘逊祷氐臄?shù)據(jù)交給倉(cāng)庫(kù)里面的 state 里面的 movieData,所以事先要在state里面定義一下

 state: {
        count: 10, // 計(jì)數(shù)器的初始值
        movieData: [], // 電影數(shù)據(jù),稍后使用 api 獲取,異步請(qǐng)求
   
    },

還有mutations里面也要定義一個(gè)saveMovieData

 mutations: {
 saveMovieData: function (state, payload) {
            state.movieData = payload;
   
        },

最后將數(shù)據(jù)渲染在頁(yè)面就好了。

      <ul v-else v-for="ele in movieData">
            <li>序號(hào):{{ ele.id }}</li>
            <li>名稱:{{ ele.title }}</li>
            <li>收藏?cái)?shù):{{ ele.star }}</li>
        </ul>

注意,在mutations里面的state指的是


image.png

是這個(gè)state


image.png

然而這里的store
image.png

指的是所在當(dāng)前的整個(gè)實(shí)例對(duì)象store


image.png

同樣的這里也要考慮一下代碼優(yōu)化,

  • mutations和actions都可以做映射,
    在組件文件.vue里面
import {mapState, mapMutations, mapActions, } from 'vuex';

在.vue組件文件里面的export default里面的method只用寫

 methods: {
         
            ...mapActions({ clickHandler: 'getMovie' }),
             // clickHandler: function () {
            //     // 獲取異步數(shù)據(jù)  希望通過倉(cāng)庫(kù)進(jìn)行 異步數(shù)據(jù)的管理
            //     this.$store.dispatch('getMovie'); // 派發(fā) action 。 同步:commit,異步 action
            //
            // }
}

如果要做篩選的操作呢,比如挑取start的值為淺12萬的數(shù)據(jù),這時(shí)候要在倉(cāng)庫(kù)實(shí)例添加一個(gè)getters


image.png
 getters: {
        // 希望可以篩選出收藏?cái)?shù)據(jù)大于 12w 的電影 類似 vuejs 里面的計(jì)算屬性
        // 定義是一個(gè)方法,按照屬性方式使用,和計(jì)算屬性一樣
        returnStarBig12w: function (state) {
            console.log(state);
            // return state.movieData; // 過濾 filter

            return state.movieData.filter( item => {
                return item.star >= 120000;
            } );

        }
    }

在組件.vue那里直接渲染

 <ul v-for="ele in $store.getters.returnStarBig12w">
            <li>序號(hào):{{ ele.id }}</li>
            <li>名稱:{{ ele.title }}</li>
            <li>收藏?cái)?shù):{{ ele.star }}</li>
        </ul>

當(dāng)然給getter也有映射,在.vue文件里面改

import {mapState, mapMutations, mapActions, mapGetters} from 'vuex';
//在export default里面
methods: {
            ...mapMutations([ INCREMENT, DECREMENT]),

            ...mapActions({ clickHandler: 'getMovie' }),
            ...mapGetters(['returnStarBig12w'])
}

異步數(shù)據(jù)有可能網(wǎng)絡(luò)會(huì)卡頓,為了避免用戶在發(fā)網(wǎng)絡(luò)請(qǐng)求時(shí)候一直點(diǎn)擊,我們應(yīng)該用戶體驗(yàn)友好,加loading。
那要在用戶發(fā)送請(qǐng)求的action里面

const store = new Vuex.Store({
actions: {
        getMovie: function (store, payload) {
            var url = 'https://movie.52kfw.cn/index.php/Api/Movie/alst?page=1&size=20';

            // 網(wǎng)絡(luò)請(qǐng)求,完全可以做個(gè)內(nèi)存緩存,先去檢測(cè)倉(cāng)庫(kù)里面是否存在數(shù)據(jù),如果存在,則不發(fā)送網(wǎng)絡(luò)請(qǐng)求;不存在發(fā)送 后臺(tái),肯定上緩存 memcache  redis 內(nèi)存緩存 io 》》》 磁盤IO mysql
            if( store.state.movieData.length > 0 ){
                // 代表用戶之前肯定點(diǎn)擊獲取電影,發(fā)送過網(wǎng)絡(luò)請(qǐng)求
                console.log('數(shù)據(jù)來自緩存信息!');
                return;
            }
//則這里的請(qǐng)求只能發(fā)送一次

而在請(qǐng)求數(shù)據(jù)的這個(gè)過程中我們可以顯示loading效果,數(shù)據(jù)成功回來后loading效果:1. loading.gif 2. 插件 3. css3 loading 效果
這里隨便找一個(gè)css3把
把loading翻入到組件中

<div class="loading" v-if="flag">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
  </div>
 <ul v-else v-for="ele in movieData">
            <li>序號(hào):{{ ele.id }}</li>
            <li>名稱:{{ ele.title }}</li>
            <li>收藏?cái)?shù):{{ ele.star }}</li>
        </ul>
//樣式放在之后的style標(biāo)簽內(nèi)

注意上面的代碼我用了v-if和v-else,只能顯示一個(gè),是否顯示取決于狀態(tài)true還是false
接下來是修改狀態(tài),

注意:所有修改狀態(tài)都是commit,只不過是異步是在action里面commit,同步是在.vue里面直接commit。

定義狀態(tài)并初始flag

const store = new Vuex.Store({
    // 開啟 vuex 嚴(yán)格模式
    strict: true, // 默認(rèn)是false

    // 倉(cāng)庫(kù)里面的數(shù)據(jù)(之前說的模型數(shù)據(jù)),一般我們叫做 state 狀態(tài)
    state: {
        count: 10, // 計(jì)數(shù)器的初始值
        movieData: [], // 電影數(shù)據(jù),稍后使用 api 獲取,異步請(qǐng)求
        flag: false,

    },

在發(fā)送請(qǐng)求之前的action里面修改狀態(tài)

 actions: {
        getMovie: function (store, payload) {
            var url = 'https://movie.52kfw.cn/index.php/Api/Movie/alst?page=1&size=20';

            // 網(wǎng)絡(luò)請(qǐng)求,完全可以做個(gè)內(nèi)存緩存,先去檢測(cè)倉(cāng)庫(kù)里面是否存在數(shù)據(jù),如果存在,則不發(fā)送網(wǎng)絡(luò)請(qǐng)求;不存在發(fā)送 后臺(tái),肯定上緩存 memcache  redis 內(nèi)存緩存 io 》》》 磁盤IO mysql
            if( store.state.movieData.length > 0 ){
                // 代表用戶之前肯定點(diǎn)擊獲取電影,發(fā)送過網(wǎng)絡(luò)請(qǐng)求
                console.log('數(shù)據(jù)來自緩存信息!');
                return;
            }

            //由于網(wǎng)絡(luò)請(qǐng)求所耗費(fèi)的時(shí)間是不確定,意味用戶等待的時(shí)長(zhǎng)也是不確定,為了防止亂點(diǎn)擊,煩躁。一般在發(fā)送網(wǎng)絡(luò)請(qǐng)求后,會(huì)在頁(yè)面上出一個(gè) loading的效果。數(shù)據(jù)成功回來后,loading消失。
            // 1. loading.gif  2. 插件 3. css3 loading 效果

            store.commit('modifyFlag', true);

            axios.get(url).then(response => {

然后在處理status的mutations里面新增

  modifyFlag: function (state, payload) {
            state.flag = payload;
        }

然后發(fā)完網(wǎng)絡(luò)請(qǐng)求以后,在保存數(shù)據(jù)那里,就是表示發(fā)送成功,改變loading的狀態(tài)

 saveMovieData: function (state, payload) {
            state.movieData = payload;
            state.flag = false;
        },

將不顯示那個(gè)loading

  • 最后的常量的優(yōu)化
    定義一個(gè)常量文件


    常量.png

    比如將這些設(shè)為常量

export  const INCREMENT = 'increa'
export  const DECREMENT = 'decrea'

然后在vuex的store文件里面導(dǎo)入常量


image.png

將需要用到的地方替換即可

  //inCrement
        [INCREMENT]: function (state, payload) {
            console.log(payload);
            console.log(state);
            state.count += 1;
            // state.count += payload.number;
        },
        [DECREMENT]: function (state, payload) {
            state.count -= 1;
        },

在.vue組件文件里面同時(shí)也要

import {INCREMENT, DECREMENT} from './store/constant'
//需要用到的地方就可以
 ...mapMutations([ INCREMENT, DECREMENT]),
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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