最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端vue2中直接拉起vnc客戶端實(shí)現(xiàn)方式

 更新時(shí)間:2025年08月20日 11:18:21   作者:隱含  
本文介紹Vue項(xiàng)目中協(xié)議檢測(cè)工具類與組件的實(shí)現(xiàn),通過(guò)封裝檢測(cè)邏輯提升復(fù)用性,并展示如何在組件中應(yīng)用工具類進(jìn)行協(xié)議校驗(yàn)與數(shù)據(jù)展示

前端vue2中直接拉起vnc客戶端

協(xié)議檢測(cè)工具類

(src/utils/protocolCheck.js)

//1. 協(xié)議檢測(cè)工具類 (src/utils/protocolCheck.js)
//javascript
// 瀏覽器檢測(cè)函數(shù)
function checkBrowser() {
  const isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
  const ua = navigator.userAgent.toLowerCase();
  return {
    isOpera: isOpera,
    isFirefox: typeof InstallTrigger !== 'undefined',
    isSafari: (~ua.indexOf('safari') && !~ua.indexOf('chrome')) || 
              Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0,
    isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream,
    isChrome: !!window.chrome && !isOpera,
    isIE: /*@cc_on!@*/false || !!document.documentMode
  }
}

// IE版本檢測(cè)
function getInternetExplorerVersion() {
  let rv = -1;
  if (navigator.appName === 'Microsoft Internet Explorer') {
    const ua = navigator.userAgent;
    const re = new RegExp('MSIE ([0-9]{1,}[\.0-9]{0,})');
    if (re.exec(ua) != null) rv = parseFloat(RegExp.$1);
  } else if (navigator.appName === 'Netscape') {
    const ua = navigator.userAgent;
    const re = new RegExp('Trident/.*rv:([0-9]{1,}[\.0-9]{0,})');
    if (re.exec(ua) != null) rv = parseFloat(RegExp.$1);
  }
  return rv;
}

// 事件注冊(cè)輔助函數(shù)
function _registerEvent(target, eventType, cb) {
  if (target.addEventListener) {
    target.addEventListener(eventType, cb);
    return {
      remove: function() {
        target.removeEventListener(eventType, cb);
      }
    };
  } else {
    target.attachEvent('on' + eventType, cb);
    return {
      remove: function() {
        target.detachEvent('on' + eventType, cb);
      }
    };
  }
}

// 創(chuàng)建隱藏iframe
function _createHiddenIframe(target, uri) {
  const iframe = document.createElement('iframe');
  iframe.src = uri;
  iframe.id = 'hiddenIframe';
  iframe.style.display = 'none';
  target.appendChild(iframe);
  return iframe;
}

// 各種瀏覽器處理函數(shù)
function openUriWithHiddenFrame(uri, failCb, successCb) {
  const timeout = setTimeout(function() {
    failCb();
    handler.remove();
  }, 1000);

  let iframe = document.querySelector('#hiddenIframe');
  if (!iframe) {
    iframe = _createHiddenIframe(document.body, 'about:blank');
  }

  const handler = _registerEvent(window, 'blur', onBlur);

  function onBlur() {
    clearTimeout(timeout);
    handler.remove();
    successCb();
  }

  iframe.contentWindow.location.href = uri;
}

function openUriWithTimeoutHack(uri, failCb, successCb) {
  const timeout = setTimeout(function() {
    failCb();
    handler.remove();
  }, 1000);

  let target = window;
  while (target != target.parent) {
    target = target.parent;
  }

  const handler = _registerEvent(target, 'blur', onBlur);

  function onBlur() {
    clearTimeout(timeout);
    handler.remove();
    successCb();
  }

  window.location = uri;
}

function openUriUsingFirefox(uri, failCb, successCb) {
  let iframe = document.querySelector('#hiddenIframe');
  if (!iframe) {
    iframe = _createHiddenIframe(document.body, 'about:blank');
  }

  try {
    iframe.contentWindow.location.href = uri;
    successCb();
  } catch (e) {
    if (e.name == 'NS_ERROR_UNKNOWN_PROTOCOL') {
      failCb();
    }
  }
}

function openUriUsingIEInOlderWindows(uri, failCb, successCb) {
  const version = getInternetExplorerVersion();
  if (version === 10) {
    openUriUsingIE10InWindows7(uri, failCb, successCb);
  } else if (version === 9 || version === 11) {
    openUriWithHiddenFrame(uri, failCb, successCb);
  } else {
    openUriInNewWindowHack(uri, failCb, successCb);
  }
}

