其他分享
首页 > 其他分享> > vue项目中文本域textarea跟随内容自动改变高度,并且阻止默认的回车换行事件

vue项目中文本域textarea跟随内容自动改变高度,并且阻止默认的回车换行事件

作者:互联网

先来几张简单图:

基本思路:

要想实现文本域跟随内容自动高度,这里准备两个textarea文本域,

文本域1:固定高度,超出部分滚动,设置绝对定位放到文本域2下面不做显示,但是注意不要设置为隐藏,否怎会读取不到宽高

文本域2:通过css设置初始宽高与文本域1一样,相对定位覆盖在文本域1上,使用vue的属性绑定 :style="{height: inputH + 'px'}" 动态的改变其高度,建议最低高度不低于文本域1的高度。

通过 v-model="source.txt" 将文本域2中输入的内容写入文本域1中,因文本域1固定高度超出滚动,然后通过vue的 watch 监听数据 source.txt 的变化,在监听中读取文本域1的滚动高度$refs.transInput0.scrollHeight 并设置文本域2的高度 this.inputH = this.$refs.transInput0.scrollHeight,为防止输入过程中出现频繁的高度变化造成闪烁设置延时 setTimeout(() => {}, 1000) 和 (tims - this.times < 1000),即停止输入1000ms后或两次输入间隔超过1000ms时才会进行高度的设置变化。

具体代码:

<template>
    <div class="part-top">
      <div class="trans-wrap layui-row">
        <div class="layui-col-md6 trans-left">
          <div class="input-wrap">
            <textarea ref="transInput0" v-model="source.txt" :class="['layui-textarea', 'txt0', {'more': source.txt.length > 23}]" />
            <textarea ref="transInput" v-model="source.txt" :class="['layui-textarea', 'txt', {'more': source.txt.length > 23}]" :style="{height: inputH + 'px'}" @keydown="interpretListen" />
            <span v-show="source.txt" class="layui-icon layui-icon-close" @click="clear()" />
          </div>
        </div>
        <div class="layui-col-md6 trans-right">
          <div ref="transOutput0" :class="['output-wrap', 'out0', {'more': target.txt.length > 25}]">
            <p>{{ target.txt }}</p>
          </div>
          <div ref="transOutput" :class="['output-wrap', {'more': target.txt.length > 25}]" :style="{height: outputH + 'px'}">
            <p>{{ target.txt }}</p>
          </div>
        </div>
      </div>
    </div>
</template>

<script>

