【问题标题】:Automatic resizing of textarea after loading data in Vue在 Vue 中加载数据后自动调整 textarea 的大小
【发布时间】:2021-02-01 17:17:29
【问题描述】:

我有一个 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 加载数据后自动调整所有 textarea 大小的解决方案。 textarea 上没有 @load。

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

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

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

【问题讨论】:

    标签: javascript vue.js asynchronous resize textarea


    【解决方案1】:

    一种解决方案是为您的textarea 元素创建一个组件,然后在mounted() 挂钩中调整它的大小。下面是一个使用单文件组件的例子:

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

    然后在你的父母中:

    <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,请将子组件中的 value 替换为 modelValue

    或者,您可以按照您的建议使用watch,这没有什么问题。像这样的:

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

    【讨论】:

    • 你应该使用 vuejs ref 而不是 [...document.querySelectorAll('textarea')] 或者如果你不想在你的 vuejs 组件之外定位 textarea,那么使用自定义 css 选择器更精确
    • 谢谢!两者都是不错的选择。就我而言,我只有想要调整大小的文本区域,因此它可以完美运行。
    【解决方案2】:

    您可以添加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"));
        });
    });
    

    【讨论】:

    • 你可以在这里测试jsfiddle.net/vtz1gwh3
    • 这是最好的解决方案。谢谢!但是现在我使用 Hannah 她的第二个答案,因为在实际情况下,textarea 嵌套在 MDBTextarea 中,比 v-for 低几级。我必须阅读 refs 功能才能在我自己的情况下实现它。
    猜你喜欢
    • 2021-11-25
    • 1970-01-01
    • 2023-02-09
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    相关资源
    最近更新 更多