function openUriUsingIE10InWindows7(uri, failCb, successCb) {
  const timeout = setTimeout(failCb, 1000);
  window.addEventListener('blur', function() {
    clearTimeout(timeout);
    successCb();
  });

  let iframe = document.querySelector('#hiddenIframe');
  if (!iframe) {
    iframe = _createHiddenIframe(document.body, 'about:blank');
  }
  try {
    iframe.contentWindow.location.href = uri;
  } catch (e) {
    failCb();
    clearTimeout(timeout);
  }
}

function openUriInNewWindowHack(uri, failCb, successCb) {
  const myWindow = window.open('', '', 'width=0,height=0');
  myWindow.document.write("<iframe src='" + uri + "'></iframe>");

  setTimeout(function() {
    try {
      myWindow.location.href;
      myWindow.setTimeout('window.close()', 1000);
      successCb();
    } catch (e) {
      myWindow.close();
      failCb();
    }
  }, 1000);
}

function openUriWithMsLaunchUri(uri, failCb, successCb) {
  navigator.msLaunchUri(uri, successCb, failCb);
}

// 主導(dǎo)出函數(shù)
export function protocolCheck(uri, failCb, successCb, unsupportedCb) {
  function failCallback() {
    failCb && failCb();
  }

  function successCallback() {
    successCb && successCb();
  }

  if (navigator.msLaunchUri) {
    openUriWithMsLaunchUri(uri, failCallback, successCallback);
  } else {
    const browser = checkBrowser();

    if (browser.isFirefox) {
      openUriUsingFirefox(uri, failCallback, successCallback);
    } else if (browser.isChrome || browser.isIOS) {
      openUriWithTimeoutHack(uri, failCallback, successCallback);
    } else if (browser.isIE) {
      openUriUsingIEInOlderWindows(uri, failCallback, successCallback);
    } else if (browser.isSafari) {
      openUriWithHiddenFrame(uri, failCallback, successCallback);
    } else {
      unsupportedCb && unsupportedCb();
    }
  }
}

Vue 組件實(shí)現(xiàn)

(src/components/ProtocolChecker.vue)

<template>
  <div class="protocol-checker">
    <el-card shadow="hover">
      <template #header>
        <div class="card-header">
          <span>VNC 連接器</span>
        </div>
      </template>

      <el-form label-position="top">
        <el-form-item label="VNC 連接地址">
          <el-input 
            v-model="vncUrl" 
            placeholder="例如: com.realvnc.vncviewer.connect://10.0.66.98:20"
            clearable>
          </el-input>
        </el-form-item>

        <el-form-item>
          <el-button
            type="primary"
            :loading="loading"
            @click="handleProtocolCheck"
            icon="el-icon-connection">
            啟動(dòng)連接
          </el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-dialog
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      width="30%"
      :close-on-click-modal="false">
      <div class="dialog-content">
        <el-alert
          :title="dialogMessage"
          :type="alertType"
          :closable="false"
          show-icon>
        </el-alert>
      </div>
      <template #footer>
        <el-button @click="dialogVisible = false">關(guān)閉</el-button>
        <el-button
          v-if="showDownload"
          type="primary"
          @click="openDownloadPage">
          下載 VNC Viewer
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { protocolCheck } from '@/utils/protocolCheck'

export default {
  name: 'ProtocolChecker',
  data() {
    return {
      loading: false,
      dialogVisible: false,
      dialogTitle: '',
      dialogMessage: '',
      alertType: 'info',
      showDownload: false,
      vncUrl: 'com.realvnc.vncviewer.connect://10.0.66.98:20'
    }
  },
  methods: {
    handleProtocolCheck() {
      if (!this.vncUrl) {
        this.showDialog('錯(cuò)誤', '請(qǐng)輸入有效的VNC連接地址', 'error')
        return
      }

      this.loading = true
      
      protocolCheck(  //直接用這個(gè)方法就可以了
        this.vncUrl,
        () => {
          // 失敗回調(diào)
          this.showDialog(
            '未檢測(cè)到VNC Viewer', 
            '您的系統(tǒng)未安裝VNC Viewer或協(xié)議不受支持', 
            'error',
            true
          )
          this.loading = false
        },
        () => {
          // 成功回調(diào)
          this.showDialog(
            '正在連接', 
            '正在啟動(dòng)VNC Viewer應(yīng)用程序...', 
            'success'
          )
          this.loading = false
        },
        () => {
          // 瀏覽器不支持回調(diào)
          this.showDialog(
            '瀏覽器不支持', 
            '您的瀏覽器不支持此功能,請(qǐng)使用Chrome/Firefox/Edge瀏覽器', 
            'warning'
          )
          this.loading = false
        }
      )
    },

    showDialog(title, message, type = 'info', showDownload = false) {
      this.dialogTitle = title
      this.dialogMessage = message
      this.alertType = type
      this.showDownload = showDownload
      this.dialogVisible = true
    },

    openDownloadPage() {
      window.open('https://www.realvnc.com/en/connect/download/viewer/', '_blank')
      this.dialogVisible = false
    }
  }
}
</script>

