vue开发中使用span替代input输入,兼容IE
2021-06-10 本文已影响0人
有你有团
以前开发中涉及到用户输入,一般使用input,textarea等html元素,当然这是最方便,最快捷的,偶然的一次项目中发现这两者不太好用,查了很多资料,结果还是不尽如人意,直到某次在度娘查到了一个html属性contenteditable
contenteditable 属性指定元素内容是否可编辑。
注意: 当元素中没有设置 contenteditable 属性时,元素将从父元素继承。
也就是说当元素设置 contenteditable 为true 那么当前元素可编辑
<p contenteditable="true">这是一个段落。是可编辑的。尝试修改文本。</p>
注意:此时该元素获取焦点时,该元素就可以进行编辑,和输入框一样的效果,但是它的值不是value而是innerText/innerHtml
说一下使用场景
在canvas上绘制文字时,我们需要实时绘制当前输入内容,刚开始使用场景是利用动态创建input元素,input获取焦点输入文字,当input失去焦点时绘制当前input的内容,功能可以实现,唯一不足就是我们需要输入框的大小按照输入内容的长度改变,使用input明显不太方便,可以使用动态改变size属性,如果输入的字母,数字,符合可以实现,当时如输入汉字的就会有问题,我们知道span等行内元素可以根据文字长度改变元素大小,所以,我们使用动态创建span标签,设置contenteditable="true",然后设置相应的样式,就可以模仿input输入框的效果
let span = document.createElement('span')
span.contenteditable=true
// 如果要创建完成后获取焦点需要使用setTimeout
setTimeout(function(){
span.focus()
},0)
vue组件封装
<template>
<span class="span-edit" :style="styleObj" :contenteditable="contenteditable" v-html="innerText" @focus="isFocus = true" @blur="isFocus = false" @keyup="inputHandle"></span>
</template>
<script>
export default {
name: 'EditInput',
props: {
value: {
type: String,
default: ''
},
contenteditable: {
type: Boolean,
default: true
}
},
data() {
return {
isFocus: false,
innerText: this.value
}
},
computed: {
styleObj() {
return {
'border-bottom': this.value ? 'none' : '1px solid #696969'
}
}
},
watch: {
value() {
// 解决光标跳动BUG
if (!this.isFocus) {
this.innerText = this.value
}
}
},
methods: {
// 如果使用元素input事件不兼容ie,无法获取到值,可以使用keyup代替,如果使用keydown ie浏览器会记录每一次按键(输入中文的时候)
inputHandle(e) {
let innerText = e.target.innerText
this.$emit('input', innerText)
}
}
}
</script>
<style lang="scss" scoped>
.span-edit {
outline: none;
// ie文字换行没有下划线
// border-bottom: 1px solid #000;
min-width: 25px;
display: inline-block;
font-size: 16px;
line-height: 20px;
word-break: break-all;
// 兼容ie写法
text-decoration: underline;
text-decoration-color: #696969;
}
</style>