彻底解决Error in nextTick: TypeError: Cannot read properties of undefined (reading clearValidate)

背景描述

最近在做国际化的功能,然后就发现各种问题,最开始是rules在国际化中不随着语言的变化而变化,为了解决这个问题开始踩坑……

错误日志

vue.runtime.esm.js:619  [Vue warn]: Error in nextTick: "TypeError: Cannot read properties of undefined (reading 'clearValidate')"

found in

---> 
        at src/views/flowinn/device/index.vue
          at src/layout/components/AppMain.vue
            at src/layout/index.vue
              at src/App.vue
               
warn @ vue.runtime.esm.js:619
vue.runtime.esm.js:1888  TypeError: Cannot read properties of undefined (reading 'clearValidate')
    at VueComponent.eval (VM5890 deviceAdd.vue:136:32)
    at Array.eval (vue.runtime.esm.js:1980:1)
    at flushCallbacks (vue.runtime.esm.js:1906:1)

解决方法

把this.$nextTick换成this.$forceUpdate即可解决。

使用了forceUpdate,如果是在引入的页面中使用了该方法,记得resetForm,不然弹出框重新打开后,那个错误的message还是在提示。

-------------------------以下是rules不同情况下的使用方法-------------------------------

在下面的几种情况中,都只用到了nextTick和forceUpdate方法,并没有使用resetFields方法。经过验证resetFields方法有问题,有时候会导致部分的input无法输入,切记不要使用。在网上搜索了一下发现有使用setTimeout方法的,那些基本是做赋值用的,这里还是不适用,经过测试完全没有效果。

第一种情况

这种情况下不需要国际化,只是一个简单的form表单验证,而且不是引入的页面或组件,就是一个完整的单一页面。这种情况下直接在data中定义自己的rules就可以实现功能。

data() {
    return {
      inputDisabled: true,
      title:"",
      addErrorMessage:"",
      addOpen: false,
      // 分组选项
      queryGroupOptions: [],
      // 用户选项
      queryUserOptions: [],
      // 表单参数
      addForm: {
        id:null,
        devId:"",
        ownerId:"",
        name:"",
        devDesc:"",
        longitude:"",
        latitude:"",
        groupId:"",
      },
      rules: {
        devId: [
          { required: true, message: '请输入用户账号', trigger: 'blur' }
        ],
      }
    };
  },

第二种情况

需要实现国际化功能,但是不是引入的页面或组件,就是一个完整的单一页面。这种情况下需要借助nextTick方法来实现。在这种情况下,如果使用第一种写法,就会出现一个问题,就是你切换了不同的语言,这时候输入框的不填写时候的错误消息还是默认的中文的,不会随着语言的切换而切换。

export default {
  name: "Device",
  data() {
    return {
      inputDisabled: true,
      title:"",
      addErrorMessage:"",
      addOpen: false,
      // 分组选项
      queryGroupOptions: [],
      // 用户选项
      queryUserOptions: [],
      // 表单参数
      addForm: {
        id:null,
        devId:"",
        ownerId:"",
        name:"",
        devDesc:"",
        longitude:"",
        latitude:"",
        groupId:"",
      },
    };
  },
  computed: {
    rules() {
      let rules = {
        devId: [
          { required: true, message: this.$i18n.t('userInput')+this.$i18n.t('indexTablePrimaryKey'), trigger: 'blur' }
        ],
      };
      // 引入的页面必须使用forceUpdate, 单一的页面中可以直接使用nextTick
      this.$nextTick( () => {
        this.$refs['addForm'].clearValidate();
      });
      return rules;
    }
  },
}

第三种情况

需要实现国际化功能,是引入的页面或组件。这种情况下需要借助forceUpdate方法来实现。

这种方法下特别要注意,功能虽然实现了,但是出现了另一个问题。就是弹出框打开后,鼠标离开输入框,错误消息提示,然后关闭弹出框,再次打开弹出框的时候,那个错误消息还在,这时候需要调用resetForm来解决。以下的代码中都有。

export default {
  name: "Device",
  data() {
    return {
      inputDisabled: true,
      title:"",
      addErrorMessage:"",
      addOpen: false,
      // 分组选项
      queryGroupOptions: [],
      // 用户选项
      queryUserOptions: [],
      // 表单参数
      addForm: {
        id:null,
        devId:"",
        ownerId:"",
        name:"",
        devDesc:"",
        longitude:"",
        latitude:"",
        groupId:"",
      },
    };
  },
  computed: {
    rules() {
      let rules = {
        devId: [
          { required: true, message: this.$i18n.t('userInput')+this.$i18n.t('indexTablePrimaryKey'), trigger: 'blur' }
        ],
      };
      // 引入的页面必须使用forceUpdate, 单一的页面中可以直接使用nextTick
      this.$forceUpdate( () => {
        this.$refs['addForm'].clearValidate();
      });
      return rules;
    }
  },
    dialogAddOpenFun(chooseId){
      this.addErrorMessage = "";
      noPageListUser().then(response => {
        this.queryUserOptions = response.rows;
      });
      listBsGroupNoPage().then(response => {
        this.queryGroupOptions = response.rows;
      });
      if(chooseId == null){
        this.inputDisabled = false;
        this.title = this.$i18n.t('btnAdd');
        this.addForm.id=null,
        this.addForm.devId="";
        this.addForm.ownerId="";
        this.addForm.name="";
        this.addForm.devDesc="";
        this.addForm.longitude="";
        this.addForm.latitude="";
        this.addForm.groupId="";
    // 特别重要
        this.resetForm("addForm");
      }else{
        this.inputDisabled = true;
        this.title = this.$i18n.t('btnEdit');
        this.addForm.devId=chooseId;
        getDevice(chooseId).then(response => {
          this.addForm = response.data;
        });
      }
      this.addOpen = true;
    },
}

vue完整代码





你可能感兴趣的:(前端,vue,rules,forceUpdate,nextTick,resetFields)