光标自动定位到起始位置contenteditable="true" ,v-html绑定内容,div可编辑时,光标移到最前面

出现这个问题原因:

(1)通过打断点可以看到,当你输入的时候触发input事件,提交值给父组件中的v-model;

(2)但因为在子组件中又监听了v-model的值,所以整体形成了闭环;

(3)还需要重点说明的是光标问题,contenteditable与v-html所在的元素值的改变如果不是通过输入而是通过赋值实现,光标就会跑到最前面;

所以以输入中文为例,你刚打了一个字母,立马就触发了监听与变动,光标移到最前面,自然无法完成整个正常的输入。

解决办法:

只有当blur的时候再做赋值操作(isChange为true),focus状态下不做赋值(isChange为false);

至于初始为true的原因是在父组件中直接给绑定的变量赋值时子组件中还是需要触发赋值的(isChange为true);

<!-- Created by dreamsqin on 2019/9/5 -->
<template>
  <div
    class="div-editable"
    contenteditable="true"
    v-html="innerText"
    @input="changeText"
    @focus="isChange = false"
    @blur="blurFunc"></div>
</template>

<script>
  export default {
    name: 'DivEditable',
    props: {
      value: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        innerText: this.value,
        isChange: true
      }
    },
    watch: {
      value() {
        if (this.isChange) {
          this.innerText = this.value
        }
      }
    },
    methods: {
      changeText() {
        this.$emit('input', this.$el.innerHTML)
      },
      blurFunc() {
        this.isChange = true
        this.$emit('blurFunc')
      }
    }
  }
</script>

<style lang="scss">
  .div-editable{
    width: 100%;
    height: 100%;
    overflow-y: auto;
    word-break: break-all;
    outline: none;
    user-select: text;
    white-space: pre-wrap;
    text-align: left;
    &[contenteditable=true]{
      user-modify: read-write-plaintext-only;
      &:empty:before {
        content: attr(placeholder);
        display: block;
        color: #ccc;
      }
    }
  }
</style>

解决办法:

只有当blur的时候再做赋值操作(isChange为true),focus状态下不做赋值(isChange为false);

至于初始为true的原因是在父组件中直接给绑定的变量赋值时子组件中还是需要触发赋值的(isChange为true);
父组件调用

<template>
  <div class="test-page">
    <div class="contain">
      <div-editable
        v-model="testContent"
        @blurFunc="blurHighLight"></div-editable>
      <el-input
        class="input-style"
        v-model="testContent"></el-input>
      <el-button
        class="button-style"
        @click="changeText">改变值</el-button>
    </div>
  </div>
</template>

<script>
  import DivEditable from '@/components/DivEditable'
  export default {
    name: 'TestPage',
    data() {
      return {
        testContent: 'dreamsqin'
      }
    },
    components: {
      DivEditable
    },
    methods: {
      blurHighLight() {
        // 这里做数据过滤或样式变更操作
      },
      changeText() {
        this.testContent = '【标签1】dreamsqin'
        this.blurHighLight()
      }
    }
  }
</script>

<style lang="scss">
  .test-page{
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    .contain{
      width: 600px;
      height: 250px;
      border: 2px solid #000;
      .input-style,.button-style{
        margin-top: 10px;
      }
      .text-blue{
        color: #2080F7;
      }
    }
  }
</style>

 

<div  ref="editableDiv" class="contain"  v-html="innerText" contenteditable="true"  @input="inputText" @blur="inputBlur" @focus="inputFocus"></div>

value: {
    type: String,
    default: ''
}

innerText: this.value,
isBlur: true,

watch: {
    value() {
        if (this.isBlur) {
            this.innerText = this.value
        }
    }
},

// 监听输入框内容
inputText() {
    /*this.$emit('input', this.$refs.editor.innerHTML);*/
    this.value = this.$refs.editableDiv.innerHTML;
},
inputFocus() {
    this.isBlur = false;
},
inputBlur() {
    this.isBlur = true;
},

 

参照原文:
https://www.cnblogs.com/dreamsqin/p/11466197.html
https://juejin.cn/post/7089030626229092359

posted @ 2024-03-03 21:34  BloggerSb  阅读(615)  评论(0编辑  收藏  举报