export default {
  name: 'IdentifyPane',
  props: {
    name: {
      type: String,
      default: ''
    },
    moduleId: {
      type: String,
      default: ''
    },
    iUri: {
      type: String,
      default: ''
    },
    index: {
      type: Number,
      default: -1
    },
    enabled: {
      type: String,
      default: 'false'
    }
  },
  data() {
    return {
      // 初始化标识 完成后即为false
      isInit: true,
      // 是否显示当前模块
      isShow: false,
      datas: {},
      inputH: 130,
      outputH: 155,
      source: {
        flag: 'source',
        txt: ''
      },
      target: {
        flag: 'target',
        txt: ''
      },
      langsBox: {
        show: false,
        for: ''
      },
      times: 0,
      timeout: undefined
    }
  },
  watch: {
    // 动态监听数据是否变化
    'source.txt': function(newVal, oldVal) {
      // console.log(`new value -> ${newVal}\nold value -> ${oldVal}`)
      this.resetTransHeight()
    },
    'target.txt': function(newVal, oldVal) {
      // console.log(`new value -> ${newVal}\nold value -> ${oldVal}`)
      this.resetTransHeight()
    },
    isShow: function(newVal, oldval) {
      if (newVal) {
        setTimeout(() => {
          // console.log(`${this.$refs.transInput.offsetWidth} ->>>- ${this.$refs.transOutput.offsetWidth}`)
          this.$refs.transInput0.style.width = this.$refs.transInput.offsetWidth + 'px'
          this.$refs.transOutput0.style.width = this.$refs.transOutput.offsetWidth + 'px'
        }, 100)
      }
    }
  },
  created() {
    this.source.lang = this.languages[1]
    this.target.lang = this.languages[0]
    // console.log(this.source)
    // console.log(this.target)
    this.datas[this.moduleId] = []
  },
  mounted() {
  },
  methods: {
    showModule() {
      this.isShow = true
    },
    // 点击面板标题 显示(展开)/隐藏(收起)面板
    showHidePanel(index) {
      this.datas[this.moduleId][index]['isShow'] = !this.datas[this.moduleId][index]['isShow']
      this.$forceUpdate()
    },
    resetTransHeight() {
      const tims = new Date().getTime()
      if (!this.timeout) {
        this.timeoutReset()
      }
      if (this.times === 0) {
        this.times = tims
      } else {
        if (tims - this.times < 1000) {
          clearTimeout(this.timeout)
          this.timeoutReset()
          this.times = tims
        }
      }
    },
    timeoutReset() {
      this.timeout = setTimeout(() => {
        this.timeout = undefined
        const ish = this.$refs.transInput0.scrollHeight
        const osh = this.$refs.transOutput0.scrollHeight
        console.log(`input height -> ${ish}\noutput height -> ${osh}`)
        if (ish > osh) {
          this.inputH = ish
          this.outputH = ish + 25
        } else {
          this.inputH = osh - 25
          this.outputH = osh
        }

        this.times = 0
      }, 1000)
    },
    // 发送消息
    interpret() {
      console.log(`interpret ->>> `)
    },
    // 清空输入和翻译结果
    clear() {
      this.source.txt = ''
      this.target.txt = ''
    },
    // 文本输入默认回车换行改为发送消息
    interpretListen(event) {
      console.log(`key down interpret listen ->>>`)
      if (event.keyCode === 13) {
        this.interpret() // 调用发送消息
        event.preventDefault() // 阻止浏览器默认的换行操作
        return false
      }
    }
  }
}
</script>

<style scoped>
.trans-wrap {
    width: 100%;
    margin: 6px 0;
}

.trans-wrap .input-wrap,
.trans-wrap .output-wrap {
    width: 100%;
    padding: 10px;
}

.trans-wrap .input-wrap {
    border: 1px solid #dcdcdc;
}

.trans-wrap .input-wrap>textarea {
    resize: none;
    height: 130px;
    min-height: 100%;
    font-size: 22px;
    display: inline-block;
    width: calc(100% - 20px);
}

.trans-wrap .input-wrap>.layui-icon-close {
    top: 15px;
    right: 5px;
    width: 30px;
    display: inline-block;
}

.trans-wrap .output-wrap {
    background: #f0f0f0;
    font-size: 22px;
    height: 155px;
}

.trans-wrap .output-wrap.more,
.trans-wrap .input-wrap>textarea.more {
    font-size: 16px;
    line-height: 20px;
}

.trans-wrap .output-wrap::-webkit-scrollbar,
.trans-wrap .input-wrap>textarea::-webkit-scrollbar {  /* 滚动条整体样式 */
    display: none;
}

.trans-wrap .output-wrap.out0,
.trans-wrap .input-wrap>textarea.txt0 {
    position: absolute;
    min-height: unset;
    z-index: -1;
}
 /* 旋转180° */
  .rotate180 {
    transform: rotate(180deg);
    -ms-transform: rotate(180deg);  /* IE 9 */
    -moz-transform: rotate(180deg);   /* Firefox */
    -webkit-transform: rotate(180deg); /* Safari 和 Chrome */
    -o-transform: rotate(180deg);   /* Opera */
  }
</style>

 

每天进步一点点,点滴记录,积少成多。

以此做个记录,

如有不足之处还望多多留言指教!

标签:vue,textarea,refs,文本,height,wrap,txt,trans,回车
来源: https://www.cnblogs.com/jindao3691/p/16145026.html