Javascript 侦听窗口属性更改

Javascript 侦听窗口属性更改,javascript,vue.js,window,Javascript,Vue.js,Window,我正在尝试在vue组件内部侦听窗口属性更改,我不确定这是否可行。 该用法用于加载程序,实际上我有一个文件,其中包含一个拦截器,该拦截器可更改窗口对象的“加载”属性(window.loading=true请求启动时,window.loading=false请求完成时(或错误))(我在访问拦截器内的存储时遇到问题)。 vue组件如下所示: <template> <v-progress-linear //this is the loader element

我正在尝试在vue组件内部侦听窗口属性更改,我不确定这是否可行。
该用法用于加载程序,实际上我有一个文件,其中包含一个拦截器,该拦截器可更改窗口对象的“加载”属性(
window.loading=true
请求启动时,
window.loading=false
请求完成时(或错误))(我在访问拦截器内的存储时遇到问题)。 vue组件如下所示:

<template> 
    <v-progress-linear   //this is the loader element
            height="20"
            v-show="loading"
    >
    </v-progress-linear>
    ...
    computed: { 
    loading(){
    return window.loading}
    }
问题是如何在我的
窗口中进行监听。加载

编辑 这是包含拦截器代码的文件,请注意,该文件无权访问vue实例

import axios from 'axios';
import { Utils } from 'em-common-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 support@emergingmed.com.');
        }

        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 support@emergingmed.com.', 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;
        },
    };
}
以下是具有创建存储的factory函数的文件:

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;
}

我真的不认为通过
窗口传递加载状态。加载
是个好主意。使用类似Vuex存储或类似的单例来保存加载状态似乎是一种更好的方法,但在这个问题中(有些神秘地)已经排除了这一点

但是,假设
窗口。加载
是唯一的选项

窗口定义一个getter和setter。加载
可能是使该方法起作用的一种方法。有几种方法可以实现,但在我的示例中,我选择通过代理到Vue observable来保存值

const loadingMonitor=Vue.observable({
加载:错误
})
Object.defineProperty(窗口“加载”{
得到(){
返回loadingMonitor.loading
},
设置(加载){
loadingMonitor.loading=正在加载
}
})
新Vue({
el:“#应用程序”,
计算:{
加载(){
返回窗口。正在加载
}
},
方法:{
切换(){
window.loading=!window.loading
}
}
})

{{loading}}

切换
感谢您的详细回答,有几个问题/要点:1)由于应用程序的引导方式,我无法使用应用商店,我在上面添加了代码,基本上所有内容都是使用工厂功能创建的,因此我无法从拦截器文件内访问应用商店。2) 您的解决方案是否允许设置
窗口。从vue组件外部加载
属性时,我需要在拦截器文件中设置它?3) 你为什么说这是不推荐的?Thanks@Michael我提供的代码允许您设置
窗口。从可以访问
窗口
对象的任何位置加载
。您需要确保在尝试使用getter和setter之前,尽早创建getter和setter。除了污染全局名称空间之外,您还有多种选择。通过快速浏览您发布的额外代码,我可以看到两位候选人。一种是使用事件总线。第二个是将加载属性放在
$api
上。我最初的印象是你们的架构太复杂了,虽然我显然不知道是什么推动了它,所以我不能确定。真的学到了很多谢谢!我很好奇为什么选择使用
Object.defineProperty
,而不是简单地通过写入
window.loading=loadingMonitor.loading
?Michael没有什么可以保持
window.loading
loadingMonitor.loading
同步的。初始值应该是正确的,但随后您又回到了使用
窗口开始的位置。加载
时,会出现无法在Vue中跟踪的值。
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;
}