使用contenteditable=“true“改造div可编辑文本框
使用contenteditable="true"改造div可编辑文本框,并去除粘贴复制的格式问题
contenteditable=“true” 可编辑
contenteditable=“false” 禁止编辑
contenteditable=“plaintext-only” 可以让编辑区域只能键入纯文本 不建议使用兼容性不好
一:简单版
<template><div :contenteditable="contenteditable" class="contentAble" :placeholder="placeholder" @focus="isLocked = true" @blur="isLocked = false" @input="changeDivText($event)" @paste="optimizePasteEvent" v-html="content" />
</template><script>
export default {props: {placeholder: {type: String,default: '请输入内容'},value: {type: String,default: ''},contenteditable: {type: String,default: 'true'}},data() {return {content: this.value,isLocked: false}},watch: {'value'() {if (!this.isLocked || !this.content) {this.content = this.value}}},methods: {// 监听粘贴内容到输入框事件,对内容进行处理optimizePasteEvent(e) {e.stopPropagation()e.preventDefault()let text = ''; const event = (e.originalEvent || e)if (event.clipboardData && event.clipboardData.getData) {text = event.clipboardData.getData('text/plain')} else if (window.clipboardData && window.clipboardData.getData) {text = window.clipboardData.getData('text')}if (document.queryCommandSupported('insertText')) {document.execCommand('insertText', false, text)} else {document.execCommand('paste', false, text)}},// 获取内容changeDivText(e) {this.$emit('input', e.target.innerHTML)}}
}
</script><style lang="scss" scoped>
.contentAble{border-radius: 10px;border: 1px solid #dcdfe6;padding: 20px;min-height: 200px;&:empty::before {content: attr(placeholder);color: #c0c4cf;}
}
</style>
使用例子
import CanableText from '@/components/CanableText'
<CanableText v-model="content" placeholder="请输入内容" />
二:升级版(可插入图片或者粘贴图片)
<template><div><divref="editor":contenteditable="contenteditable"class="contentAble":class="{uploadImage:uploadImage}":placeholder="placeholder"@focus="isLocked = true"@blur="isLocked = false"@input="changeDivText($event)"@paste.prevent="handlePaste"v-html="content"/>//插入图片封装组件,代码太长,根据自己需求编写旧不展示了<EditorImage v-if="uploadImage" ref="EditorImage" @successCBK="imageSuccessCBK"><template v-slot:button><el-button class="blueBorBtn insetImg" @click="insertImg">插入图片</el-button></template></EditorImage></div>
</template><script>
import EditorImage from '@/components/Tinymce/components/EditorImage'
export default {components: { EditorImage },props: {placeholder: {type: String,default: '请输入内容'},value: {type: String,default: ''},contenteditable: {type: Boolean,default: true},imgShowWidth: { // 聊天输入框中粘贴的图片显示的宽度type: Number,default: 60},imgShowHeight: { // 聊天输入框中粘贴的图片显示的高度type: Number,default: 60},uploadImage: {type: Boolean,default: false}},data() {return {content: this.value,isLocked: false}},watch: {'value'() {if (!this.isLocked || !this.content) {this.content = this.value}}},methods: {async handlePaste(event) {const pasteResult = this.optimizePasteEvent(event)if (pasteResult) returnawait this.handlePasteImageFile(event.clipboardData)},// 监听粘贴文本到输入框事件,对内容进行处理optimizePasteEvent(e) {e.stopPropagation()e.preventDefault()let text = ''; const event = (e.originalEvent || e)if (event.clipboardData && event.clipboardData.getData) {text = event.clipboardData.getData('text/plain')} else if (window.clipboardData && window.clipboardData.getData) {text = window.clipboardData.getData('text')}if (document.queryCommandSupported('insertText')) {document.execCommand('insertText', false, text)} else {document.execCommand('paste', false, text)}if (text) return truereturn false},// 粘贴图片(可以粘贴图片路径显示图片在文本框中)async handlePasteImageFile(clipboardData) {const img = this.getPasteImageFile(clipboardData.files)if (!img) return//这段代码为上次图片接口结果得到的路径,根据自己需求编写//this.uploadFileList = [{// raw: img,// size: img.size,// name: img.name,// chunkList: [],// status: this.FileStatus.wait,// progressStatus: 'warning',// uploadProgress: 0//}]//this.uploadFileList.length && this.submitUpload(async result => {// if (!result) {// return this.$message.error('图片上传失败,请重新上传')// }const oImage = await this.getImageObject(result, this.imgShowWidth, this.imgShowHeight)this.cursorInsert(oImage)this.changeDivText()// })},getPasteImageFile(clipboardDataFiles) {if (!clipboardDataFiles.length) {// console.log('没有要粘贴的文件')return null}// 剪切版中选择的(用户第一个点的在尾)第一张图片const clipboardDataFileList = Array.from(clipboardDataFiles || [])let firstSelectedImage = nullclipboardDataFileList.forEach(file => {if (!file.type.match(/image\//i)) {return}firstSelectedImage = file})/*** 这里的 firstSelectedFile 对象就是和 <input type="file" /> onchange 时 一样的 文件对象* */return firstSelectedImage},// 获取一个 image objectgetImageObject(uploadRes, showWidth, showHeight) {const oImage = new Image(showWidth, showHeight)oImage.src = uploadRes.urlreturn oImage},// 光标处插入节点cursorInsert(node) {// 获取光标范围if (window.getSelection()) {this.focus()}const selObj = window.getSelection()const range = selObj.getRangeAt(0)// 光标处插入节点range.insertNode(node)// 取消insert node 后的选中状态,将光标恢复到 insert node 后面range.collapse(false)},// 输入框 焦点focus() {this.$refs.editor.focus()},// 插入图片insertImg() {this.$refs.EditorImage.show()},// 获取上传的图片路径imageSuccessCBK(arr) {arr.forEach(async res => {const oImage = await this.getImageObject(res, this.imgShowWidth, this.imgShowHeight)this.cursorInsert(oImage)this.changeDivText()})},/*** 删除所有标签属性,支持忽略标签* @param {*} str 字符串文本* @param {*} ignoreArr 要忽略的标签*/deleteTagAttr(str, tagArr) {if (typeof str !== 'string') returnconst reg = new RegExp(`<(?:(${tagArr.join('|')}))(.*?)(?:>|\/>)`, 'gi')return str.replace(reg, mstr => {return mstr.replace(/(<[A-z]+)(.*)?(\/?>)/gi, '$1$3')})},// 获取内容,需求需要html外层添加div标签,没要求直接获取this.$refs.editor.innerHTML即可changeDivText() {const html = this.$refs.editor.innerHTMLconst newHtml = html.substring(1, 4) === 'div' ? html : this.deleteTagAttr(this.$refs.editor.outerHTML, ['div'])this.$emit('input', newHtml)}}
}
</script><style lang="scss" scoped>
.contentAble{border-radius: 10px;border: 1px solid #dcdfe6;padding: 20px;min-height: 200px;word-break: break-all;overflow: hidden;position: relative;&:empty::before {content: attr(placeholder);color: #c0c4cf;}
}
.uploadImage{padding: 20px 20px 70px 20px
}
.insetImg{position: absolute;right: 30px;bottom: 30px;
}
</style>
使用例子:
import CanableText from '@/components/CanableText'
<CanableText v-model="content" placeholder="请输入内容" :uploadImage="true" />
显示结果:
使用contenteditable=“true“改造div可编辑文本框相关推荐
- div模拟textarea文本框,输入文字高度自适应,且实现字数统计和限制
需求: 文本框可根据输入内容高度自适应,不带滚动条,高度可变的那种,我搜索了很多,发现textarea无法实现我的需求,scrollHeigh这个无法获取实际内容的高度(我用的是那种简单的,可能我写的 ...
- 仿淘宝图片空间 点击文字 出现可编辑文本框 提交ajax数据到后台修改
思路来源:昨天看淘宝的图片空间,发现了一个效果. 点击宝贝的名字,出现一个可编辑的文本框,然后ajax提交(如果数据变的话),改变数据 看图说明: 编辑完了提交进行修改数据 自己做的代码效果如下: 具 ...
- gui设置可编辑文本框的回调函数_用Tkinter制作Python程序的图形用户界面(GUI),打包后比Qt5减少60M(77.5%)(实例63)...
实例61使用PyQt5制作了图形用户界面(GUI).这个香是香,但是打包后的安装文件太大(约80M),感觉有些美中不足啊.由于这个GUI实在简单,从现实角度实在用不着高大上的PyQt5,所以改用Pyt ...
- pdf中如何编辑文本框
在word中插入文本框对于经常接触文档的人来说可谓是信手拈来,但是在pdf文档中要进行这个操作该怎么办呢?方法也很简单! 第一步,先到网上下载一个捷速pdf编辑器: 下载好之后将编辑器打开,并单击左上 ...
- 【MATLAB】在MATLAB中利用GUI编写加法计算器,要求:通过两个编辑文本框实现两个数字的输入,点击“开始计算”按钮进行计算,并在用于结果显示的静态文本框中实现两输入数字的和的显示
1)打开Matlab,点击工具栏上的[File]–>New–>GUI,命名为:addnum.fig 2)在addnum.fig面板里,拖曳3个静态文本TXT控件(不做任何修改).3个编辑 ...
- 富文本编辑器,可编辑div contentEditable=true,光标位置window.getSelection
在近期项目中,需要在一个实时通信软件中,在发送消息时支持发送加粗的消息,现在总结一下使用心得. 需求: 在发送消息时,点击加粗图标,图标添加选中效果,输入的文字.添加的文字表情.@人员都需要显示为加粗 ...
- vue可编辑div_vue2 如何实现div contenteditable=“true”(类似于v-model)的效果
发现问题 在 vue2 中对表单控件有着良好的双向数据绑定机制,但是对于要特定实现某些功能的输入时,我们就不得不使用到 contenteditable="true" 的 div , ...
- div模拟textarea文本域轻松实现高度自适应——张鑫旭
by zhangxinxu from http://www.zhangxinxu.com 本文地址: http://www.zhangxinxu.com/wordpress/?p=1362 一.关于t ...
- contenteditable属性让div也可以当做输入框
你知道div也可以当做输入框么? H5的全局属性contenteditable,带有contenteditable属性的div而不是input或者textarea来作为输入框(div可以根据内容自动调 ...
最新文章
- 《xUnit Test Patterns》学习笔记3 - Philosophy of Test Automation
- Java(三):序列化
- 做算法题时的一些小技巧
- [codevs 1743] 反转卡片
- android 使用AIDL实现进程间通讯
- JavaScript 如何打败众语言,成为 Node 的实现语言?
- 力扣题目——217. 存在重复元素
- plsql oracle client没有正确安装(plsql连接远程数据库)
- 求不规则立方体表面积java_不规则立方体体积计算
- PayPal支付配置
- html 转盘抽奖开发,html 大转盘抽奖
- CC2430基础——外部中断分析
- 软件测试非功能性需求,什么是非功能测试?非功能测试包括哪些类型?
- Linux HaProxy安装/启动/简单配置教程
- python--webdriver驱动浏览器操作(基础知识)
- Vue组件选项props
- 仿微信群聊头像(图像合成、缩放)
- (转载)深入分析HDFS原理及读写流程
- 【ubuntu】Ubuntu中Android NDK下载跟配置
- 校园快餐店网上订餐管理系统(JSP+MySQL+MyEclipse)