<style scoped>
.protocol-checker {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.dialog-content {
  margin-bottom: 20px;
}
</style>


總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue中路由的使用方法實(shí)例詳解

    Vue中路由的使用方法實(shí)例詳解

    本文為大家介紹Vue中路由的使用方法,包括安裝路由創(chuàng)建路由并導(dǎo)出以及在應(yīng)用實(shí)例中使用vue-router的相關(guān)知識(shí),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-02-02
  • vue中Vue.set()的使用以及對(duì)其進(jìn)行深入解析

    vue中Vue.set()的使用以及對(duì)其進(jìn)行深入解析

    vue不允許在已經(jīng)創(chuàng)建的實(shí)例上動(dòng)態(tài)添加新的根級(jí)響應(yīng)式屬性,不過(guò)可以使用Vue.set()方法將響應(yīng)式屬性添加到嵌套的對(duì)象上,下面這篇文章主要給大家介紹了關(guān)于vue中Vue.set()的使用以及對(duì)其進(jìn)行深入解析的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • vue中push()和splice()的使用解析

    vue中push()和splice()的使用解析

    這篇文章主要介紹了vue中push()和splice()的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Vue使用自定義指令實(shí)現(xiàn)頁(yè)面底部加水印

    Vue使用自定義指令實(shí)現(xiàn)頁(yè)面底部加水印

    本文主要實(shí)現(xiàn)給項(xiàng)目的整個(gè)背景加上自定義水印,可以改變水印的文案和字體顏色等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Vue.js之slot深度復(fù)制詳解

    Vue.js之slot深度復(fù)制詳解

    這篇文章主要介紹了Vue.js之slot深度復(fù)制的相關(guān)資料,文中介紹的很詳細(xì),對(duì)大家具有一定的參考價(jià)值,需要的朋友們來(lái)一起看看吧。
    2017-03-03
  • vue2.x element-ui實(shí)現(xiàn)pc端購(gòu)物車頁(yè)面demo

    vue2.x element-ui實(shí)現(xiàn)pc端購(gòu)物車頁(yè)面demo

    這篇文章主要為大家介紹了vue2.x element-ui實(shí)現(xiàn)pc端購(gòu)物車頁(yè)面demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • vue-pdf插件實(shí)現(xiàn)pdf文檔預(yù)覽方式(自動(dòng)分頁(yè)預(yù)覽)

    vue-pdf插件實(shí)現(xiàn)pdf文檔預(yù)覽方式(自動(dòng)分頁(yè)預(yù)覽)

    這篇文章主要介紹了vue-pdf插件實(shí)現(xiàn)pdf文檔預(yù)覽方式(自動(dòng)分頁(yè)預(yù)覽),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 利用vue實(shí)現(xiàn)模態(tài)框組件

    利用vue實(shí)現(xiàn)模態(tài)框組件

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)模態(tài)框組件的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 對(duì)Vue beforeRouteEnter 的next執(zhí)行時(shí)機(jī)詳解

    對(duì)Vue beforeRouteEnter 的next執(zhí)行時(shí)機(jī)詳解

    今天小編就為大家分享一篇對(duì)Vue beforeRouteEnter 的next執(zhí)行時(shí)機(jī)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 使用axios請(qǐng)求時(shí),發(fā)送formData請(qǐng)求的示例

    使用axios請(qǐng)求時(shí),發(fā)送formData請(qǐng)求的示例

    今天小編就為大家分享一篇使用axios請(qǐng)求時(shí),發(fā)送formData請(qǐng)求的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-10-10

最新評(píng)論

牡丹江市| 玛多县| 盐山县| 宜城市| 英吉沙县| 赫章县| 洱源县| 汾西县| 班戈县| 容城县| 黄石市| 乌兰县| 鲁山县| 三台县| 凌云县| 玉屏| 武乡县| 洱源县| 平远县| 达孜县| 墨竹工卡县| 漾濞| 玉田县| 内丘县| 梅河口市| 绵竹市| 永新县| 海宁市| 抚州市| 平阴县| 博客| 昭觉县| 乐清市| 山东| 郯城县| 海城市| 永州市| 读书| 定陶县| 临桂县| 山丹县|