英文:
Refs inside arrays unexpected behavior
问题
I am trying to use an v-model
with a custom component. More specifically I was using an v-for
to generate a list of elements based on infomations in an array. In practice, the components did not behave as I expected... the problem seems to arise from how the ref
(s) are treated and I can't find the reason for it nor a solution.
This is my test code, from which I expect the same result on both rows, but it doesn't:
// App.vue
<script setup>
import { ref } from 'vue'
import CustomInput from './CustomInput.vue'
const message = ref('hello')
const myArr = [message]
</script>
<template>
<CustomInput v-model="message" /> {{ message }}
<br/>
<CustomInput v-model="myArr[0]" /> {{ myArr[0] }}
</template>
// CustomInput.vue
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
I premise that I am new to Vue, and have only read a small part of the documentation at the moment, so I apologize if there is anything I missed that would allow a simple and obvious solution to the question.
I tried wrapping the array in a ref
or reactive
(read around) but it doesn't seem to work.
I am sure there are solutions such as hardcoding the components to solve my original problem. But mine is mainly an educational question, so the code shown above I think extrapolates well to the problem I'm interested in. Thank you in advance for your answers.
英文:
I am trying to use an v-model
with a custom component. More specifically I was using an v-for
to generate a list of elements based on infomations in an array. In practice, the components did not behave as I expected... the problem seems to arise from how the ref
(s) are treated and I can't find the reason for it nor a solution.
This is my test code, from which I expect the same result on both rows, but it doesn't:
// App.vue
<script setup>
import { ref } from 'vue'
import CustomInput from './CustomInput.vue'
const message = ref('hello')
const myArr = [message]
</script>
<template>
<CustomInput v-model="message" /> {{ message }}
<br/>
<CustomInput v-model="myArr[0]" /> {{ myArr[0] }}
</template>
// CustomInput.vue
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
I premise that I am new to Vue, and have only read a small part of the documentation at the moment, so I apologize if there is anything I missed that would allow a simple and obvious solution to the question.
I tried wrapping the array in a ref
or reactive
(read around) but it doesn't seem to work.
I am sure there are solutions such as hardcoding the components to solve my original problem. But mine is mainly an educational question, so the code shown above I think extrapolates well to the problem I'm interested in. Thank you in advance for your answers.
答案1
得分: 1
通常,在您的<template>
代码中使用的引用会自动“解封装”,因此v-model="message"
实际上变成了v-model="message.value"
,其中.value
是内部值'hello'
。
使用v-model="myArr[0]"
实际上是通过分配一个数组索引来隐藏它是引用的事实。在这种情况下,Vue 不会聪明到知道它是引用,这导致整个引用代理对象被分配给 v-model。这就是为什么您在输入框中看到[object Object]
而不是内部值的原因。简单的修复方法是通过指定.value
来自行解封装值。
<CustomInput v-model="myArr[0].value" /> {{ myArr[0].value }}
<details>
<summary>英文:</summary>
Normally a ref used in your `<template>` code is automatically "unwrapped", so `v-model="message"` actually becomes `v-model="message.value"`, where `.value` is the inner value `'hello'`.
With `v-model="myArr[0]"` you're basically hiding the fact that it's a ref by assigning an array index. Vue isn't _that_ smart to know it's a ref in this case, which results in the entire ref proxy object being assigned to the v-model. This is why you see `[object Object]` in the input instead of the inner value. The simple fix is to unwrap the value yourself by specifying `.value`
```html
<CustomInput v-model="myArr[0].value" /> {{ myArr[0].value }}
答案2
得分: 1
这不是Vue中的响应式变量,因此对于这种变量,将不可用于响应式渲染或更新。此外,您必须使用 message.value
来引用脚本中 message
ref 的值。
const myArr = [message]
如果您想使用多个输入并跟踪它们的输入,以下是一种解决方法:
<script setup>
import { ref } from 'vue'
import CustomInput from './CustomInput.vue'
const myArr = ref([
{id: 1, message: null, holder: "Holder1"},
{id: 2, message: null, holder: "Holder2"}
])
</script>
<template>
<CustomInput v-model="message" /> {{ message }}
<br/>
<template v-for="item in myArr" :key="item.id">
<CustomInput v-model="item.message" :placeholder="item.holder" />{{item.message || 'None'}}<br/>
</template>
</template>
<details>
<summary>英文:</summary>
This is not a reactive variable in Vue, so reactive rendering|update will not be available for such variable. Plus you have to use `message.value` to reference the value of `message` ref inside the script.
```js
const myArr = [message]
If you want to use multiple inputs and track their inputs here is one workaround:
<script setup>
import { ref } from 'vue'
import CustomInput from './CustomInput.vue'
const myArr = ref([
{id: 1, message: null, holder: "Holder1"},
{id: 2, message: null, holder: "Holder2"}
])
</script>
<template>
<CustomInput v-model="message" /> {{ message }}
<br/>
<template v-for="item in myArr" :key="item.id">
<CustomInput v-model="item.message" :placeholder="item.holder" />{{item.message || 'None'}}<br/>
</template>
</template>
Example at Vue Sfc Playground
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论