双击编辑文字,对于一些简单的需求就很简单,双击之后把div换成input,鼠标失去焦点之后隐藏input换回div就好了。
but
本文要讲的是复杂一点的需求,主要用于一些编辑系统,或者低代码平台的编辑文字组件,属于一种基础组件吧。
类似于这样:
总体思路其实很简单
花了个图:
有一些要点需要说明下:
有问题看代码吧:
<template>
<section class="element-box" :style="boxStyle">
<!-- 展示部分-->
class="show-text"
:style="textStyle"
v-if="!isEdit"
@dblclick="editText"
v-html="text"
></div>
<!-- 编辑部分-->
<div ref="text" class="textbox" v-if="isEdit">
class="textbox-container"
contenteditable="true"
@blur="updateText()"
id="textbox"
:style="textStyle"
v-html="text"
></div>
</div>
</section>
</template>
<script>
export default {
name: 'edit-text-test',
data() {
return {
isEdit: false,
text: '双击编辑文字',
boxInfo: {
width: 200,
height: 36
computed: {
//文字的样式
textStyle() {
return {
fontSize: '24px',
textAlign: 'center'
//容器的宽高
boxStyle() {
return {
width: this.boxInfo.width + 'px',
height: this.boxInfo.height + 'px'
methods: {
editText() {
this.isEdit = true
setTimeout(() => {
//选中文字
if (window.getSelection) {
let selection = window.getSelection()
let range = document.createRange()
range.selectNodeContents(document.getElementById('textbox'))
selection.removeAllRanges()
selection.addRange(range)
//粘贴时,去除多余格式
document
.getElementById('textbox')
.addEventListener('paste', e => {
e.preventDefault()
e.stopPropagation()
let text
let clp = (e.originalEvent || e).clipboardData
if (clp === undefined || clp === null) {
text = window.clipboardData.getData('text') || ''
if (text !== '') {
if (window.getSelection) {
let newNode = document.createElement('span')
newNode.innerHTML = text
window
.getSelection()
.getRangeAt(0)
.insertNode(newNode)
} else {
document.selection
.createRange()
.pasteHTML(text)
} else {
text = clp.getData('text/plain') || ''
if (text !== '') {
document.execCommand('insertText', false, text)
}, 100)
updateText() {
let modifiedText = this.$refs.text.childNodes[0].innerHTML
.replace(/<div><br></div>/g, '\n')
.replace(/<div.*?>/g, '\n')
.replace(/<br.*?>/g, '')
.replace(/</div>| |</?span.*?>/g, '')
this.isEdit = false
// 文字内容没修改不update
if (this.text !== modifiedText) {
if (modifiedText === '') modifiedText = '双击编辑文字'
this.text = modifiedText
this.updateBoxSize()
updateBoxSize() {
//更新下父容器的高度
this.boxInfo.height = document.getElementById(
'textbox'
).offsetHeight
</script>
<style lang="less" scoped>
.element-box {
position: relative;
.show-text {
word-break: break-all;
white-space: pre-line;
.textbox {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
.textbox-container {
width: 100%;
position: absolute;
border: 1px dashed #000;
height: auto;
word-break: break-word;
outline: none;
white-space: pre-wrap;
box-sizing: content-box;
-webkit-user-select: text !important;
user-select: text !important;
-webkit-background-clip: text;
caret-color: black;
</style>
双击编辑文字的逻辑大概都是这样的,我是用vue写的,其实可以很方便的改成react或者其他框架的语法。
希望本文可以解决一些人的需求。
写文本大约耗费了两局王者荣耀的时间,求一下点赞。
算了,不求赞了,这篇文章受众太小了,估计都没什么人看、就酱紫,写完收工。