v-model 实现原理, 自定义v-model 以及应用 对可编辑div实现双向数据绑定,解决光标在前和不能输入中文的问题

对于表单大家都很熟悉,v-model 大家也很喜欢,他确实很方便。那么他是怎么实现的呢, 其实他是一个语法糖, v-model 干了 两件事 下面以 input 为例

<input type="text" v-bind:value='message' @input='message = $event.target.value'>

等价于

<input type="text" v-model='message'>

对于自定义组件,我们也要实现双向绑定,对于可编辑div大家都了解,接下来我们来实现可编辑div的双向绑定

子组件:ContentEditable

<template>
  <div
    class="edit-div"
    v-html="innerText"
    :contenteditable="canEdit"
    @focus="isLocked = true"
    @blur="isLocked = false"
    @input="changeText"
    placeholder="请输入审批意见(必填)"
  ></div>
</template>
<script>
export default {
  name: "ContentEditable",
  props: {
    value: {
      type: String,
      default: ""
    },
    canEdit: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      innerText: this.value,
      isLocked: false
    };
  },
  watch: {
    value() {
      if (!this.isLocked || !this.innerText) {
        this.innerText = this.value;
      }
    }
  },
  methods: {
    changeText() {
      this.$emit("input", this.$el.innerHTML);
    }
  }
};
</script>
<style lang="scss">
.edit-div {
  width: 100%;
  height: 100%;
  overflow: auto;
  word-break: break-all;
  outline: none;
  user-select: text;
  white-space: pre-wrap;
  text-align: left;
  &[contenteditable="true"] {
    &:empty:before {
      content: attr(placeholder);
      display: block;
      color: #ccc;
    }
  }
}
</style>

调用:

<ContentEditable v-model="text" />
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章