999
999
  • 发布:2021-03-28 14:29
  • 更新:2022-04-07 14:36
  • 阅读:625

【报Bug】【紧急】uni.preloadPage HX3.1.4和HX3.1.6正式版打包使用出错

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: 10

HBuilderX类型: 正式

HBuilderX版本号: 3.1.6

手机系统: Android

手机系统版本号: Android 11

手机厂商: 小米

手机机型: 10

页面类型: nvue

nvue编译模式: 纯nvue

打包方式: 云端

项目创建方式: HBuilderX

操作步骤:

使用uni.preloadPage预加载tabbar页面

预期结果:

可以正常切换

实际结果:

不能切换

bug描述:

uni.preloadPage HX3.1.4和HX3.1.6正式版打包使用出错,出现预载的底部tabbar切换后,页面无法切换问题。

使用同版本打包的自定义调试基座可以正常使用。

2021-03-28 14:29 负责人:DCloud_UNI_HT 分享
已邀请:
999

999 (作者)

https://ask.dcloud.net.cn/question/119780 还有这个问题,都是切实存在的,咋官方就不关注呢

c***@foxmail.com

c***@foxmail.com

测试发现是uni统计造成的。。。测试发现是uni统计造成的。。。

  • 阿Zone

    多亏了你的发现。。。

    2022-04-08 12:10

k***@163.com

k***@163.com

修复方法如下:

修改uni统计源代码

打开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)  
})  

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

999

999 (作者)

@DCloud_UNI_linju_json

小花瓶

小花瓶

遇到同样的问题

999

999 (作者)

@DCloud_Android_DQQ

风云杭州

风云杭州

关注 uni.preloadPage ,可以用于视频 预先加载吗

Hi校园

Hi校园

你的修复了吗?

  • 999 (作者)

    不知道

    2021-06-29 08:34

阿Zone

阿Zone - 加油啊~

顶顶,期待官网解决一下

DCloud_UNI_HT

DCloud_UNI_HT

确定bug ,下个版本修复

  • 阿Zone

    太好了,期待。希望下个版本,我们加入uni统计后 tab栏能够正产更实用。感谢!!!

    2022-02-17 11:46

DCloud_UNI_HT

DCloud_UNI_HT

HBuiderX 3.4.4+ 已经修复此问题

  • 阿Zone

    一年啦。。。感恩。。还是期待正式版

    2022-04-08 12:09

要回复问题请先登录注册