Vue開發移動端項目,這個工具對你必定有幫助

基於Vue.js開發移動端工程時,一些特定的問題和場景下,只能在移動端運行工程復現、追蹤問題(好比在微信端內,在App容器內),桌面端的Devtools就無法用了。數次安裝Electron版本devtools後,以爲調試起來太麻煩了,因此我決定把devtools搬進vConsole裏javascript

若是不知道什麼是vConsole,能夠看這裏vConsole Readmehtml

最終效果:

Sample Code 體驗地址: CodePenvue

Github 地址 歡迎Starjava

引入很是簡單webpack

import VConsole from "vconsole";
import Devtools from 'vue-vconsole-devtools'
Devtools.initPlugin(new VConsole());
複製代碼

效果圖:git

實現過程

分析完Vue、Vue-devtools、vConsole源碼之後,彷佛可行。步驟以下:github

  1. 剝離Vue-devtools @front部分
  2. 實現@backend 和 @front 部分通訊
  3. 實現front注入iframe
  4. iframe嵌入vConsole
  5. 製做npm包併發布

1. 剝離front

首先一個問題就是 Vue-devtools並非一個庫,因此npm上沒有它,沒法引用,其次這個工程也不適合做爲庫輸出,由於它的打包方式比較特殊,還有這個工程自己的目的就是打包成一個可執行的App或者chrome插件,因此若是想引用它裏面的代碼,我想到最簡單的方式就是拷貝了。。。 因此剝離frontend很是簡單,在Vue-devtools工程的package.json中增長script: "buildvc": "cd packages/shell-dev && cross-env NODE_ENV=production webpack --progress --hide-modules", 同時在shell-dev裏增長一個文件叫 inject.js:web

import { initDevTools } from '@front'
import Bridge from '@utils/bridge'

const targetWindow = window.parent;
document.body.style.overflow = "scroll";
initDevTools({
  connect (cb) {
    cb(new Bridge({
      listen (fn) {
        window.addEventListener('message', evt => {
          fn(evt.data)
        })
      },
      send (data) {
        targetWindow.postMessage(data, '*')
      }
    }))
  },
  onReload (reloadFn) {
    reloadFn.call();
  }
})
複製代碼

固然shell-dev裏的webpack.config.js裏 增長一個入口配置 inject: './src/inject.js'chrome

打出來的包就是咱們要的front部分,最終嵌入iframe裏。shell

2. 實現通訊

上面的inject.js中已經包含了 front部分 接收和發送消息的代碼了。 接下來完成backend部分的消息發送和接收,

import { initBackend } from '@back'
import Bridge from '@utils/bridge'

const initBackendWithTargetWindow = function(win,targetWindow){
  const bridge = new Bridge({
    listen (fn) {
      win.addEventListener('message', evt => {
        fn(evt.data)})
    },
    send (data) {
      targetWindow.postMessage(data, '*')
    }
  })
  
  initBackend(bridge)
}

export default { initBackendWithTargetWindow }
複製代碼

3. front嵌入iframe

這個比較麻煩,也遇到了一些兼容性問題,最終方案是:

  1. 把第一步打包的inject.js 重命名爲 inject.txt
  2. 增長一個rawloader規則,識別txt
  3. 使用script.txt的方式插入到script標籤中,而後插入iframe的body中
import injectString from './inject.txt'

function inject (scriptContent, done) {
  const script = document.getElementById('vue-iframe').contentWindow.document.createElement('script')
  script.text = scriptContent
  document.getElementById('vue-iframe').contentWindow.document.body.appendChild(script)
}

inject(injectString)
複製代碼

4. iframe嵌入vconsole

實現一個plugin類,繼承VConsolePlugin,而後實現對應的方法便可,具體文檔能夠查看VConsole文檔vConsole Readme

class VConsoleVueTab extends VConsolePlugin {

  constructor(...args) {
    super(...args);
  }
  onRenderTab(cb){
    cb(`<iframe id="vue-iframe" style="width:100%;position:absolute;top:0;bottom:0;min-height:100%;"></iframe>`);
  }
  onReady() {
    target = document.getElementById('vue-iframe')
    targetWindow = target.contentWindow;
    be.initBackendWithTargetWindow(window,targetWindow);    
  }

  onShow() {    
    injectOnce(injectString)
  }
}
複製代碼

5. 製做npm包併發布

這一步須要打包發佈,而且優化

const initPlugin = function(vConsole){
  var tab = new VConsoleVueTab('vue', 'Vue');
  vConsole.addPlugin(tab);
}
export default {
  initPlugin
}
複製代碼

21-08-03更新,支持CDN引入

<script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-vconsole-devtools@0.0.7/dist/vue_plugin.js"></script>
<script> var vConsole = new window.VConsole(); const Devtools = window.vueVconsoleDevtools["default"]; Devtools.initPlugin(vConsole); </script>
複製代碼
相關文章
相關標籤/搜索