如果利用textarea
的输入框,只能输入文本,无法输入图片等。比较好的方法是利用可编辑的div
进行实现。
div的可编辑
div
要完成可编辑,只需要设置contenteditable = "true"
即可实现。我们可以监听用户输入的区域,用户输入的时候,获取其中的innerText
,之后进行字数的限制判断,重新设置其innerHtML
,超出的字数显示成其他颜色。在提交之前,对表单进行预验证,要求用户删除多余的字符,方可提交给后端。
🍡可编辑的div
的难点在于光标难于控制,因此设置html
的时候利用两层div
重叠的方式进行解决
- 上层的
div
用于文本的输入,背景颜色透明 - 下层的
div
节点用于高亮超出的部分文字,文字颜色设置为透明,超出的部分设置背景颜色进行高亮
🌭 bug1:div
的高度自适应
<div class="box" contenteditable="true" ref="box"></div>
<div class="hightLight"></div>
.box{
width:400px;
min-height:200px; //实现自适应
max-height:400px;
margin-left:auto;
margin-right:auto;
padding:3px;
outline:none; // div在获取焦点的时候有虚框,让它消失
border:1px solid #dedede;
word-wrap:break-word;
overflow-x:hidden;
overflow-y:auto;
}
🌮bug2:输入框的placeholder
.box:empty::before{
content:attr(placehoder);
color:#dedede;
position:absolute;
}
之后就可以在html
中使用placeholder
属性。但是存在一些问题(点击回车的时候,会插入<div></div>
或者<br>
,这会导致一些问题,甚至影响到统计的字数)
解决办法:
1⃣ 通过JS
手动的添加、移除class
类处理placeholder
的显示与隐藏
.box.is-show-ploacehoder::before{
content:attr(placehoder);
color:#dedede;
position:absolute;
}
// JS
let box = this.refs.box
box.addEventListener('input', () => {
if (box.innerHTML === '<div><br></div>' ||
box.innerHTML === '<br>' ||
box.innerHTML === '') {
box.classList.add('is-showPlaceholder')
} else {
box.classList.remove('is-showPlaceholder')
}
})
2⃣ 第一层div
使用textarea
替换,textarea
中有placeholder
属性
🍅bug3:输入中文的统计字数
在中文输入的时候,中文还没有输入到输入框中的时候,字数已经在开始统计了,合理的是中文输入composing
组合的过程中不应该计算字数,在composed
组合完成输入到输入框中的时候再计算。composing
:在中文输入中,组合开始compsied
:在中文输入中,组合完成
let isComposing = false
editorArea.addEventListener('compositionstart', () => {
isComposing = true
})
editorArea.addEventListener('compositionend', () => {
isComposing = false
// 字数统计
let text = box.innerText
// 判断字数是否超出限制
setCounter(limitCnt - text.length)
})
🍌bug4:文件选择器于前端预览图片
古老的时候是无法直接在前端预览图片的,那时候借助的是ajax预先把图片发送给服务端,服务端返回图片的地址,前端利用img标签进行显示。不论用户需不需要上传该图片,该图片等会被上传到服务器中。
现在的做法:
fileReader
—>我不用-
URL.creatObjectURL
👈URL.creatObjectURL()
方法会创建一份DOMString对象,它包含url,这个url的生命周期跟创建它的窗口绑定,并且这个url就是操作的对象的映射地址(临时地址)
🍎bug5:拖动于前端预览图片<input type="file" accept="image/*" ref = 'imgFiles' @change="handleChange"> <img :src="srcImg"> handleChange(event){ const fileObj = event.files[0] //对于type="file" input.files[0]得到当前选中的file对象 const img = new Image() this.srcImg = file ? URL.createObjectURL(fileObj) : '' }
拖动是利用html5
中的drop
、drogover
、drogleave
方法
drogover:移进到了敏感区域,一直调用
注意:🔊需要阻止它们的默认方法,负责网页会自动打开该图片 DataTransfer
对象出现在拖拽事件中,具体包括开始拖拽dragstart
事件,拖拽进入dragenter
事件,拖拽离开dragleave
事件,拖拽经过dragover
事件,拖拽释放drop
事件以及拖拽结束dragend
事件。DataTransfer.items
(只读)
提供DataTransferItemList
对象,该对象是所有拖动数据的列表。
🍇bug6:@drogover = "handleDrogover" @drop= "handleDrop" handleDrogover(e){ e.preventDefault() e.stopPropagation() } handleDrop(e){ e.preventDefault() e.stopPropagation() const dt = e.dataTransfer const oFile = dt.item[0] // 文件对象 if(/image/.test(oFile.type)){// 判断是否为图片对象 const blod = new Blod([oFile ])// 生成Blod对象 const img = new Image() const imgSrc = URL.createObjectURL(blod)//URL.createObjectURL()可以处理File对象、Blod对象 img.src = imgSrc img.onload = function(){ box.appendChild(img) } } }
formData
传输多个文件let formData = new FormData() for(let i = 0;i<fileObj.length;i++){ formData.append('file[]',fileObj[i]) } // 不可以直接console.log(formData)---->需要利用formData.get([key])
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ZengXPang's blog!
评论