• 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>

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

    以此做个记录,

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

  • 相关阅读:
    VMware安装Centos7超详细过程
    LVS+Keepalived小试牛刀
    Spring入门之AOP篇
    Spring学习笔记及资源
    Spring入门第一例
    Mybatis学习手记(二)
    Mybatis学习手记(一)
    java web 开发入门实例
    关于JAVA编译时找不到自定义包的问题
    Java 学习笔记及资源
  • 原文地址:https://www.cnblogs.com/jindao3691/p/16145026.html
Copyright © 2020-2023  润新知