vue——【v-model实现原理】

1.使用v-model封装一个自定义组件:inputTableForm.vue

<template>
  <el-form
    label-position="top"
    size="mini"
    :rules="rules"
    :model="form"
  >
    <el-form-item
      prop="name"
      style="margin-bottom:0"
    >
      <el-input
        :disabled="disabled"
        @change="handleChange"
        v-model="form.name"
      />
      <template
        slot="error"
        slot-scope="scope"
      >
        <span style="color:#f56c6c;font-size:12px">{{ scope.error }}</span>
      </template>
    </el-form-item>
  </el-form>
</template>
<script>
import _ from "lodash";
export default {
  data() {
    // eslint-disable-next-line
    let partten = /^[a-zA-Z$_][a-zA-Zd_]*$/;
    let reg = /^td+$/;
    var validateName = (rule, value, callback) => {
      if (!value) {
        callback(new Error("请输入表名"));
        this.backToOriginName();
      } else {
        if (value == this.oldValue) {
          callback();
        } else {
          if (!partten.test(value)) {
            callback(new Error("表名格式不正确"));
            this.backToOriginName();
          } else if (this.tableData.map(v=>v.tablename==value).length >= 2) {
            callback(new Error("表名重复"));
            this.backToOriginName();
          } else if (reg.test(value)) {
            callback(new Error("t+数字是系统默认名称,不能使用"));
            this.backToOriginName();
          } else {
            callback();
          }
        }
      }
    };

    var rules = {
      name: [
        { required: true, message: "请输入表名", trigger: "change" },
        { validator: validateName, trigger: "blur" },
      ],
    };
    return {
      oldValue: "",
      rules: rules,
      form: {
        name: "",
      },
    };
  },
  props: {
    value: {
      type: String,
      default: "",
    },
    tableData: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  computed: {
    disabled() {
      return false;
    },
  },
  created() {
    this.form.name = this.value;
    this.oldValue = _.cloneDeep(this.value);
    // console.log(this.value, 111);
  },
  watch: {
    value(val) {
      this.form.name = val;
      // console.log(val, '监听更新');
    },
    // value: {
    //   immediate: true,
    //   handler(val) {
    //     this.form.name = val || '';
    //     this.oldValue = _.cloneDeep(val || '');
    //     console.log(val, '监听更新111');
    //   }
    // },
  },
  methods: {
    handleChange(val) {
      this.$emit("input", val);
      // console.log(val, 222);
    },
    backToOriginName() {
      setTimeout(() => {
        this.$emit("input", this.oldValue);
        // console.log(this.oldValue, 333);
      }, 1000);
    },
  },
};
</script>

2.引用组件:

<template>
  <div>
    <el-form
      label-position="top"
      :model="forn"
      :rules="rules"
    >
      <el-form-item
        label="接入组件:"
        prop="table"
      >
        <el-table
          :data="inputtable"
          :show-header="false"
          border
        >
          <el-table-column prop="tablename">
            <template slot-scope="scope">
              <inputTableForm
                :table-data="inputtable"
                :key="scope.row.$index"
                v-model="scope.row.tablename"
              />
            </template>
          </el-table-column>
          <el-table-column prop="tablevalueText">
            <template slot-scope="scoped">
              <span>{{ inputtableMatch[scoped.row.tablevalue] }}</span>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
 import inputTableForm from './inputTableForm.vue'
  components: {
      inputTableForm ,
  },
  data () {
    return {
      inputtable:[],
      inputtableMatch:{},
      form:{ table:[]},
      rules: {
        table: [
          { type: 'array', required: true, message: '接入组件不可为空', trigger: 'change' }
        ],
      },
    } 
</script> 

-end-

原文地址:https://www.cnblogs.com/wheatCatcher/p/13633520.html