Vue: Доступ к DOM / шаблон из модуля? - PullRequest
0 голосов
/ 07 марта 2020

У меня есть Vue PWA с ServiceWorker. Когда ServiceWorker (registerServiceWorker. js) импортируется, он проверяет, доступна ли новая версия, и если да, то я хочу предоставить пользователю возможность обновления. Но в этот момент я нахожусь в модуле JavaScript, как я могу добавить всплывающее окно / сообщение + кнопку в документ HTML в этот момент?

В идеале я бы настроил свое сообщение заранее, используя закусочная Vuetify, или что-то подобное в приложении. vue или в навигационной панели. vue, которую я мог бы показать / скрыть на основе глобальной переменной, события или чего-то еще.

Однако есть усложняющий фактор: кнопка должна выполнить js -код на основе параметра ...

main. js (упрощенно):

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import vuetify from './plugins/vuetify'
import './registerServiceWorker'

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

Приложение. vue (упрощенно):

<template>
  <v-app>
    <Navbar/>
    <v-content>
      <router-view></router-view>
    </v-content>
    <Footer/>
  </v-app>
</template>

<script>
import styles from './app.css'
import Navbar from '@/components/Navbar'
import Footer from '@/components/Footer'

export default {
  name: 'App',
  components: { Navbar, Footer },
}
</script>

registerServiceWorker. js

function onNewServiceWorker(registration, callback) {
  if (registration.waiting) {
    // SW is waiting to activate. Can occur if multiple clients open and
    // one of the clients is refreshed.
    return callback();
  }

  function listenInstalledStateChange() {
    registration.installing.addEventListener('statechange', function(event) {
      if (event.target.state === 'installed') {
        // A new service worker is available, inform the user
        callback();
      }
    });
  };

  if (registration.installing) {
    return listenInstalledStateChange();
  }

  // We are currently controlled so a new SW may be found...
  // Add a listener in case a new SW is found,
  registration.addEventListener('updatefound', listenInstalledStateChange);
}

if (process.env.NODE_ENV === 'production') {

  window.addEventListener('load', function() {
    var refreshing
    // When the user asks to refresh the UI, we'll need to reload the window
    navigator.serviceWorker.addEventListener('controllerchange', function(event) {
      if (refreshing) return // prevent infinite refresh loop when you use "Update on Reload"
      refreshing = true
      console.log('Controller loaded')
      window.location.reload()
    })

    navigator.serviceWorker.register(`${process.env.BASE_URL}service-worker.js`,{})
    .then(function (registration) {
        // Track updates to the Service Worker.
      if (!navigator.serviceWorker.controller) {
        // The window client isn't currently controlled so it's a new service
        // worker that will activate immediately
        return
      }
      registration.update()
      onNewServiceWorker(registration, function() {
        //showRefreshUI(registration);
        console.log('TODO: show update message')
      })
    });
  });
}

Закомментированный showRefreshUI(registration) вызов - это то, что мне нужно иметь в моем шаблоне Vue, и здесь есть усложняющий фактор, он основан на параметре registration:

function showRefreshUI(registration) {
  var button = document.createElement('button');
  button.style.position = 'absolute';
  button.style.bottom = '24px';
  button.style.left = '24px';
  button.textContent = 'This site has updated. Please click here to see changes.';

  button.addEventListener('click', function() {
    if (!registration.waiting) {
      // Just to ensure registration.waiting is available before
      // calling postMessage()
      return;
    }

    button.disabled = true;

    registration.waiting.postMessage('skipWaiting');
  });

  document.body.appendChild(button);
};

К вашему сведению, регистрация ServiceWorker основана на:

Я только начинаю работать с Vue и PWA. Пожалуйста, потерпите меня здесь; -)

1 Ответ

0 голосов
/ 08 марта 2020

Вот рабочее решение для Vue. js.

App.vue; Добавьте v-лист с сообщением и кнопкой:

<template>
  <v-app>
    <Navbar/>
    <v-content>
      <router-view></router-view>
    </v-content>
    <v-sheet class="text-center" height="100px" id="update_banner" style="display:none">
      <div class="d-flex justify-center align-center" style="height:100%;">
          <span class="pr-6">We've made an update to this site, please click update to see the changes.</span>
          <v-btn
            id="update_btn"
            class="mr-4"
            color="primary"
          >Update</v-btn>
          <v-btn
            outlined
            color="primary"
            @click="closeBsh()"
          >Later</v-btn>
        </div>
    </v-sheet>
    <Footer/>
  </v-app>
</template>

<script>
import styles from './app.css'
import Navbar from '@/components/Navbar'
import Footer from '@/components/Footer'

export default {
  name: 'App',
  components: { Navbar, Footer },
  methods: {
    closeBsh() {
      document.getElementById("update_banner").style.display = "none"
    }
  },
}
</script>

Добавьте функцию showRefreshUI в registerServiceWorker.js; он делает две вещи: 1. добавляет прослушиватель onClick к существующей кнопке, определенной в приложении. vue 2. делает V-лист видимым

function showRefreshUI(registration) {
  // Q. could it be possible that the document isn't ready yet at this point??
  var vbutton = document.getElementById("update_btn")
  vbutton.addEventListener('click', function() {
    if (!registration.waiting) {
      // Just to ensure registration.waiting is available before
      // calling postMessage()
      return;
    }
    //vbutton.disabled = true; //?? needed?
    document.getElementById("update_banner").style.display = "none" // not really needed, as on refresh it will default back to none... probably.
    registration.waiting.postMessage('skipWaiting');
  });
  document.getElementById("update_banner").style.display = "block"
};

и раскомментирует вызов на showRefreshUI:

  onNewServiceWorker(registration, function() {
    showRefreshUI(registration);
  })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...