ArmLiang
ArmLiang
  • 发布:2020-08-07 10:25
  • 更新:2020-08-07 10:25
  • 阅读:1989

小程序debug技巧,让调试更加方便

分类:uni-app

小程序debug更加方便

众所周知,小程序的调试工具是不支持vue devtool 的,我们有的时候想要调试一个响应式变量都需要通过事件或者把vm引用到全局变量上
这样做有些繁琐,所以经过我长时间的摸索总结出以下的方案用于微信小程序的调试

  1. 我们使用vue devtool 的时候如果选择了一个组件默认的情况下会把当前实例的引用添加到全局上面,默认的名称为$vm+数字
  2. 本着这种目的我写了一个vue全局混入来吧页面级别的组件添加到全局上
  3. 我还编写了一个可以通过组件名称搜索的全局函数searchComponentByName暴露在全局上面方便查找组件
  4. vue和vuex事件控制台输出
// debugMiddleware.js  
const exportFn = process.env.NODE_ENV === 'development' ? function(Vue) {  
  if (process.env.NODE_ENV === 'development') {  
    // 挂载对象,如果parent对象存在就使用parent(window),不然就是用 Object  
    const mountObj = typeof parent === 'object' ? parent : Object  

    // 广度优先遍历搜索组件  
    // eslint-disable-next-line no-inner-declarations  
    function searchComponentByName(root, keyword) {  
      // 第一个参数不是对象,那么就是直接通过根元素进行搜索  
      if (typeof root !== 'object') {  
        keyword = root  
        root = mountObj.$vmRoot  
      }  
      // keyword 支持字符串或者正则表达式  
      if (typeof keyword === 'string') {  
        keyword = keyword.toUpperCase()  
      }  
      if (!root || !root.$children || root.$children.length === 0) {  
        return null  
      }  
      const stack = [root]  
      let current  
      // eslint-disable-next-line no-cond-assign  
      while (current = stack.shift()) {  
        if (current.$options && current.$options.name && current.$options.name.toUpperCase().match(keyword)) {  
          return current  
        }  
        if (current.$children && current.$children.length !== 0) {  
          stack.push(...current.$children)  
        }  
      }  
    }  
    // 在全局暴露一个通过组件名称搜索的函数  
    mountObj.searchComponentByName = searchComponentByName  

    // // 函数劫持,劫持 uni.$emit 用于控制台打印  
    const oldUniEmit = uni.$emit  
    // uni.$emit 依赖于vue事件流,uni.$emit属于全局事件  
    let isEmitGlobal = false  
    uni.$emit = function(eventName, param) {  
      isEmitGlobal = true  
      return oldUniEmit.apply(uni, arguments)  
    }  
    const oldVueEmmit = Vue.prototype.$emit  
    Vue.prototype.$emit = function(event, args) {  
      console.info(`%c ${isEmitGlobal ? 'global' : 'Vue'}.$emit `, `background-color: #41b883;color: #fff`, `${event}`, args, this)  
      isEmitGlobal = false  
      return oldVueEmmit.apply(this, arguments)  
    }  

    Vue.mixin({  
      beforeCreate() {  
        if (this.$options.store) {  
          this.$options.store.subscribe((mutation, state) => {  
            console.info(`%c Vux.mutation `, `background-color: #41b883;color: #fff`, `${mutation.type}`, mutation.payload)  
          })  
          this.$options.store.subscribeAction((action, state) => {  
            console.info(`%c Vuex.action `, `background-color: #41b883;color: #fff`, `${action.type}`, action.payload)  
          })  
        }  
      },  
      created() {  
        if (process.env.NODE_ENV === 'development') {  
          // 如果当前组件类型是页面就把this挂载  
          if (this.mpType === 'page') {  
            mountObj.__count = mountObj.__count ? mountObj.__count++ : 1  
            const count = mountObj.__count  
            mountObj['$vm' + count] = this  
            // 把root挂载到全局  
            mountObj.$vmRoot = this.$root  
          }  
        }  
      },  
      beforeDestroy() {  
        if (process.env.NODE_ENV === 'development') {  
          if (this.mpType === 'page') {  
            if (mountObj.__count) {  
              mountObj.__count--  
            }  
          }  
        }  
      }  
    })  
  }  
} : null  
export default exportFn  

// main.js  
// 如果测试环境就给所有组件添加debugMiddleware  
if (process.env.NODE_ENV === 'development') {  
  Vue.use(debugMiddleware)  
}

这样我们就可以在小程序控制台通过 $vm1 获取到当前页面的引用

0 关注 分享

要回复文章请先登录注册