监听窗口属性变化

Mic*_*ael 1 javascript window vue.js

我正在尝试在 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}
    }
Run Code Online (Sandbox Code Playgroud)

我也尝试过这个作为解决方案:

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

问题是我怎样才能听我的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;
        },
    };
}
Run Code Online (Sandbox Code Playgroud)

这是具有创建商店的工厂函数的文件:

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;
}
Run Code Online (Sandbox Code Playgroud)

ski*_*tle 7

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

然而,假设这window.loading是唯一的选择......

定义 getter 和 setterwindow.loading可能是使该方法发挥作用的一种方法。有多种方法可以完成,但在我的示例中,我选择代理到 Vue observable 来保存该值。

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

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

new Vue({
  el: '#app',
  
  computed: { 
    loading () {
      return window.loading
    }
  },
  
  methods: {
    toggle () {
      window.loading = !window.loading
    }
  }
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <p>{{ loading }}</p>
  <button @click="toggle">Toggle</button>
</div>
Run Code Online (Sandbox Code Playgroud)

请注意,这Vue.observable是在 Vue 2.6 中添加的,因此如果您使用旧版本,则需要使用data新的 Vue 实例来达到相同的效果。

由于该值保存在可观察对象中,因此它可以像其他所有东西一样参与反应系统。这允许它作为反应依赖项在计算属性中使用。