異步管理數據就是有發請求,我們這里異步請求用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
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文件里面導入常量
將需要用到的地方替換即可
//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]),