首页 > 解决方案 > Vue.js Textarea在keyDown事件上调整大小,如何获取样式属性?

问题描述

我想为 Vue.js Textarea 组件复制autosize。而且我发现我无法获得几个属性的值:boxSizingpaddingToppaddingBottomborderTopWidthborderBottomWidth来计算heightOffset

const style = window.getComputedStyle(this.$refs.textarea, null);
if (style.boxSizing === 'content-box') {
  heightOffset = -(parseFloat(style.paddingTop + parseFloat(style.paddingBottom));
} else {
  heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
}

模板:

<textarea 
  class="answer" 
  ref="textarea"
  v-bind:placeholder="placeholder" 
  v-on:keydown="setHeight"
  v-bind:style="{ height: areaHeight + 'px' }"
>
</textarea>

在组件中:

data: function () {
  return {
    placeholder: "Your answer",
      areaHeight: 24
  }
},
methods: {
  setHeight: function(e) {
    var ta = this.$refs.textarea;

    console.log("ta.paddingTop: " + ta.paddingTop); //undefined
    console.log("ta.style.paddingTop: " + ta.style.paddingTop); //""
    console.log("ta.paddingBottom: " + ta.paddingBottom); //undefined
    console.log("ta.style.paddingBottom: " + ta.style.paddingBottom); //""

    console.log("ta.borderTopWidth: " + ta.borderTopWidth); //undefined
    console.log("ta.style.borderTopWidth: " + ta.style.borderTopWidth); //""
    console.log("ta.borderBottomWidth: " + ta.borderBottomWidth); //undefined
    console.log("ta.style.borderBottomWidth: " + ta.style.borderBottomWidth); //""

    this.areaHeight = this.$refs.textarea.scrollHeight;

    if (e.keyCode === 13) {
      this.areaHeight += 24;
    }
    if (e.keyCode === 8) {
      this.areaHeight -= 24;
      if(this.areaHeight <= 0) this.areaHeight = 24;
    }
}

标签: vue.jstextareavue-component

解决方案


我在Vue 论坛上问了这个问题,并根据建议找到了解决方案:

  (....)

  data: function () {
    return {
      placeholder: "Your answer",
      areaHeight: 24,
      style: null
    }
  },
  // https://vuejs.org/v2/api/#mounted
  mounted: function () {
    const self = this;
    self.$nextTick(function () {
      // Code that will run only after the
      // entire view has been rendered
      const style = window.getComputedStyle(this.$refs.textarea, null);
      self.style = style;
    })
  },
  methods: {
   setHeight: function(e) {
     //https://github.com/jackmoore/autosize/blob/master/src/autosize.js
     let heightOffset = null;
     var ta = this.$refs.textarea

     const style = this.style;

     if (style.boxSizing === 'content-box') {
       heightOffset = -(parseFloat(style.paddingTop)+parseFloat(style.paddingBottom));
     } else {
       heightOffset = parseFloat(style.borderTopWidth)+parseFloat(style.borderBottomWidth);
     }

     // Fix when a textarea is not on document body and heightOffset is Not a Number
     if ( isNaN(heightOffset) ) heightOffset = 0;         

     //ta.style.height = (ta.scrollHeight+heightOffset)+'px';


     //Vue Async Update Queue:
     this.$nextTick(function() {
       this.areaHeight = this.$refs.textarea.scrollHeight + heightOffset;
     });

     /*
     if (e.keyCode === 13) {
       this.areaHeight += 24;
     }
     if (e.keyCode === 8) {
       this.areaHeight -= 24;
       if(this.areaHeight <= 0) this.areaHeight = 24;
     }
     */

     //console.log(this.areaHeight);
   }
  }

推荐阅读