x***@163.com
x***@163.com
  • 发布:2023-05-13 00:42
  • 更新:2023-08-17 11:39
  • 阅读:722

form表单验证失败,TypeError: child.onFieldChange is not a function

分类:uni-app

很简单的一个表单,验证一直报错:
TypeError: child.onFieldChange is not a function
at _callee$ (uni-forms.vue:330:1)

断点进去看了下发现这里进入了4次,有点不理解。

下面是代码:

<template>  
    <view class="forget-page">  
        <image class="logo" src="../../static/image/logo.png" mode="aspectFit"></image>  

        <uni-forms :modelValue="formData" ref="form">  
            <uni-forms-item label="旧密码" name="password" >  
                <uni-easyinput type="text" v-model="formData.password" placeholder="请输入旧密码" />  
            </uni-forms-item>  
            <uni-forms-item label="新密码" name="newPassword" >  
                <uni-easyinput type="text" v-model="formData.newPassword" placeholder="请输入新密码" />  
            </uni-forms-item>  
            <uni-forms-item label="确认密码" name="confirmPassword" >  
                <uni-easyinput type="text" v-model="formData.confirmPassword" placeholder="请再次输入新密码" />  
            </uni-forms-item>  

        </uni-forms>  
        <button class="login-btn" @click="restartPassword">重置密码</button>  

    </view>  
</template>  

<script>  
export default {  
    data() {  
        return {  
            formData: {  
                password: "",  
                newPassword: "",  
                confirmPassword: "",  
            },  
            rules: {  
                password: {  
                    rules: [{  
                        required: true,  
                        errorMessage: '请输入旧密码',  
                    }]  
                },  
                newPassword: {  
                    rules: [{  
                        required: true,  
                        errorMessage: '请输入新密码',  
                    }, {  
                        pattern: /^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z])(?=.*[!@#$%^&*?]).{8,16}$/,  
                        errorMessage: '密码由8位以上数字,大小写字母,特殊字符组成',  
                    }],  
                },  
                confirmPassword: {  
                    rules: [{  
                        required: true,  
                        errorMessage: '请再次输入新密码',  
                    }, {  
                        validateFunction: function (rule, value, data, callback) {  
                            // debugger  
                            if (value != data.newPassword) {  
                                callback('两次输入的密码不一致')  
                            }  
                            return true  
                        }  
                    }],  
                }  
            }  

        };  
    },  
    onReady() {  
        // 需要在onReady中设置规则  
        this.$refs.form.setRules(this.rules)  
    },  
    methods: {  
        restartPassword() {  
            this.$refs.form.validate().then(res => {  
                const param = {  
                    oldPassword: this.formData.password,  
                    newPassword: this.formData.newPassword,  
                }  
                this.$http.put('/updatePwd', param, true).then(res => {  
                    this.$tool.showSuccess('重置成功')  
                })  
            }).catch(err => {  
                console.log('表单错误信息:', err);  
                this.$tool.showToast(err)  
            })  

        }  
    }  
}  
2023-05-13 00:42 负责人:无 分享
已邀请:
a***@126.com

a***@126.com - 阿里崔

我也碰到这个问题了 奇怪,下载的demo正常,把demo加入项目中,就报错。

y***@gmail.com

y***@gmail.com - bruh

还没看到官方更新,贴一个临时解决方案

在 uni-forms\uni-forms.vue 里的 async checkAll 方法里的 for (let i in childrens) 的循环里添加一个判断:

for (let i in childrens) {  
    const child = childrens[i]  
        // 添加下面的if判断  
    // 检查child是否有效并且具有onFieldChange方法  
    if (!child || typeof child.onFieldChange !== 'function') {  
        continue;  // 跳过此次循环迭代  
    }  

    let name = realName(child.name);  
    const result = await child.onFieldChange(tempFormData[name]);  
    if (result) {  
        results.push(result);  
        // toast ,modal 只需要执行第一次就可以  
        if (this.errShowType === 'toast' || this.errShowType === 'modal') break;  
    }  
}  

这个循环因为未知原因有一个空组件(可以通过log打印name属性发现一个空行),这里做判断跳过空组件即可。

z***@163.com

z***@163.com

两个解决方案:修改源码 uni_modules\uni-forms\components\uni-forms\uni-forms.vue
方案一:


方案二:

报错原因:
项目中其他插件,给Array的原型增加了自定义的方法,uni-forms用的是for-in遍历的,会把这个自定义方法也遍历出来,导致也去执行 child.onFieldChange,所以报错了。
定位问题的方法:
在uni-forms这段源码中,打印child,看下是什么,是否有多余的非表单类型的child(假如是 testFn),然后项目全局搜索下,是否有 Array.prototype.testFn

要回复问题请先登录注册