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

異步管理數據就是有發請求,我們這里異步請求用axios,這個也是第三方的庫,所以我們要在當前項目yarn add axios或者npm i axios,然后再store.js文件里面導入

import axios from  'axios'

在來到組件文件里面的template組件這里添加一個事件觸發源

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

然后再export default這里派發一個action

clickHandler: function () {
              // 獲取異步數據  希望通過倉庫進行 異步數據的管理
              this.$store.dispatch('getMovie'); // 派發 action 。 同步:commit,異步 action

          }

然后異步請求不能在store.js的 mutations里面修改數據咯,要在const store = new Vuex.Store先加一個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 ){
                    // 把返回的數據交給倉庫里面的 state 里面的 movieData
                    // response.data.result;
                    // 當前 store 對象
                    store.commit('saveMovieData', response.data.result);

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

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

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

因為把返回的數據交給倉庫里面的 state 里面的 movieData,所以事先要在state里面定義一下

 state: {
        count: 10, // 計數器的初始值
        movieData: [], // 電影數據,稍后使用 api 獲取,異步請求
   
    },

還有mutations里面也要定義一個saveMovieData

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

最后將數據渲染在頁面就好了。

      <ul v-else v-for="ele in movieData">
            <li>序號:{{ ele.id }}</li>
            <li>名稱:{{ ele.title }}</li>
            <li>收藏數:{{ ele.star }}</li>
        </ul>

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


image.png

是這個state


image.png

然而這里的store
image.png

指的是所在當前的整個實例對象store


image.png

同樣的這里也要考慮一下代碼優化,

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

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

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

如果要做篩選的操作呢,比如挑取start的值為淺12萬的數據,這時候要在倉庫實例添加一個getters


image.png
 getters: {
        // 希望可以篩選出收藏數據大于 12w 的電影 類似 vuejs 里面的計算屬性
        // 定義是一個方法,按照屬性方式使用,和計算屬性一樣
        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>序號:{{ ele.id }}</li>
            <li>名稱:{{ ele.title }}</li>
            <li>收藏數:{{ ele.star }}</li>
        </ul>

當然給getter也有映射,在.vue文件里面改

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

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

異步數據有可能網絡會卡頓,為了避免用戶在發網絡請求時候一直點擊,我們應該用戶體驗友好,加loading。
那要在用戶發送請求的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';

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

而在請求數據的這個過程中我們可以顯示loading效果,數據成功回來后loading效果:1. loading.gif 2. 插件 3. css3 loading 效果
這里隨便找一個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>序號:{{ ele.id }}</li>
            <li>名稱:{{ ele.title }}</li>
            <li>收藏數:{{ ele.star }}</li>
        </ul>
//樣式放在之后的style標簽內

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

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

定義狀態并初始flag

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

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

    },

在發送請求之前的action里面修改狀態

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

            // 網絡請求,完全可以做個內存緩存,先去檢測倉庫里面是否存在數據,如果存在,則不發送網絡請求;不存在發送 后臺,肯定上緩存 memcache  redis 內存緩存 io 》》》 磁盤IO mysql
            if( store.state.movieData.length > 0 ){
                // 代表用戶之前肯定點擊獲取電影,發送過網絡請求
                console.log('數據來自緩存信息!');
                return;
            }

            //由于網絡請求所耗費的時間是不確定,意味用戶等待的時長也是不確定,為了防止亂點擊,煩躁。一般在發送網絡請求后,會在頁面上出一個 loading的效果。數據成功回來后,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;
        }

然后發完網絡請求以后,在保存數據那里,就是表示發送成功,改變loading的狀態

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

將不顯示那個loading

  • 最后的常量的優化
    定義一個常量文件


    常量.png

    比如將這些設為常量

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

然后在vuex的store文件里面導入常量


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組件文件里面同時也要

import {INCREMENT, DECREMENT} from './store/constant'
//需要用到的地方就可以
 ...mapMutations([ INCREMENT, DECREMENT]),
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容