前言
上一篇封装了可编辑div组件–挺好用的可编辑div组件(一),这一篇将讲解应用可编辑div的注意事项。
环境
- vue2.5
- webpack3.6
- element-ui2.4.6
事件和快捷键
下面代码中添加了input
、blur
、focus
事件和键盘快捷键,可以实时的监听 checkHtml
的改变。
<!--HelloWorld.vue-->
<template>
<div class="content">
<div>
<button @click="onChangeVal">改变可编辑div的值</button>
<base-edit-div
ref="editDiv"
class="beautiful"
:text="checkHtml"
v-model="checkHtml"
@input="changeText"
@blur="onBlur"
@focus="onFocus"
@keydownTab="onKeydownTab"
>
</base-edit-div>
</div>
<el-popover
ref="popover"
placement="top-start"
trigger="manual"
width="200"
v-model="visible">
<el-button type="info" size="mini" stle="margin-left:0;" @click="onAddNoise">[噪音]</el-button>
</el-popover>
</div>
</template>
<script>
import BaseEditDiv from './BaseEditDiv'
const NOISE = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r'
export default {
components: {
BaseEditDiv
},
data () {
return {
checkHtml: '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r',
visible: false
}
},
methods: {
onChangeVal () {
this.checkHtml = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
},
onAddNoise () {
this.insertHtmlAtCaret(NOISE)
},
onKeydownTab (e) {
console.log('tab快捷点', e)
},
onFocus (e) {
this.visible = true
const target = e.target
let left = target.offsetLeft + 70
let top = target.offsetTop - 50
this.$refs.popover.$el.querySelector('.el-popper').style.cssText = `left:${left}px;top:${top}px`
console.log('获取焦点', e)
},
onBlur (e) {
this.visible = false
console.log('失去焦点', e)
},
changeText (innerHTML, index) {
console.log('input事件', innerHTML)
},
insertHtmlAtCaret (html) {
let sel, range
if (window.getSelection) {
sel = window.getSelection()
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0)
range.deleteContents()
let el = document.createElement('div')
el.innerHTML = html
let frag = document.createDocumentFragment()
let node
let lastNode
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node)
}
range.insertNode(frag)
if (lastNode) {
range = range.cloneRange()
range.setStartAfter(lastNode)
range.collapse(true)
sel.removeAllRanges()
sel.addRange(range)
}
}
} else if (document.selection && document.selection.type !== 'Control') {
// IE < 9
document.selection.createRange().pasteHTML(html)
}
}
}
}
</script>
<style lang="less" scoped>
.content{
margin: 50px auto;
.beautiful{
width: 300px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
border-radius: 4px;
border: 1px solid #ebeef5;
background-color: #fff;
overflow: hidden;
color: #303133;
transition: .3s;
}
}
</style>
效果如下:
然 checkHtml
的值都是我们手动输入改变的,那么如果我需要点击按钮后才改变 checkHtml
的值呢?通过操作,点击 改变可编辑div的值
按钮,依然没有变化。有两种解决办法:
- 操作可编辑div的innerHTML
onChangeVal () {
this.$refs.editDiv.$el.innerHTML = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
}
操作可编辑div组件的innerHTML会触发input事件,进而将改变了可编辑div组件的value值,并且v-model绑定的可编辑div组件正是获取的value值,故能实现改变可编辑div组件的值。
- 使用v-if
<base-edit-div
v-if="!loading"
ref="editDiv"
class="beautiful"
:text="checkHtml"
v-model="checkHtml"
@input="changeText"
@blur="onBlur"
@focus="onFocus"
@keydownTab="onKeydownTab"
>
</base-edit-div>
data () {
return {
checkHtml: '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r',
visible: false,
loading: false
}
},
methods: {
onChangeVal () {
// 方式一:操作可编辑div的innerHTML
// this.$refs.editDiv.$el.innerHTML = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
// 方式二:使用v-if
this.loading = true
this.checkHtml = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
setTimeout(() => {
this.loading = false
}, 0)
}
}
}
最后的代码如下:
<!-- HelloWorld.vue -->
<template>
<div class="content">
<div>
<button @click="onChangeVal">改变可编辑div的值</button>
<base-edit-div
v-if="!loading"
ref="editDiv"
class="beautiful"
:text="checkHtml"
v-model="checkHtml"
@input="changeText"
@blur="onBlur"
@focus="onFocus"
@keydownTab="onKeydownTab"
>
</base-edit-div>
</div>
<el-popover
ref="popover"
placement="top-start"
trigger="manual"
width="200"
v-model="visible">
<el-button type="info" size="mini" stle="margin-left:0;" @click="onAddNoise">[噪音]</el-button>
</el-popover>
</div>
</template>
<script>
import BaseEditDiv from './BaseEditDiv'
const NOISE = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r'
export default {
components: {
BaseEditDiv
},
data () {
return {
checkHtml: '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r',
visible: false,
loading: false
}
},
methods: {
onChangeVal () {
// 方式一:操作可编辑div的innerHTML
// this.$refs.editDiv.$el.innerHTML = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
// 方式二:使用v-if
this.loading = true
this.checkHtml = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
setTimeout(() => {
this.loading = false
}, 0)
},
onAddNoise () {
this.insertHtmlAtCaret(NOISE)
},
onKeydownTab (e) {
console.log('tab快捷点', e)
},
onFocus (e) {
this.visible = true
const target = e.target
let left = target.offsetLeft + 70
let top = target.offsetTop - 50
this.$refs.popover.$el.querySelector('.el-popper').style.cssText = `left:${left}px;top:${top}px`
console.log('获取焦点', e)
},
onBlur (e) {
this.visible = false
console.log('失去焦点', e)
},
changeText (innerHTML, index) {
console.log('input事件', innerHTML)
},
insertHtmlAtCaret (html) {
let sel, range
if (window.getSelection) {
sel = window.getSelection()
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0)
range.deleteContents()
let el = document.createElement('div')
el.innerHTML = html
let frag = document.createDocumentFragment()
let node
let lastNode
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node)
}
range.insertNode(frag)
if (lastNode) {
range = range.cloneRange()
range.setStartAfter(lastNode)
range.collapse(true)
sel.removeAllRanges()
sel.addRange(range)
}
}
} else if (document.selection && document.selection.type !== 'Control') {
// IE < 9
document.selection.createRange().pasteHTML(html)
}
}
}
}
</script>
<style lang="less" scoped>
.content{
margin: 50px auto;
.beautiful{
width: 300px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
border-radius: 4px;
border: 1px solid #ebeef5;
background-color: #fff;
overflow: hidden;
color: #303133;
transition: .3s;
}
}
</style>