记录一下如何实现在文本中插入图片的功能

2,126 阅读1分钟

背景

产品要做一个类似豆瓣那样的发布功能,需要在文章插入图片,类似富文本编辑器,但其实又用不到那么多功能,于是决定自己开发

问题分析

  1. 如何让普通div可以编辑;
  2. 点击选择图片后如何记住光标的位置;
  3. 选择图片后如何插入到对应位置。
<template>
    <div>    
        <editor v-model="content" ref="myEditor"></editor>
    </div>
</template>
<script>
    import editor from '@/components/editor/index.vue';
    export default {
        name: "CommentPublish",
        components: {
            editor
        },
        data() {
            return {
                content: '',
            }
        },
        methods: {
            // 插入图片,实际中应该是上传完图片然后插入
            insertImg() {
                const HTML = `<div><img src="yourImage.png"></div>`
                this.$refs.myEditor.insert(HTML)
            }
        }
    }
</script>
/**
*   editor/index.vue
*/
<template>
    <div class="editor-wrap"
         v-html="editorHtml"
         ref="editor"
         contenteditable="true"
         @focus="isLocked = true"
         @blur="isLocked = false"
         @click="saveRange"
         @input="changeText">
    </div>
</template>

<script>
    export default {
        name: "editor",
        props: ['value'],
        data() {
            return {
                editorHtml: this.value,
                isLocked: false,
                range: ''
            }
        },
        watch: {
            'value'(val){
                if (!this.isLocked && !this.editorHtml) { // 解决光标错位的问题
                    this.editorHtml = val;
                }
            }
        },
        methods: {
            changeText() {
                this.$emit('input', this.$el.innerHTML);
                this.saveRange()
            },
            // 记录光标位置,本来是放在@blur里的,即失焦时记录光标位置;后面发现IOS下blur不能记录到,所以现在的做法是点击或者输入的时候记录
            saveRange() {
                const selection = window.getSelection ? window.getSelection() : document.getSelection()
                this.range = selection.getRangeAt(0)
            },
            // 设置焦点位置
            setRange() {
                const selection = window.getSelection ? window.getSelection() : document.getSelection()
                selection.removeAllRanges()
                if (this.range) {
                    selection.addRange(this.range)
                } else {
                    this.$refs.editor.focus()
                }
            },
            insert(html) {
                this.setRange()
                document.execCommand("insertHTML", false, html);
            }
        }
</script>