b***@163.com
b***@163.com
  • 发布:2024-03-26 19:31
  • 更新:2024-08-23 01:54
  • 阅读:464

【报Bug】升级最新版HBuilderX后,抖音小程序突然不支持uni-easyinput的事件

分类:uni-app

产品分类: uniapp/小程序/字节跳动

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: Windows 11 专业版 22631.3296

HBuilderX类型: 正式

HBuilderX版本号: 4.06

第三方开发者工具版本号: V4.2.1

基础库版本号: 3.14.0.1

项目创建方式: HBuilderX

示例代码:
<template>  
    <view class="title">  
        <text>老师快速登录</text>  
    </view>  

    <view class="login-info">  
        <view class="input-phone">  
            <uni-easyinput v-model="phoneNumber" type="number" maxlength="11" trim="all" :errorMessage="phoneInputError"  
                placeholder="请输入手机号" @input="onInputPhone" @clear="onClearPhone"></uni-easyinput>  
            <view class="input-error">  
                <text>{{phoneInputError}}</text>  
            </view>  
        </view>  
        <view class="input-code" v-if="isLogin">  
            <view class="code">  
                <uni-easyinput type="number" maxlength="6" trim="all" :errorMessage="codeInputError"  
                    placeholder="请输入验证码" @input="onInputVerifyCode" @clear="onClearVerifyCode"></uni-easyinput>  
                <view class="input-error">  
                    <text>{{codeInputError}}</text>  
                </view>  
            </view>  
            <view class="countdown" v-if="!isReget">  
                <uni-countdown :color="color" :second="60" @timeup="onTimeupdate" :showDay='false' :showHour='false'  
                    :showMinute="false" />  
                <text>秒后重新获取</text>  
            </view>  
            <view class="reget-code" v-if="isReget" @click="onGetVerifyCode">  
                <text>重新获取</text>  
            </view>  
        </view>  

        <view class="protocols">  
            <uni-data-checkbox class="checkbox" multiple v-model="checkboxV" @change="onChangeBox" :localdata="hobby">  
            </uni-data-checkbox>  
            <text class="text">已详读并同意</text>  
            <text class="link-text" @click="onUserAgreement">用户协议</text>  
            <text>和</text>  
            <text class="link-text" @click="onPrivacyPolicy">隐私政策</text>  
            <text>,新手机号将自动注册</text>  
        </view>  
        <button class="get-code" v-if="!isLogin" @click="onGetVerifyCode">获取验证码</button>  
        <button class="get-code" v-if="isLogin" :disabled="loginDisabled" @click="onLogin">登录</button>  
    </view>  
</template>  

