k***@163.com
k***@163.com
  • 发布:2021-12-29 22:42
  • 更新:2022-10-20 14:35
  • 阅读:2014

修复uni.preloadPage预加载tabBar页面,正式打包切换tabBar报错/出错

分类:uni-app

修复方法如下:

修改uni统计源代码(修改后的uni-stat见附件)

打开HBuilderX安装目录,找到 HBuilderX安装目录\plugins\uniapp-cli\node_modules\@dcloudio\uni-stat\dist\index.js 这个文件。需注意package.json文件中version指定的版本,我的是uni-stat 2.0.0-32920211119001这个版本。

如果你的项目不是使用HBuilderX创建的,你可能需要修改 HBuilderX安装目录\plugins\uniapp-cli\node_modules\@dcloudio\vue-cli-plugin-uni\packages\uni-stat\dist 文件夹下的 uni-stat.cjs.js和uni-stat.es.js这两个文件,改造方法应该和下面的相同(因为我的项目没有用到这两个js代码,所以不清楚这两个代码在什么环境下起作用)。至于怎么查看用到的是哪个目录中的uni-stat,可以通过查看项目编译后的app-service.js文件,搜索关键字“@dcloudio/uni-stat@”, 可以定位到uni-stat的版本

下面开工改造:

1. 修改getRoute方法

const getRoute = () => {    
  var pages = getCurrentPages();    
  var page = pages[pages.length - 1];    
  if (!page) return ''    
  // preloadPage的nvue页面$vm为undefined    
  let _self = page.$vm;    
  // 为preloadPage的nvue页面尝试从$page获取route属性    
  let _page = page.$page;    
  if (getPlatformName() === 'bd' && _self) {    
    return _self.$mp && _self.$mp.page.is;    
  } else if (_self){    
    return (_self.$scope && _self.$scope.route) || (_self.$mp && _self.$mp.page.route);    
  } else if (_page){    
    return _page.route    
  } else {    
    console.error('未找到路径')    
    return ''    
  }    
};

2. 修改getPageRoute方法

const getPageRoute = (self) => {    
  var pages = getCurrentPages();    
  var page = pages[pages.length - 1];    
  if (!page) return ''    
  let _self = page.$vm;    
  let _page = page.$page;    
  let query = self._query;    
  let str = query && JSON.stringify(query) !== '{}' ? '?' + JSON.stringify(query) : '';    
  // clear    
  self._query = '';    
  if (getPlatformName() === 'bd' && _self) {    
    return _self.$mp && _self.$mp.page.is + str;    
  } else if (_self) {    
    return (_self.$scope && _self.$scope.route + str) || (_self.$mp && _self.$mp.page.route + str);    
  } else if (_page){    
    return _page.route    
  } else {    
    console.error('未找到路径')    
    return ''    
  }    
};

3. 修改class Stat的load方法

class Stat extends Util {    
  ....此处省略    
  load(options, self) {    
    if (!self.$scope && !self.$mp) {    
      // 如果是preloadPage nvue页面, 则这里拿不到对应的页面(也就是nvue页面不在CurrentPages页面栈中),需要使用route判断一下正确性    
      // 否则会把错误的页面赋值给self.$scope,进而引发Cannot read property '__call_hook' of undefined的错误    
      const page = getCurrentPages();    
      const route = page[page.length - 1].route;    
      if (self.$options && self.$options.route === route) {    
        self.$scope = page[page.length - 1];    
      }    
    }    
    this.self = self;    
    this._query = options;    
  }    
}

4. 在lifecycle前定义函数tryinterceptShare

const tryinterceptShare = function(ctx) {    
    if (ctx.$scope && ctx.$scope.onShareAppMessage) {    
        let oldShareAppMessage = ctx.$scope.onShareAppMessage;    
        ctx.$scope.onShareAppMessage = function(options) {    
          stat.interceptShare(false);    
          return oldShareAppMessage.call(ctx, options)    
        };    
    }    
}

5. 修改lifecycle 的 onLoad 方法

  onLoad(options) {    
    stat.load(options, this);    
    // 重写分享,获取分享上报事件    
    tryinterceptShare(this)    
    // preloadPage nvue页面,$scope可能为undefined    
    if (!this.$scope) {    
        var $scope = undefined;    
        var self = this;    
        Object.defineProperty(this, '$scope', {    
            get() {    
                return $scope    
            },    
            set(val) {    
                $scope = val;    
                setTimeout(()=>{    
                    tryinterceptShare(self)    
                }, 0)    
            }    
        })    
    }    
  }

6. try catch lifecycle 中的所有方法,防止uni-stat统计出错引发应用异常

在 lifecycle定义后,添加如下代码  

const ERROR_PREFIX = 'uni-stat@' + STAT_VERSION;    

// 把lifecycle的方法全都try catch起来,防止出什么错导致应用页面打不开    
const tryfunc = function(func, name) {    
    return function() {    
        try {    
            let args = [].slice.call(arguments);    
            func.apply(this, args)    
        } catch(e) {    
            console.error(ERROR_PREFIX + ' error in function '+ name);    
            console.error(JSON.stringify(e))    
        }    
    }    
}    
Object.keys(lifecycle).forEach(k=>{    
    lifecycle[k] = tryfunc(lifecycle[k], k)    
})  

至此改造完毕。因为我也不知道这么修改会不会在其它平台出现错误,所以大家还是在修改后调试一下再发布,不过目前我自己在安卓机子上测试没发现问题。

0 关注 分享

要回复文章请先登录注册

s***@163.com

s***@163.com

不知所云~不过字数多,信你!
2022-10-20 14:35