使用两个textarea
基本实现
如同下面这部分代码,这里就是用了两个textarea;一个textarea用来展示,一个textarea隐藏起来用来计算文本高度,并将计算后的高度赋予展示的textarea。首先是第一个show-textarea,这个是用来输入的,hidden-textarea就是用来计算高度的。将显示的textarea中的输入内容双向绑定到intervalue属性中,再通过监听input的事件将intervalue值赋给隐藏的textarea中,实现两个textarea内容同步。然后再计算hidden-textarea的scrollheight(这个包含padding,为了让演示更简单这里将padding设置为0),然后再将这个scrollheight传给show-textarea作为他的高度。这样就可以做到show-textarea的高度跟着内容增多而变高。
<template>
<div id="app">
<textarea
ref="textarea"
class="textarea show-textarea"
v-model="intervalue"
@input="handleInput"
>
</textarea>
<textarea
ref="hiddentextarea"
class="hidden-textarea textarea"
>
</textarea>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
intervalue: ''
}
},
methods: {
handleInput(e) {
this.$refs.hiddentextarea.value = e.target.value;
this.$refs.textarea.style.height = `${this.$refs.hiddentextarea.scrollHeight}px`
}
}
}
</script>
<style>
.textarea {
box-sizing: content-box;
resize: none;
padding: 0;
position: relative;
}
.show-textarea {
width: 440px;
overflow: auto;
}
.hidden-textarea {
overflow: hidden;
position: absolute;
width: 440px;
height: auto;
}
</style>
如果要设置一个最大高度呢?
上面这种方式只是解决了最基本的要求,如果我们希望给他设置一个最大高度呢?比如像那些组件库,可以设置最多的行数那样子!我们就需要设置行高和行数,并且根据输入内容的长度限制textarea的滚动条状态。例如下面的这个样子。
这里增加的代码是通过showScroll属性来控制是否允许滚动条展示,以及在高度达到属性row的高度以后就定死show-textarea的高度为row * lineheight。
<template>
<div id="app">
<textarea
ref="textarea"
class="textarea show-textarea"
:class="[showScroll ? 'show-scorll' : 'hide-scorll']"
v-model="intervalue"
@input="handleInput"
>
</textarea>
<textarea
ref="hiddentextarea"
class="hidden-textarea textarea"
>
</textarea>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
intervalue: '',
row: 5,
showScroll: false,
}
},
methods: {
handleInput(e) {
this.$refs.hiddentextarea.value = e.target.value;
this.showScroll = false
if (this.$refs.hiddentextarea.scrollHeight < this.row * 22) {
this.$refs.textarea.style.height = `${this.$refs.hiddentextarea.scrollHeight}px`
} else {
this.showScroll = true
this.$refs.textarea.style.height = `${this.row * 22}px`
}
}
}
}
</script>
<style>
.textarea {
box-sizing: content-box;
resize: none;
line-height: 22px;
position: relative;
padding: 0;
}
.show-textarea {
width: 440px;
overflow: auto;
}
.show-scorll {
overflow: auto;
}
.hide-scroll {
overflow: hidden;
}
.hidden-textarea {
overflow: hidden;
position: absolute;
width: 440px;
height: auto;
}
</style>
如果最后还要加一个初始高度呢?
这样的话只需要在最上面的基础上,在style里面加上一点点,再在handleInput方法里面加一点点的处理就好了。直接看代码。
首先在style里面加上height: 66px,这是3行的初始高度。
.textarea {
box-sizing: content-box;
resize: none;
line-height: 22px;
position: relative;
padding: 0;
height: 66px;
}
然后再改一下handleInput方法,当hide-textarea的内容高度大于66px的时候才执行高度变化的部分,如果小于等于66px则直接将高度定为66px。
handleInput(e) {
this.$refs.hiddentextarea.value = e.target.value;
this.showScroll = false
if (this.$refs.hiddentextarea.scrollHeight > 66) {
if (this.$refs.hiddentextarea.scrollHeight < this.row * 22) {
this.$refs.textarea.style.height = `${this.$refs.hiddentextarea.scrollHeight}px`
} else {
this.showScroll = true
this.$refs.textarea.style.height = `${this.row * 22}px`
}
} else {
this.$refs.textarea.style.height = `${66}px`
}
}