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

【报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

要回复问题请先登录注册