【问题标题】:Vue: Access the dom/template from a module?Vue:从模块访问 dom/模板?
【发布时间】:2020-06-20 02:32:48
【问题描述】:

我有一个带有 ServiceWorker 的 Vue PWA。导入 ServiceWorker (registerServiceWorker.js) 时,它会检查是否有新版本可用,如果有,我想向用户提供升级选项。但是那时我在一个 JavaScript 模块中,我如何在 HTML 文档上添加一个弹出/消息+按钮?

理想情况下,我会事先使用 Vuetify 快餐栏或 App.vue 或 Navbar.vue 上的类似东西设置我的消息,我可以根据全局变量或事件或其他东西显示/隐藏。

但是,有一个复杂的因素:按钮需要根据参数执行js-code...

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')

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。请在这里忍受我;-)

【问题讨论】:

    标签: javascript vue.js vuejs2


    【解决方案1】:

    这是一个适用于 Vue.js 的有效解决方案。

    App.vue;添加带有消息和按钮的 v-sheet:

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

    在 registerServiceWorker.js 中添加 showRefreshUI 函数;它做了两件事: 1.给app.vue中定义的现有按钮添加一个onClick监听器 2. 使 v-sheet 可见

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

    【讨论】:

      猜你喜欢
      • 2016-03-12
      • 2021-09-02
      • 2016-12-24
      • 2017-02-12
      • 2017-12-21
      • 2022-01-22
      • 2021-11-03
      • 1970-01-01
      • 2016-01-09
      相关资源
      最近更新 更多