<script setup>  
    import teacher from '@/api/teacher.js'  
    import student from '@/api/student.js'  
    import {  
        ref  
    } from "vue";  
    import tools from '@/utils/tools.js'  
    // 手机号  
    const phoneNumber = ref('')  
    // 用户协议和隐私政策  
    const hobby = ref([{  
        text: '',  
        value: true  
    }])  
    // 选中用户协议和隐私政策的值  
    const checkboxV = ref()  
    // 验证码  
    const verifyCode = ref('')  
    const phoneInputError = ref('')  
    const codeInputError = ref('')  
    // 获取验证码按钮是否置灰  
    const buttonDisabled = ref(true)  
    // 验证码倒计时文字颜色  
    const color = ref('#d5d5d5')  
    // 判断是否显示重新获取  
    const isReget = ref(false)  
    // 登录按钮是否置灰  
    const loginDisabled = ref(true)  
    // 是否显示登录按钮  
    const isLogin = ref(false)  
    // 判断输入的手机号格式是否正确  
    const onInputPhone = (e) => {  
        phoneInputError.value = ''  
        console.log("phoneNumber:", e)  
        if (e && isNaN(parseInt(e))) {  
            phoneInputError.value = '只能输入手机号'  
            return  
        }  
    }  
    // 判断选中用户协议和隐私政策  
    const isProtocolSelect = () => {  
        if (!(checkboxV.value && checkboxV.value[0])) {  
            uni.showToast({  
                title: "阅读并勾选用户协议和隐私政策",  
                icon: 'none',  
            })  
            return false  
        }  
        return true  
    }  
    // 查看用户协议  
    const onUserAgreement = () => {  
        uni.navigateTo({  
            url: '/pages/protocols/user_agreement'  
        })  
    }  
    // 查看隐私政策  
    const onPrivacyPolicy = () => {  
        uni.navigateTo({  
            url: '/pages/protocols/privacy_policy'  
        })  
    }  
    // 获取验证码按钮置灰  
    const onClearPhone = () => {  
        buttonDisabled.value = true  
    }  
    // 获取验证码  
    const onGetVerifyCode = async () => {  
        // 判断选中用户协议和隐私政策  
        if (!isProtocolSelect()) {  
            return  
        }  
        console.log("phoneNumber:", phoneNumber.value)  
        if (  
            phoneNumber.value.length != 11 ||  
            isNaN(parseInt(phoneNumber.value.length))  
        ) {  
            isLogin.value = false  
            phoneInputError.value = "手机号错误,请重新输入"  
            return  
        }  
        let {  
            message,  
            data  
        } = await teacher.apiSendVerifyCode({  
            phone: tools.phoneToE16(phoneNumber.value)  
        })  
        if (message == '0') {  
            isReget.value = false  
            isLogin.value = true  
        }  
        // isReget.value = false  
        // isLogin.value = true  
    }  
    // 判断输入的验证码的格式是否正确  
    const onInputVerifyCode = async (e) => {  
        codeInputError.value = ''  
        verifyCode.value = e  
        if (e && isNaN(parseInt(verifyCode.value))) {  
            codeInputError.value = '只能输入验证码'  
            return  
        }  
        if (verifyCode.value.length == 6) {  
            loginDisabled.value = false  
            await onLogin()  
        } else {  
            loginDisabled.value = true  
        }  
    }  
    // 登录按钮置灰  
    const onClearVerifyCode = () => {  
        loginDisabled.value = true  
    }  
    // 倒计时结束时显示重新获取  
    const onTimeupdate = () => {  
        isReget.value = true  
    }  
    // 登录  
    const onLogin = async () => {  
        // 判断选中用户协议和隐私政策  
        if (!isProtocolSelect()) {  
            return  
        }  

        // 退出学生账户  
        if (uni.getStorageSync('role') == "student") {  
            await student.apiLogout()  
        }  

        let {  
            message,  
            data  
        } = await teacher.apiUserLogin2({  
            phone: tools.phoneToE16(phoneNumber.value),  
            verify_code: verifyCode.value,  
        })  
        if (message == '0') {  
            // console.log("resp data:", data)  
            uni.setStorageSync("accessToken", {  
                token: data.access_token,  
                expiresAt: data.access_token_expires_at,  
            })  
            uni.setStorageSync('role', 'teacher')  
            await beforNavigate()  
        } else {  
            codeInputError.value = '验证码错误'  
            // console.log('登陆失败:', message)  
        }  
    }  

    const beforNavigate = async () => {  
        let {  
            message,  
            data  
        } = await teacher.apiGetBriefInfo()  
        if (message == '0') {  
            if (!data.name) {  
                // 先补充个人基本信息  
                uni.redirectTo({  
                    url: '/pages/teacher-my/improve-information'  
                })  
            } else {  
                // 返回上一页并重载  
                let pages = getCurrentPages()  
                uni.reLaunch({  
                    url: "/" + pages[pages.length - 2]?.route  
                })  
            }  
        }  
    }  
</script>  

<style lang="scss">  
    page {  
        background-color: #fff;  
        display: flex;  
        flex-direction: column;  
        justify-content: center;  
    }  

    .title {  
        margin: 94rpx auto 0 auto;  
        font-size: 48rpx;  
        color: #232832;  
    }  

    .login-info {  
        // margin: 240rpx 72rpx 0 72rpx;  
        margin: 144rpx 48rpx 0 48rpx;  

        .input-error {  
            height: 14rpx;  
            font-size: 24rpx;  
            color: #dd524d;  
        }  

        .input-phone {  
            display: flex;  
            flex-direction: column;  
        }  

        .input-code {  
            // margin-top: 10rpx;  
            display: flex;  
            flex-direction: row;  

            .code {  
                width: 380rpx;  
            }  

            .countdown {  
                width: 226rpx;  
                height: 72rpx;  
                background-color: #F7F6F6;  
                display: flex;  
                flex-direction: row;  
                justify-content: center;  
                align-items: center;  
                font-size: 26rpx;  
                color: #d5d5d5;  
            }  

            .reget-code {  
                width: 226rpx;  
                height: 70rpx;  
                border: 1px solid #d5d5d5;  
                // border-radius: 8rpx;  
                display: flex;  
                justify-content: center;  
                align-items: center;  
                font-size: 26rpx;  
            }  

        }  

        .protocols {  
            // width: 480rpx;  
            font-size: 24rpx;  
            color: #787B86;  
            margin: 30rpx auto;  
            text-align: left;  
            display: flex;  
            flex-direction: row;  
            align-items: center;  

            .checkbox {  
                width: 48rpx;  
            }  

            .link-text {  
                color: #4594FF;  
                text-decoration: underline;  
            }  

            // .text {  
            //  vertical-align: middle;  
            // }  
        }  

        .get-code {  
            height: 88rpx;  
            font-size: 32rpx;  
            color: white;  
            background-color: #FF4E4D;  
        }  
    }  

    @import "@/static/icons/iconfont.css";  

    .login-phone {  
        width: 630rpx;  
        border-radius: 46rpx;  
        background-color: #fff;  
        border: solid 2rpx #D1D1D6;  
        color: #232832;  
        // margin: 0 auto 0 auto;  
        // background-color: #00BAAD;  

        .icon {  
            position: absolute;  
            left: 40rpx;  

        }  
    }  
