Open yangkaiyangyi opened 5 years ago
先来张目录结构
1、准备好你想表达的loading界面,这里我就简单的用文字表示,你可以随意发挥。conponents文件下新建Loading.vue
- <template>
- <div id="loading">
- 加载中,请稍后...
- </div>
- </template>
2、引入App.vue
import Loading from './components/Loading.vue'
- components:{
- Loading
- },
<Loading v-show="showLoading"></Loading>
Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。store(仓库)是 Vuex 应用的核心。"store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state)。更多专业详情参考https://vuex.vuejs.org/zh-cn/intro.html
首先,在components同级目录下新建文件夹store,内部包含文件store.js, actions.js,mutations.js还有type.js
store.js
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- import actions from './actions.js'
- import mutations from './mutations.js'
-
- Vue.use(Vuex)
- export default new Vuex.Store({
- modules:{
- mutations
- },
- actions
- })
actions.js
- import * as types from './type.js'
-
- export default{
- showloader:({ commit }) => {
- commit( types.SHOWLOADING )
- },
- hideloader:({ commit }) => {
- commit( types.HIDELOADING )
- },
- }
mutations.js
- import { SHOWLOADING,HIDELOADING } from './type.js'
-
- const state = {
- showLoading:false
- }
-
- const mutations = {
- [SHOWLOADING](state){
- state.showLoading = true;
- },
- [HIDELOADING](state){
- state.showLoading = false;
- }
- }
-
- const getters = {
- showLoading(state){
- return state.showLoading
- }
- }
-
- export default {
- state,mutations,getters
- }
type.js
- export const SHOWLOADING = 'SHOWLOADING';
- export const HIDELOADING = 'HIDELOADING';
刚开始写会觉得麻烦,,但是当你的state需求量增加时,就很方便了,直接按部就班的复制就好。
4、完善一下main.js,配置请求
- import Vue from 'vue'
- import VueRouter from 'vue-router'
- import axios from 'axios'
- import App from './App.vue'
- import routes from './router.js'
- import stores from './store/store.js'
-
- Vue.use(VueRouter)
- const router = new VueRouter({
- routes
- })
-
- Vue.prototype.$http = axios;
- axios.interceptors.request.use(function(config){
- stores.dispatch('showloader')
- return config
- },function(err){
- return Promise.reject(err)
- });
- axios.interceptors.response.use(function(response){
- stores.dispatch('hideloader')
- return response
- },function(err){
- return Promise.reject(err)
- });
-
- new Vue({
- el: '#app',
- router,
- store:stores,
- render: h => h(App)
- })
-
</div>
也可以通过vuex+vue-router的钩子函数,在跳转成功之前loading为true,在跳转成功之后为false
import Vue from 'vue'
import Router from 'vue-router'
import store from '../store/index'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
const routes = [ { path: '/', name: 'HelloWorld', component: HelloWorld } ]
// 实例化路由 const router = new Router({ routes })
// 路由跳转前的钩子 router.beforeEach(function (to, from, next) { store.commit('updateLoadingStatus', {isLoading: true}) next() })
// 路由跳转后的钩子 router.afterEach(function (to) { store.commit('updateLoadingStatus', {isLoading: false}) })
在vue项目中自定义组件实现异步请求数据,在获取到数据之前有一个loading的动态图,使界面更友好
在这里定义一个loading组件:
loading.vue:
- <template>
- <div class="loading-img">
- <img src="../../assets/loading.gif" alt="">
- </div>
- </template>
-
- <script>
- export default {
- name:'loading'
- }
- </script>
-
- <style lang="less" scoped>
- .loading-img{
- position: absolute;
- left: 0;
- right: 0;
- bottom: 0;
- top: 0;
- width: 100px;
- height: 100px;
- margin: auto;
- img{
- width: 100px;
- height: 100px;
- }
-
- }
- </style>
在home页面使用:
- <template>
- <div>
- <h1>home</h1>
- <Loading class="loading" v-if="loading"></Loading>
- </div>
-
- </template>
-
- <script>
- import Loading from '../components/loading.vue'
- import {mapState} from 'vuex'
- export default {
- name: 'home',
- data(){
- return {
- isLoading: false
- }
- },
- beforeCreate(){
- document.querySelector('body').setAttribute('style', 'background-color:#fff')
- },
- beforeDestroy(){
- document.querySelector('body').removeAttribute('style')
- },
- mounted(){
- this.$store.state.loading = true
- this.$store.dispatch('getNews')
- },
- components:{Loading},
- computed:{
- ...mapState([
- 'loading'
- ])
- }
- }
- </script>
-
- <style lang="less" scoped>
- body{
- background: red;
- position: relative;
- }
- </style>
-
-
store.js:
- import Vuex from 'vuex'
- import Vue from 'vue'
- import axios from 'axios'
-
- Vue.use(Vuex)
-
- export const store = new Vuex.Store({
- state:{
- newsList: [],
- loading: false
- },
- mutations:{
- setNews(state,{newsList}){
- state.newsList = newsList
- }
- },
- actions: {
- getNews(store){
- setTimeout(()=>{
- axios.get('/109-35'+'?showapi_appid=73783&showapi_sign=c870408835214a0eacca959aba6f317f').then(res=>{
- store.state.loading = false //请求到数据后,loading图消失
-
- })
- },2000)
-
- }
- }
- })
原理:
在vuex中使用一个loading变量来记录动态图的状态,通过开始请求数据和请求到数据这两种状态的改变,来控制动态图的显示与否
vue axios 请求loading 1.在src文件夹里面找到main.js文件
2.在main.js中引入axios,引入mint-ui
import Axios from 'axios';
import Mint from 'mint-ui';
Vue.use(Mint);
3.发起请求,打开loading
//请求拦截器
Axios.interceptors.request.use((config) => {
Mint.Indicator.open({//打开loading
text: '加载中...',
spinnerType: 'fading-circle'
});
return config;
}, (err) => {
return Promise.reject(err)
})
4.响应回来关闭loading
//响应拦截器
Axios.interceptors.response.use((response) => {
Mint.Indicator.close();//关闭loading
return response;
}, (err) => {
return Promise.reject(err);
})
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
准备 利用vue-cli脚手架创建项目 进入项目安装vuex、axios(npm install vuex,npm install axios) axios配置 项目中安装axios模块(npm install axios)完成后,进行以下配置:
main.js
//引入axios import Axios from 'axios'
//修改原型链,全局使用axios,这样之后可在每个组件的methods中调用$axios命令完成数据请求 Vue.prototype.$axios=Axios loading组件 我这里就选择使用iview提供的loading组件,
npm install iview
main.js import iView from 'iview'; import 'iview/dist/styles/iview.css'; Vue.use(iView); 安装引入后,将loading写成一个组件loading.vue
Vuex state状态设置控制loading的显隐
store.js(Vuex)
export const store = new Vuex.Store({
state:{
isShow:false
}
})
在state中定义isShow属性,默认false隐藏
v-if="this.$store.state.isShow" 为loading组件添加v-if绑定state中的isShow
组件使用axios请求数据
<button @click="getData">请求数据</button>
methods:{
getData(){
this.$axios.get('https://www.apiopen.top/journalismApi')
.then(res=>{
console.log(this.mydata)//返回请求的结果
})
.catch(err=>{
console.log(err)
})
}
}
我这里使用一个按钮进行触发事件,利用get请求网上随便找的一个api接口,.then中返回请求的整个结果(不仅仅包括数据)
Axios拦截器配置 main.js
//定义一个请求拦截器
Axios.interceptors.request.use(function(config){
store.state.isShow=true; //在请求发出之前进行一些操作
return config
})
//定义一个响应拦截器
Axios.interceptors.response.use(function(config){
store.state.isShow=false;//在这里对返回的数据进行处理
return config
})
分别定义一个请求拦截器(请求开始时执行某些操作)、响应拦截器(接受到数据后执行某些操作),之间分别设置拦截时执行的操作,改变state内isShow的布尔值从而控制loading组件在触发请求数据开始时显示loading,返回数据时隐藏loading 特别注意:这里有一个语法坑(我可是来来回回踩了不少次)main.js中调取、操作vuex state中的数据不同于组件中的this.$store.state,而是直接store.state 同上面代码
效果展示
axios 实现loading加载提示 思路其实很简单,可自己却想了很久,是太纠结原生的判断了吧TT
使用拦截器就可以了,请求拦截,和响应拦截。其实思考一下。
0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法。 1 (载入):已经调用open() 方法,但尚未发送请求。 2 (载入完成): 请求已经发送完成。 3 (交互):可以接收到部分响应数据。 4 (完成):已经接收到了全部数据,并且连接已经关闭。 // 请求的地方设置成true axios.interceptors.request.use(function () { store.isLoading = true
})
// 响应的地方设置成false axios.interceptors.response.use(function () { store.isLoading = fasle
})
在项目中,一般是在数据载入前,常常会使用 loding 过渡数据的加载时间。
1.自定义loading组件,一般loading组件作为一个全局的加载状态,建议写在App.vue 中。 这个Loading 组件通过 loading的状态显示隐藏。我们希望在请求某个接口的时候,将 loading 改为true,当接口请求后改为false,这样就能实现loading的过渡效果了。
其中:vuex状态管理器作用于全局,在state中定义存储loading的布尔值,其中loading的布尔值的改变随请求的改变而变,一般是在封装的ajax/axios中请求改变;
app.vue
这里的fetchLoading是存在vuex里面的一个变量。在store状态管理器中里需要如下定义: / 此js文件用于存储公用的vuex状态 /
loading组件如下:
最后在fetch/api.js里封装的axios里写入判断loading事件即可:如下
原文