admin管理员组

文章数量:1415697

I am trying to listen inside a vue ponent to a window property change, I am not sure this is possible.
The use is for a loader, baiscally I have a file which has an interceptor which alters the "loading" property on the window object (window.loading = true when request initiated, window.loading = false when request plete (or error)) (I have issues accessing my store inside the interceptor). The vue ponent looks like this:

<template> 
    <v-progress-linear   //this is the loader element
            height="20"
            v-show="loading"
    >
    </v-progress-linear>
    ...
    puted: { 
    loading(){
    return window.loading}
    }

I also tried this as a solution:

created () {
    window.addEventListener('loading', this.handleLoading);
  },
  destroyed () {
    window.removeEventListener('loading', this.handleLoading);
  },
  methods: {
    handleLoading(val){
      console.log(val)
    this.loading =  val
}
  },

The question is how can I listen on my window.loading

EDIT

Here is the file which contains the interceptor code, note this does not have access to the vue instance.

import axios from 'axios';
import { Utils } from 'em-mon-vue';

import {UsersApi} from "./usersApi";
import {PartnersApi} from "./partnersApi";
import {TrialsApi} from "./trialsApi";

export function apiFactory($security) {
    const $http = axios.create({
        baseURL: process.env.VUE_APP_API_URL
    });
    $http.interceptors.request.use(function (config) {
        window.loading = true
        const token = $security.loginFrame.getToken();

        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }

        return config;

    }, function (error) {
        window.loading = true
        Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
        window.loading = false
        return Promise.reject(error);
    }
);

    $http.interceptors.response.use(function (response) {
        window.loading = false
        return response;

    }, function (error) {
        if (error.response && error.response.status === 401) {

            Utils.EventBus.$emit('authErr', error);
        } else if (error.response && error.response.status === 403) {
            alert('You are not authorized to access this application. If you believe you are seeing this message in error, please contact [email protected].');
        }

        else if (error.response && error.response.status !== 409){
            Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
        }
        else if (error.response && error.response.status === 500){
            Utils.EventBus.$emit('toastMessageHandler', {message: 'There was a problem with this operation - please contact [email protected].', type: 'error'});
        }
        window.loading = false
        return Promise.reject({error});
    });

    const $api = {
        users: new UsersApi($http),
        partners: new PartnersApi($http),
        trials: new TrialsApi($http)
    };

    return $api;
}

// register $api as vue plugin
export function apiPluginFactory($api) {
    return {
        install(vue) {
            vue.prototype.$api = $api;
        },
    };
}

Here is the file which has factory function which creates the store:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

import {usersStoreFactory} from "./users/module";

// global
import {InitActions} from './actions';
import mutations from './mutations'
import getters from "./getters";

export function storeFactory($api, $config) {

    // global
    const actions  = InitActions($api);

    const store = new Vuex.Store({
        modules: {
            users: usersStoreFactory($api, $config),
        },
        state: {
            partners: null,
            // loading: window.loading
        },

        actions,
        mutations,
        getters
    });

    return store;
}

I am trying to listen inside a vue ponent to a window property change, I am not sure this is possible.
The use is for a loader, baiscally I have a file which has an interceptor which alters the "loading" property on the window object (window.loading = true when request initiated, window.loading = false when request plete (or error)) (I have issues accessing my store inside the interceptor). The vue ponent looks like this:

<template> 
    <v-progress-linear   //this is the loader element
            height="20"
            v-show="loading"
    >
    </v-progress-linear>
    ...
    puted: { 
    loading(){
    return window.loading}
    }

I also tried this as a solution:

created () {
    window.addEventListener('loading', this.handleLoading);
  },
  destroyed () {
    window.removeEventListener('loading', this.handleLoading);
  },
  methods: {
    handleLoading(val){
      console.log(val)
    this.loading =  val
}
  },

The question is how can I listen on my window.loading

EDIT

Here is the file which contains the interceptor code, note this does not have access to the vue instance.

import axios from 'axios';
import { Utils } from 'em-mon-vue';

import {UsersApi} from "./usersApi";
import {PartnersApi} from "./partnersApi";
import {TrialsApi} from "./trialsApi";

export function apiFactory($security) {
    const $http = axios.create({
        baseURL: process.env.VUE_APP_API_URL
    });
    $http.interceptors.request.use(function (config) {
        window.loading = true
        const token = $security.loginFrame.getToken();

        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }

        return config;

    }, function (error) {
        window.loading = true
        Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
        window.loading = false
        return Promise.reject(error);
    }
);

    $http.interceptors.response.use(function (response) {
        window.loading = false
        return response;

    }, function (error) {
        if (error.response && error.response.status === 401) {

            Utils.EventBus.$emit('authErr', error);
        } else if (error.response && error.response.status === 403) {
            alert('You are not authorized to access this application. If you believe you are seeing this message in error, please contact [email protected].');
        }

        else if (error.response && error.response.status !== 409){
            Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
        }
        else if (error.response && error.response.status === 500){
            Utils.EventBus.$emit('toastMessageHandler', {message: 'There was a problem with this operation - please contact [email protected].', type: 'error'});
        }
        window.loading = false
        return Promise.reject({error});
    });

    const $api = {
        users: new UsersApi($http),
        partners: new PartnersApi($http),
        trials: new TrialsApi($http)
    };

    return $api;
}

// register $api as vue plugin
export function apiPluginFactory($api) {
    return {
        install(vue) {
            vue.prototype.$api = $api;
        },
    };
}

Here is the file which has factory function which creates the store:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

import {usersStoreFactory} from "./users/module";

// global
import {InitActions} from './actions';
import mutations from './mutations'
import getters from "./getters";

export function storeFactory($api, $config) {

    // global
    const actions  = InitActions($api);

    const store = new Vuex.Store({
        modules: {
            users: usersStoreFactory($api, $config),
        },
        state: {
            partners: null,
            // loading: window.loading
        },

        actions,
        mutations,
        getters
    });

    return store;
}
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Aug 27, 2019 at 8:36 MichaelMichael 5,0588 gold badges37 silver badges59 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

I really don't think municating the loading state via window.loading is a good idea. Using something like the Vuex store or a similar singleton to hold the loading state seems like a much better approach but that has been (somewhat cryptically) ruled out in the question.

However, assuming that window.loading is the only option...

Defining a getter and setter for window.loading might be one way to get that approach to work. There are several ways that might be done but in my example I've chosen to proxy through to a Vue observable to hold the value.

const loadingMonitor = Vue.observable({
  loading: false
})

Object.defineProperty(window, 'loading', {
  get () {
    return loadingMonitor.loading
  },
  
  set (loading) {
    loadingMonitor.loading = loading
  }
})

new Vue({
  el: '#app',
  
  puted: { 
    loading () {
      return window.loading
    }
  },
  
  methods: {
    toggle () {
      window.loading = !window.loading
    }
  }
})
<script src="https://unpkg./[email protected]/dist/vue.js"></script>
<div id="app">
  <p>{{ loading }}</p>
  <button @click="toggle">Toggle</button>
</div>

Note that Vue.observable was added in Vue 2.6 so if you're using an older version you'd need to use the data of a new Vue instance to achieve the same effect.

As the value is held in an observable object it can take part in the reactivity system just like everything else. That allows it to be used in a puted property as a reactive dependency.

本文标签: javascriptlistening on a window property changeStack Overflow