封装组件,子组件v-model

238 阅读1分钟

自定义V-model

父组件:
    <TaskDetailDialog v-if="taskDetailDialogVisible" v-model="taskDetailDialogVisible"
      :history-records-params="{ dispatchType: null, taskNode: 5, taskNo: ruleForm.taskNo, }"></TaskDetailDialog>
子组件

  <el-dialog title="任务详情" :visible="visible" width="800px" :close-on-click-modal="true" :close-on-press-escape="true" @update:visible="onCancelClick">
</el-dialog>
model: {
    prop: 'visible',
    event: 'change',
},
props: {
    visible: {
      type: Boolean,
      default: () => false,
    },
    disabled: {
      type: Boolean,
      default: () => true,
    },
    historyRecordsParams: {
      type: Object,
      default: () => ({}),
    },
},
methods: {
    onCancelClick() {
      this.$emit('change', false)
    },
},

参考:www.jianshu.com/p/bff82a472…

v-model只是将$emit和prop传入合并到了一起的一个语法糖

封装 input /select等选择器/输入框

vue2:
<input :value="a" @input="(e) => a = e.target.value" />
等于
<input v-model="a" />

vue3:v-model的事件统一改成了 update:modelValue
传入的props改成了modelValue,但是v-model后面可以带参数
如果是v-model:aaa 那么传入的值就是 aaa
事件就是 update:aaa

混入mixins

export default {
  props: {
    value: {
      type: [Object, String, Number, Boolean, Array],
      default() {
        return {}
      },
    },
  },
  data() {
    return {
      node: {},
    }
  },
  methods: {
    _initValue() {
      this.node = JSON.parse(JSON.stringify(this.value))
    },
    _emitInput(node) {
      console.log('this ', this)
      // this.$emit('input', node)
      this.$emit('change', node)
    },
  },
  watch: {
    value: {
      handler() {
        if (JSON.stringify(this.node) === JSON.stringify(this.value)) return
        this._initValue()
      },
      deep: true,
      immediate: true,
    },
    node: {
      handler(node) {
        this._emitInput(node)
      },
      deep: true,
    },
  },
}

子组件

<template>
  <div>
    <el-select v-model="node" placeholder="请选择">
      <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
      </el-option>
    </el-select>
  </div>
  <!-- <a-radio-group v-if="type == 'radio'" v-model="node" :options="options" :disabled="disabled" />
  <a-checkbox-group v-else-if="type == 'checkbox'" v-model="node" :options="options" :disabled="disabled" />
  <a-select v-else v-model="node" :options="options" :mode="(multiple) ? 'multiple' : 'default'" :disabled="disabled" :placeholder="placeholder" /> -->

</template>
<script>
import mixins from './model'
export default {
  mixins: [mixins],
  props: {
    options: {
      type: Array,
      default () {
        return [
          {
            value: '选项1',
            label: '黄金糕'
          }, {
            value: '选项2',
            label: '双皮奶'
          }, {
            value: '选项3',
            label: '蚵仔煎'
          }, {
            value: '选项4',
            label: '龙须面'
          }, {
            value: '选项5',
            label: '北京烤鸭'
          }
        ]
      },
    }
  }
};
</script>
<style lang="scss" scoped>
</style>

父组件中使用

          <Change v-model="valueData"></Change>

image.png