Vue中加载数据后自动调整文本区域的大小

Automatic resizing of textarea after loading data in Vue

我有一个 Vue 页面,它从 api 加载一个 json 数组,并使用 v-for 在多个 s 的列表中显示内容。

如果您关注其中一个文本区域或更改文本,一个函数会自动调整文本区域的大小以适应内容。

<div v-for="post in posts">
<textarea v-model="post.body" rows="1" @focus="resizeTextarea" @keyup="resizeTextarea"></textarea>
</div>

resizeTextarea(e) {
  let area = e.target;
  area.style.overflow = 'hidden';
  area.style.height = area.scrollHeight + 'px';
}

以我有限的 Vue 知识,我找不到在从 API 加载数据后自动调整所有文本区域大小的解决方案。文本区域上没有@load。

我试图通过对数据使用观察器来达到相同的目标,但感觉这是一个漫长的解决方法。

任何人都有下降解决方案?谢谢!

https://jsfiddle.net/oehoe83/c1b8frup/19/

一个解决方案是为您的 textarea 元素创建一个组件,然后在 mounted() 挂钩中调整它的大小。这是一个使用 single-file 组件的示例:

// CustomTextarea.vue
<template>
  <textarea
    v-model="value"
    ref="textarea"
    rows="1"
    @focus="resize"
    @keyup="resize"
  >
  </textarea>
</template>

<script>
  export default {
    props: {
      value: {
        type: String,
        required: true,
      }
    },
    mounted() {
      this.resize();
    },
    methods: {
      resize() {
        const { textarea } = this.$refs;
        textarea.style.height = textarea.scrollHeight - 4 + 'px';
      }
    }
  }
</script>

然后在你的 parent:

<template>
  <div v-for="post in posts">
    <CustomTextarea v-model="post.body" />
  </div>
</template>

<script>
  import CustomTextarea from './CustomTextarea.vue';

  export default {
    components: {
      CustomTextarea,
    }
    // etc.
  }
</script>

注意:如果您使用的是 Vue 3,请在 child 组件中将 value 替换为 modelValue

或者您可以像您建议的那样使用 watch,这没有任何问题。像这样:

watch: {
  posts() {
    // Wait until the template has updated
    this.$nextTick(() => {
      [...document.querySelectorAll('textarea')].forEach(textarea => {
        this.resizeTextarea({ target: textarea });
      });
    });
  }
}

您可以添加 ref 属性:

<div id="app">
    <div v-for="post in posts" ref="container">
        <textarea v-model="post.body" rows="1"@focus="resizeTextarea" @keyup="resizeTextarea" ></textarea>
    </div>
</div>

并在mounted()末尾添加如下代码:

this.$nextTick(()=>{
    this.$refs.container.forEach( ta => {
        ta.firstChild.dispatchEvent(new Event("keyup"));
    });
});