通知 App.vue 正在调用 Service-Worker 事件

Inform App.vue a Service-Worker Event is Being Called

我有一个使用 Vue CLI 3 创建的项目,其中包含 Vue 的 PWA 插件。我想显示一个横幅,提示用户点击应用内“刷新”link,如 'Approach #3' 部分所述 here

但是在我的 Vue.js 应用程序中,因为 service-worker 代码是在 main.js 中执行的,而我的小吃店横幅是内置在我的 App.vue 组件中的,所以我不确定如何在调用 service-worker updated() 事件后触发我的 showRefreshUI() 方法。

main.js(适用部分)

import Vue from 'vue';
import App from './App';
import './registerServiceWorker';

new Vue({
  router,
  render: h => h(App),
}).$mount('#app');

register-service-worker(适用部分)

import { register } from 'register-service-worker';

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    updated (registration) {
      console.log('New content is available; please refresh.');
      // I'd like to call App.vue's showRefreshUI() method from here.
    },
  });
}

App.vue(适用部分)

<script>
export default {
  name: 'App',
  mounted () {
    // Alternatively, I'd like to call this.showRefreshUI() from here
    // when the service worker's updated() method is called.
  },

  methods: {
    showRefreshUI () {
      // My code to show the refresh UI banner/snackbar goes here.
    },
  },
};
</script>

如果我无法从 main.js 调用 showRefreshUI() 方法,我如何将 updated() 事件中的内容传递给 App.vuemounted() 生命周期钩子来完成同样的基本事情?

我不确定,但我认为您可以为此目的使用 custom event。这样的东西可能对你有用..

1) 在您的 main.js..

中创建自定义事件

main.js

import Vue from 'vue';
import App from './App';
import './registerServiceWorker';

const updateEvent = new Event('SWUpdated');

new Vue({
  router,
  render: h => h(App),
}).$mount('#app');

2) 当 service worker 更新时调度自定义事件..

register-service-worker

import { register } from 'register-service-worker';

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    updated (registration) {
      console.log('New content is available; please refresh.');
      document.dispatchEvent(updateEvent);
    },
  });
}

3) 将事件侦听器附加到 mounted 挂钩中的文档对象,以侦听自定义事件。移除beforeDestroy钩子中的事件监听器..

App.vue

<script>
export default {
  name: 'App',
  mounted () {
    document.addEventListener('SWUpdated', this.showRefreshUI);
  },
  beforeDestroy () {
    document.removeEventListener('SWUpdated', this.showRefreshUI);
  },
  methods: {
    showRefreshUI () {
      // My code to show the refresh UI banner/snackbar goes here.
    },
  },
};
</script>

对我来说最终可行的解决方案是保持 main.js 不变,而是:

register-service-worker(适用部分)

import { register } from 'register-service-worker';

const UpdatedEvent = new CustomEvent('swUpdated', { detail: null });

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    updated (registration) {
      console.log('New content is available; please refresh.');
      UpdatedEvent.detail = registration;
      document.dispatchEvent(UpdatedEvent);
    },
  });
}

App.vue(适用部分)

<script>
export default {
  name: 'App',
  data () {
    return {
      registration: null,
    };
  },
  mounted () {
    document.addEventListener('swUpdated', this.showRefreshUI);
  },
  beforeDestroy () {
    document.removeEventListener('swUpdated', this.showRefreshUI);
  },
  methods: {
    showRefreshUI (e) {
      this.registration = e.detail;
      // My code to show the refresh UI banner/snackbar goes here.
    },
  },
};
</script>