uView组件Popup 弹出层中嵌套form表单,在onReady生命周期this.$ref.uForm为undefined

  • 原创
  • 作者:程序员三丰
  • 发布时间:2021-07-15 12:56
  • 浏览量:767
基于uni-app,结合uView开发微信小程序,其中需要在弹出层组件Popup中嵌套form表单组件,同时需要应用表单验证功能。根据uView官网文档在onReady生命周期中通过$refs设置验证规则,但是运行代码报错,控制打印对应表单的ref结果为undefined,导致表单验证功能无法正常使用。

问题复现

  • 模版代码:
          <u-popup v-model="bookTrialClassShow" mode="bottom" border-radius="14" height="82%">
              <view class="book-trailclass-popup content">
                  <view class="text-black text-lg text-bold text-center padding">预约信息</view>
                  <view class="margin-bottom padding-lr">
                      <u-form :model="trialClassBookForm" ref="trialClassBookUForm" :label-width="152"
                          :error-type="['message']">
                          <u-form-item label="姓名" prop="name">
                              <u-input v-model="trialClassBookForm.name" placeholder="请输入学生的真实姓名" />
                          </u-form-item>
                          <u-form-item label="性别" prop="sex">
                              <u-radio-group v-model="trialClassBookForm.sex">
                                  <u-radio v-for="(item, index) in sexMap" :key="index" :name="item.name"
                                      :data-val="item.val">
                                      {{ item.name }}
                                  </u-radio>
                              </u-radio-group>
                          </u-form-item>
                          <u-form-item label="年龄" prop="age">
                              <u-input v-model="trialClassBookForm.age" placeholder="请输入学生的年龄" type="number" />
                          </u-form-item>
                          <u-form-item label="手机号" prop="mobile">
                              <u-input v-model="trialClassBookForm.mobile" placeholder="请输入您的常用手机号" />
                          </u-form-item>
                      </u-form>
                  </view>
                  <view class="cum-popup-foot text-center padding-tb-xs margin-top-sm">
                      <button class="cu-btn bg-cyan round" @click="bookTrialClassSubmit">确定选择</button>
                  </view>
              </view>
          </u-popup>
    
  • js代码:
    export default {
          data() {
              return {
                  //控制是否显示预约信息弹层
                  bookTrialClassShow: true,
                  trialClassBookForm: {
                      name: '',
                      sex: '',
                      age: '',
                      mobile: ''
                  },
                  trialClassBookFormRules: {
                      name: [{
                          required: true,
                          message: '请输入姓名',
                          trigger: ['change', 'blur']
                      }],
                      sex: [{
                          required: true,
                          message: '请选择性别',
                          trigger: ['change', 'blur']
                      }],
                      age: [{
                              required: true,
                              message: '请输入年龄',
                              trigger: ['change', 'blur']
                          },
                          {
                              validator: (rule, value, callback) => {
                                  return this.$u.test.range(value, [1, 100]);
                              },
                              message: '年龄必须是1-100之间',
                              trigger: ['change', 'blur'],
                          }
                      ],
                      mobile: [{
                              required: true,
                              message: '请输入手机号',
                              trigger: ['change', 'blur'],
                          },
                          {
                              validator: (rule, value, callback) => {
                                  return this.$u.test.mobile(value);
                              },
                              message: '手机号码不正确',
                              trigger: ['change', 'blur'],
                          }
                      ]
                  },
                  sexMap: [{
                          name: '男',
                          val: 1
                      },
                      {
                          name: '女',
                          val: 2
                      }
                  ],
              }
          },
          onLoad() {},
          onReady() {
              this.$refs.trialClassBookUForm.setRules(this.rules);
          },
          methods: {
              /**
               * 试听预约信息提交
               */
              bookTrialClassSubmit() {
                  this.$refs.trialClassBookUForm.validate(valid => {
                      if (valid) {
                          this.showModal(JSON.stringify(this.trialClassBookForm))
                      }
                  })
              }
          }
      }
    
  • 运行结果是控制台报错如下:

    [vue warn]: error in onready hook: “typeerror: cannot read property ‘setrules’ of undefined”

解决思路

  • 在控制台打印报错方法所属的对象,也就是$refs,代码如下:

    onReady() {
      //this.$refs.trialClassBookUForm.setRules(this.rules);
      console.log(this.$refs.trialClassBookUForm); //执行结果是undefined
    },
    

    根据上面的调试结果,猜测onLoad生命周期form组件可能尚未创建完毕。
    分析代码执行逻辑,一般场景下Popup弹层不是页面加载完就默认显示的,而是点击某个按钮才会动态显示Popup弹层的,那么表单组件很可能是Popup弹层组件创建成功之后才创建的,这与官方文档说明以及我的猜测是匹配的。那么解决思路就有了。

  • 解决思路就是:看Popup是否开放了组件创建完成的事件API,通过阅读官方文档,确实有Popup弹出层打开的Event,事件名为open,因此我们可以尝试在open事件中添加在onReady生命周期中执行表单验证处理逻辑。

解决方法

  • 在Popup组件上增加监听open事件,模版代码调整如下:
      <u-popup v-model="bookTrialClassShow" mode="bottom" border-radius="14" height="82%" @open="bookTrialClassOpen">  <!-- 增加的代码:@open="bookTrialClassOpen" -->
    
  • methods中增加open事件监听处理,将之前onReady中代码逻辑放到open事件监听处理中,js代码调整如下:
      onReady() {
          //this.$refs.trialClassBookUForm.setRules(this.rules); // 注释或删除这行代码
      },
      methods: {
          /**
           * 试听预约信息提交
           */
          bookTrialClassSubmit() {
              this.$refs.trialClassBookUForm.validate(valid => {
                  if (valid) {
                      this.showModal(JSON.stringify(this.trialClassBookForm))
                  }
              })
          },
          bookTrialClassOpen() {
              this.$refs.trialClassBookUForm.setRules(this.trialClassBookFormRules);
          },
      }
    
  • 再次运行代码,控制台无报错,uView表单组件验证功能可正常使用。
声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://www.51blog.xyz/article/10

文章归档

强烈推荐的PHP全栈开发后台管理系统
buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

推荐文章

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas vue3 three.js 微信支付 PHP全栈开发 Python AI 人工智能 AI辅助 工作经验 实战笔记