辉笑流
辉笑流
  • 发布:2020-05-27 22:05
  • 更新:2023-11-14 16:38
  • 阅读:1498

【报Bug】父组件把方法传给子组件后,该方法里的this是子组件的this而不是父组件的this

分类:uni-app

产品分类: uniapp/小程序/微信

PC开发环境操作系统: Windows

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

HBuilderX类型: 正式

HBuilderX版本号: 2.7.5

第三方开发者工具版本号: 微信开发者工具v1.02.1911180

基础库版本号: 2.11.1

项目创建方式: HBuilderX

示例代码:

子组件:
<template>
<button
:size="size"
:type="type"
:plain="plain"
:disabled="disabledData"
:loading="loadingData"
:form-type="formType"
:open-type="openType"
:hover-class="hoverClass"
:hover-start-time="hoverStartTime"
:hover-stay-time="hoverStayTime"

    @click="clickButton"  
>  
    <text>{{text}}</text>  
</button>  
</template> <script> export default { name: "LsButton", props: { text:{//按钮里的文字,必传 type: String, default: '' }, time:{//防二次点击的默认时间,默认单位是毫秒。 type: Number, default: '' }, clickBtn:Function,//接收外面的方法,因为存在异步的要求,所以不用this.$emit('clickBtn')来传递值 size: {//按钮的大小:default:默认大小; mini:小尺寸 type: String, default: 'default' }, type: {//按钮的样式类型:default:白色; warn:红色; primary:微信小程序为绿色,App、H5、百度小程序、支付宝小程序为蓝色,头条小程序为红色,QQ小程序为浅蓝色 type: String, default: 'default' }, plain: {//按钮是否镂空,背景色透明。 type: Boolean, default: false }, disabled: {//是否禁用 type: Boolean, default: false }, loading: {//名称前是否带 loading 图标 type: Boolean, default: false }, formType: {//用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件 type: String, default: '' }, openType: {//开放能力。contact:打开客服会话,share:触发用户转发,getUserInfo:获取用户信息(手机号、头像、昵称等),getPhoneNumber:获取用户手机号,launchApp:打开APP,openSetting:打开授权设置页 type: String, default: '' }, hoverClass: {//指定按钮按下去的样式类。当 hover-class="none" 时,没有点击态效果 type: String, default: 'button-hover' }, hoverStartTime: {//按住后多久出现点击态,单位毫秒 type: Number, default: 20 }, hoverStayTime: {//手指松开后点击态保留时间,单位毫秒 type: Number, default: 70 }, }, data() { return { allowClick:true,//记录是否允许点击按钮(防二次点击用) disabledData:this.disabled,//点击后,异步请求完后,才允许点击 loadingData:this.loading,// }; }, computed: { }, watch: { }, created() { }, mounted() { }, methods: { async clickButton(){ this.disabledData=true this.loadingData = true if(this.time){ await this.clickBtn() setTimeout(()=>{ this.disabledData=false this.loadingData = false },this.time) } if(!this.time){ await this.clickBtn() this.disabledData=false this.loadingData = false } }, } }; </script>

操作步骤:

父组件:
<template>
<ls-button class="w-auto flex-center" :text="'搜索'" :plain="true" :clickBtn="searchSeller" :time="1000" :options="{cl:'#ffffff',lh:'44px',pr:'10'}"/>

</template> <script> export default { name: '', components: { }, props: {}, data() { return { } }, computed: {}, watch: { }, created() {}, mounted() {}, destroyed() {}, methods: { searchSeller(){ return new Promise((resolve, reject) => { appShopList.loadListByPage( this,this.params, {complete(){resolve(true)}} ) }) }, }, } </script>

预期结果:

父组件里的this,应该是指向父组件

实际结果:

父组件里的this,是指向子组件的this。
实测H5和APP正常,微信小程序不正常

bug描述:

重新封装了一个button的组件(因为用防抖的话不能彻底解决防重复点击的问题),如下图。
现在有这个需求,要求用异步方法,执行完父组件的方法后,再打开button的点击功能,让它可以再次点击。
现用的方法是在子组件props里建一个Function变量,让传入的这个父组件的方法,在子组件里运行。
现在遇到一个问题,父组件的方法里的this,打印出来,竟然是子组件里的,导致了该方法不可用
(我记得我半年前的一个项目,也是用该组件,当时的HbuilderX版本下,父组件传递到子组件里的方法里的this是指向父组件的,现在的2.7.5版本的父组件传递到子组件里的方法里的this是指向竟然是指向子组件本身的,求解决)
实测H5和APP正常,微信小程序不正常

2020-05-27 22:05 负责人:无 分享
已邀请:
白羽

白羽

searchSeller里的this是不是传错了。
在return之前,先定义_this = this,然后在promise内部使用_this而非this。
试试咯

  • 辉笑流 (作者)

    试过了,不行的。只要是该方法里的this,微信小程序上,都是指向子组件(但H5和APP端是指向父组件)


    2020-05-28 13:34

  • 8***@qq.com

    回复 辉笑流: 我解决了,在export default {}外面定义一个_this,onLoad的时候,_this = this,父组件方法里面用_this


    2020-12-29 15:55

  • qkang

    回复 8***@qq.com: 可是这样_this就是个单例了,如果一个组件要渲染很多次会导致_this只指向最新的那个


    2021-02-01 10:33

qkang

qkang

看了下编译后的代码,是把通过props传入的function 写入了子组件的 methods里面,而子组件vue编译又会把 methods的this指向自己。

战斗猪

战斗猪

这个问题很烦,我最后直接转到tarojs去了,感觉vue的支持比uni好,不过css 不支持scoped有点烦,两个都不完美,

f***@163.com

f***@163.com

为什么不在编译时将this指向到父组件呢,想给子组件添加个钩子一点儿办法都没有

x***@qq.com

x***@qq.com

测试半天发现了这个bug,官方也解决不了吗

7***@qq.com

7***@qq.com - 码字的憨憨

我也刚刚遇到这个问题,看你们这么说是BUG,我就没想办法解决了。利用条件编译 重新指向this就好了。

let that = this;  
// #ifdef MP-WEIXIN  
that = this.$parent;  
// #endif
  • 辉笑流 (作者)

    这个问题我很久前解决了,我用了这个方法:this.asyncFunction.apply(uni.$u.$parent.call(this,name)),其中的name,小程序才用到,是指引用的页面的name


    2024-01-06 15:06

要回复问题请先登录注册