e***@qq.com
e***@qq.com
  • 发布:2022-08-20 20:03
  • 更新:2024-11-25 15:45
  • 阅读:2061

【报Bug】$nextTick在APP上存在不执行的情况

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

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

HBuilderX类型: 正式

HBuilderX版本号: 3.5.3

手机系统: Android

手机系统版本号: Android 10

手机厂商: 模拟器

手机机型: Pixel 2 API 29

页面类型: vue

vue版本: vue2

打包方式: 离线

项目创建方式: HBuilderX

示例代码:
主页面:  
<template>  
   <view class="uni-container">  
      <view style="position: relative;z-index: 99; background-color:#fff;">  
        <button @click="onClick">开始</button>  
      </view>  
    <test :dataList="val"></test>  
    <view>{{res}}</view>  
    <view>{{res1}}</view>  
  </view>  
</template>  

<script>  
  export default {  
    data() {  
      return {  
        val:[],  
        res:"",  
        res1:""  
      }  
    },  
    methods: {  
      onClick(){  
        console.log("点击事件开始 -> ");  
        let val = [...this.val];  
        val.push({  
          "letter": "C",  
          "data": [  
            "阿克苏机场",  
            "阿拉山口机场",  
            "阿勒泰机场",  
            "阿里昆莎机场",  
            "安庆天柱山机场",  
            "澳门国际机场"  
            ]  
        });  
        this.val = val;  
        this.$nextTick(()=>{  
          console.log("下一帧执行 -> ");  
          this.res = "已执行下一帧"  
        });  
        console.log("点击事件结束 -> ");  
        setTimeout(()=>{  
          this.res1 = "已超时"  
        },3000)  
      }  
    }  
  }  
</script>  

子组件:  
<template>  
  <view></view>  
</template>  

<script>  
  export default {  
    props:{  
      dataList:{  
        type:Array,  
        default:()=>[]  
      }  
    },  
    data() {  
      return {  
        inList:[],  
      };  
    },  
    watch:{  
      "dataList":{  
        immediate:true,  
        handler(newValue){  
          this.inList = typeof(newValue)=="string"? [newValue] :[...newValue];  
          for(let i=0;i<9999;i++){  
            this.inList.push(9)  
          }  
        }  
      }  
    }  
  }  
</script>

操作步骤:

为排除所有干扰因素,测试项目使用官方 Android 离线 SDK 内的 UniPlugin-Hello-AS 项目,版本3.5.3。
如提交的代码,点击按钮后,首先更新子组件的 dataList 数据,然后设置 $nextTick 执行操作。
复现步骤:连续点击两次按钮

预期结果:

$nextTick 的行为应在各平台统一,否则在某些场景或条件下导致非预期的代码不执行,造成严重后果,且难以排查。

实际结果:

1、在APP上,可以看到并不会执行$nextTick,只在计时器到时,更新页面 res1 触发渲染更新后执行$nextTick。
2、在H5上,可以看到第一次的点击能够立即执行$nextTick,在下一次的按钮点击前输出结果。

bug描述:

需求在一段代码中,更新子组件的props数据,并在props数据进入子组件后,再在父组打开子组件,故而需要使用$nextTick,而发现了$nextTick不执行的问题。
该问题存在于APP平台。H5及微信小程序已测试无此问题。
出现$nextTick不执行的原因大概确定,可复现。猜测为父页面没有触发渲染更新,子组件的数据变更也没有触发渲染更新。H5上会立即执行$nextTick,而在APP上则要等到渲染更新才执行$nextTick,如果一直没有渲染更新,则一直不会执行。

2022-08-20 20:03 负责人:无 分享
已邀请:
FullStack

FullStack - 【插件开发】【专治疑难杂症】【ios上架、马甲包、白包、过审、已成功上架过几百个】【多款插件已上架:https://ext.dcloud.net.cn/publisher?id=22130】【非诚勿扰】QQ:543610866

this.val = [];  
this.val = val;  
this.$forceUpdate();

这样看看

  • e***@qq.com (作者)

    已尝试,没有效果。从问题发生原因来看,只要父页面及子组件都没有更新渲染,且同时更新了子组件的数据,APP上$nextTick就不会执行。一个比较常见的情况,子组件是用v-if来控制开关的,子组件的打开是通过父页面调用子组件的open方法,如官方的popup组件等。而如果调用open的代码放在$nextTick里面,那么这里就存在风险了,因为只要open方法不执行,子组件一定不会更新渲染,再加上父页面也不更新渲染的话,那么就可能永远不会打开子组件。

    2022-08-23 09:00

  • CODE_MOP

    回复 e***@qq.com: 请问后来是怎么解决这个问题的?

    2023-11-08 11:30

  • 1***@qq.com

    回复 e***@qq.com: 请问后来怎么解决的

    2024-07-31 15:55

不如摸鱼去

不如摸鱼去 - 一个前端打工仔。如果我的回答对你产生了帮助,还请给个star: https://github.com/Moonofweisheng

遇到相同问题

从零薛

从零薛

遇到同样的问题

  • 1***@qq.com

    最后怎么解决的?

    2024-11-25 15:45

CODE_MOP

CODE_MOP

这种很常见场景的bug,1年都不fix,不闻不问?

Diligent_UI

Diligent_UI - 【插件开发】【专治疑难杂症】【多款插件已上架:https://ext.dcloud.net.cn/publisher?id=193663(微信搜索飘逸科技UI小程序直接体验)】【骗子请绕道】问题咨询请加QQ群:120594820,代表作灵感实用工具小程序

打印这个方法试试

1***@qq.com

1***@qq.com

遇到相同问题

  • e***@qq.com (作者)

    目前解决方法

    1、换vue3引擎

    2、避免使用出问题的写法,或确认更改数据后子组件一定会更新渲染,再使用$nextTick

    3、把$nextTick换成setTimeout。不过由于变成异步,在机子卡顿时或许会出现提前执行的情况,需注意延迟时间的控制

    2024-11-29 12:11

要回复问题请先登录注册