</style>

操作步骤:

输入手机号码

预期结果:

被uni-easyinput的@input事件所调用的onInputPhone函数应该实时获取参数结果,并且v-model所绑定的phoneNumber的值也应该实时更新

实际结果:

uni-easyinput的@input事件没有执行,v-model也没有绑定到phoneNumber

bug描述:

今下午更新到最新版Hbuilder后,抖音小程序突然不支持uni-easyinput组件的@input事件和v-model了,同时微信小程序和QQ小程序目前没遇到同样的问题

2024-03-26 19:31 负责人:无 分享
已邀请:
DCloud_UNI_OttoJi

DCloud_UNI_OttoJi - 日常回复 uni-app/x 问题,如果艾特我没看到,请主动私信

感谢反馈,你提到相同的代码在微信、qq 上可以,在抖音上不行,我已复现,通过调试发现

临时解决方案

进入 umi module 文件夹找到easyinput 组件,

方案一 推荐
源码中现在是开启 options.virtualHost=true 会导致这个问题,你可以尝试临时设置 options.virrtualHost=false 来绕过该问题。

方案二

或者你对平台进行兼容。通过判断 ifdef 是抖音就设置为 false,其他平台默认为 true,这也是官方接下来的修复方案

原因分析

的确是本次升级带来的一个潜在影响,抖音小程序开启 virtualHost 之后,会影响自定义绑定的事件。https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/framework/custom-component/component-model-and-style/#7417c627 ,而微信平台没有这个问题。本次升级正好在抖音刚刚支持 fragment 的时间点,旧版本默认不生效,新版本生效了,对比之下产生了差异

后续解决

后续会对 easyinput 进行兼容,在抖音平台默认关闭虚拟节点

  • DCloud_UNI_OttoJi

    原因分析:的确是本次升级带来的一个潜在影响,抖音小程序开启 virtualHost 之后,会影响自定义绑定的事件。https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/framework/custom-component/component-model-and-style/#7417c627 ,而微信平台没有这个问题。本次升级正好在抖音刚刚支持 fragment 的时间点,旧版本默认不生效,新版本生效了,对比之下产生了差异


    后续解决:后续会对 easyinput 进行兼容,在抖音平台默认关闭虚拟节点

    2024-03-27 16:16

  • b***@163.com (作者)

    收到,回退到上一版BuilderX,目前先用着旧版,等新版bug解决后再升级吧。

    2024-03-28 11:44

c***@icloud.com

c***@icloud.com

我是cli vscode ,抖音小程序依然不能用。 v-model 一输入 抖音开放工具卡死,:value @input 方式,还可以响应一个字母,然后继续卡死。

  • DCloud_UNI_OttoJi

    卡死的问题修复了,还没有发版。你参考 https://ask.dcloud.net.cn/question/193727 可以正常使用

    2024-08-22 20:33

c***@icloud.com

c***@icloud.com

我这用的还是老版本 uni-easyinput,按照官方方式修改
事实证明,老老实实,用生态内的方案

hbuildx脚手架+uni_modules(加载ui方案,可随时颗粒化优化)

c***@icloud.com

c***@icloud.com

天呐,找四个人,uni-forms virtualHost 没有同步更新的原因。

要回复问题请先登录注册