产品要作一个相似豆瓣那样的发布功能,须要在文章插入图片,刚接到这个需求时,一脸懵逼。没办法,为了糊口,在看了一些大佬的文章后,终于实现了。废话很少说,直接上代码!javascript
// parent.vue
<template>
<div>
<editor v-model="content" ref="myEditor"></editor>
</div>
</template>
<script>
import editor from "@/components/editor";
export default {
name: "CommentPublish",
components: {
editor
},
data() {
return {
photoPng,
commentBanner,
title: '',
content: '',
fileList: []
}
},
methods: {
// 插入图片,实际中应该是上传完图片而后插入
insertImg() {
const HTML = `<div><img src="yourImage.png"></div>`
this.$refs.myEditor.insert(HTML)
}
}
}
</script>
复制代码
// child.vue
<template>
<div class="editor-wrap"
v-html="editorHtml"
ref="editor"
contenteditable="true"
@focus="isLocked = true"
@blur="isLocked = false" // IOS下blur不能获取光标位置,因此舍弃
@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()
},
// 失焦时记录焦点位置
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>
复制代码