ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-04-14 16:05:31  阅读:465  来源: 互联网

标签:vue textarea refs 文本 height wrap txt trans 回车


先来几张简单图:

基本思路:

要想实现文本域跟随内容自动高度,这里准备两个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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有