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。
我试图通过对数据使用观察器来达到相同的目标,但感觉这是一个漫长的解决方法。
任何人都有下降解决方案?谢谢!
一个解决方案是为您的 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"));
});
});
我有一个 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。
我试图通过对数据使用观察器来达到相同的目标,但感觉这是一个漫长的解决方法。
任何人都有下降解决方案?谢谢!
一个解决方案是为您的 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"));
});
});