Vue中使用contenteditable属性撸一个可以自动手动换行的输入框
写在前面有时候页面上需要一个类似于微信中发送消息的输入框,即可以实现:默认只有一行文字高度,用户输入超过自动换行,用户也可以点击Enter键盘换行,当输入的内容清空后,输入框又恢复成一行的高度,原生的输入框input和文本框textarea无法实现以上功能,所以就自己写了一个,采用HTML5的contenteditable属性,可以完美实现:1、自动换行及手动换行;2、双向绑定;3、类似于...
·
写在前面
有时候页面上需要一个类似于微信中发送消息的输入框,即可以实现:默认只有一行文字高度,用户输入超过自动换行,用户也可以点击Enter键盘换行,当输入的内容清空后,输入框又恢复成一行的高度,原生的输入框input和文本框textarea无法实现以上功能,所以就自己写了一个,采用HTML5的contenteditable属性,可以完美实现:
1、自动换行及手动换行;
2、双向绑定;
3、类似于textarea中的rows属性;
4、maxlength属性;
5、placeholder属性
复制代码到Vue项目中即可预览
效果图
子组件代码
<template>
<div class="textarea-wrap">
<div
class="mTextarea"
ref='mTextarea'
@input="input"
:style="style"
contenteditable="true"
:placeholder="placeholder"
></div>
</div>
</template>
<script>
export default {
props: {
// 输入提示,非必传
placeholder: String,
// 最大字数,非必传
maxlength: {
type: Number,
default: 99999
},
// 行数,非必传
rows: {
type: Number,
default: 6
},
// 字体大小,非必传
fontSize: {
type: Number,
default: 28
},
// 行高,非必传
lineHeight: {
type: Number,
default: 1.4
},
// 值,必传
value: String
},
computed: {
style () {
return {
fontSize: this.fontSize / 75 + 'rem',
lineHeight: this.lineHeight,
maxHeight: this.rows * this.fontSize / 75 * this.lineHeight + 'rem'
}
}
},
data () {
return {
mTextarea: null
}
},
watch: {
value () {
// 清空
if (!this.value) {
this.mTextarea.innerText = ''
}
}
},
mounted () {
this.$nextTick(() => {
this.mTextarea = this.$refs.mTextarea
// 回显
this.mTextarea.innerText = this.value
})
},
methods: {
input (event) {
let innerText = this.mTextarea.innerText
// 限制输入
if (innerText.length >= this.maxlength) {
innerText = innerText.substring(0, this.maxlength)
this.mTextarea.innerText = innerText
// 设置光标到最后
this.setFocus()
}
if (this.mTextarea.innerText.length === 1 && this.mTextarea.innerHTML.includes('br')) {
this.mTextarea.innerText = ''
innerText = ''
}
this.$emit('input', innerText)
},
// 设置光标到最后
setFocus () {
var selection = window.getSelection()
var range = document.createRange()
range.selectNodeContents(this.mTextarea)
range.collapse(false)
selection.removeAllRanges()
selection.addRange(range)
}
}
}
</script>
<style lang="less" scoped>
.textarea-wrap{
background: #f8f8f8;;
padding: 24/75rem;
border-radius: 2px;
font-size: 0;
&:active{
background: #eee;
}
.mTextarea{
width: 100%;
display: inline-block;
outline: none;
overflow: auto;
// 加了可实现纯textarea功能,不加则像富文本一样可以写入css样式和HTML标签
user-modify: read-write-plaintext-only;
-webkit-user-modify: read-write-plaintext-only;
// 必须加,不然移动端有些浏览器无光标
user-select: auto;
-webkit-user-select: auto;
// placeholder属性
&:empty:before{
content:attr(placeholder);
font-size: 28/75rem;
color: #999;
}
}
}
</style>
父组件调用代码
<template>
<div class="wrap">
<m-textarea v-model="value" placeholder='请输入评论' :rows='6' :maxlength='200'/>
<p>输入的内容:{{value}}</p>
<button @click="value = ''">清空</button>
</div>
</template>
<script>
import MTextarea from './MTextarea'
export default {
components: {
MTextarea
},
data () {
return {
value: ''
}
}
}
</script>
<style lang="less" scoped>
// 可删除
.wrap{
background: #fff;
padding: 30/75rem;
p{
padding: 30/75rem 0;
font-size: 30/75rem;;
line-height: 1.4;
}
button{
padding:12/75rem 20/75rem;
background: #ff6633;
color: #fff;
font-size: 26/75rem;
border-radius: 4px;
}
}
</style>
觉得有用就给我点个赞吧,蟹蟹,(●ˇ∀ˇ●)
个人联系方式(添加请备注):
QQ:332983810
微信:hu_jiliang
更多推荐
已为社区贡献8条内容
所有评论(0)