[英]Vue3 use v-model in Child Components
I just found out that in Vue3, v-model
is not working responsively / reactively with child Component
.我刚刚发现在 Vue3 中,
v-model
不能响应式地/响应式地与子Component
一起工作。
This code will update the username
data此代码将更新
username
数据
<template>
<div>
<input type="text" v-model="username" placeholder="Insert your username" />
<p>{{ username }}</p>
</div>
</template>
<script>
// Home.vue
export default {
name: 'Home',
data() {
return {
username: 'admin'
}
}
}
</script>
If I type something in the input
, the username
data will change too.如果我在
input
中输入一些东西, username
数据也会改变。
But, when I use Component
like this example:但是,当我像这个例子一样使用
Component
时:
<template>
<input type="text" :class="'input-text ' + additionalClass" :placeholder="placeholder" />
</template>
<script>
// InputText.vue
import { defineComponent } from "vue"
export default defineComponent({
name: 'InputText',
props: {
placeholder: {
type: String,
default: ''
},
additionalClass: {
type: String,
default: ''
}
}
})
</script>
Then I updated my code to use the Component
.然后我更新了我的代码以使用
Component
。
Note: The Component
is registered successfully.注意:
Component
注册成功。
<template>
<div>
<input-text v-model="username" :placeholder="`Insert your username`" />
<p>{{ username }}</p>
</div>
</template>
<script>
// Home.vue
export default {
name: 'Home',
data() {
return {
username: 'admin'
}
}
}
</script>
When I type something, the username
data not updated, different with the previous one.当我键入内容时,
username
数据未更新,与前一个不同。
Is there any solution or at least reference of what I'm trying to achieve?是否有任何解决方案或至少参考我想要实现的目标?
You can't expect v-model
to implicitly update the underlying element for you.您不能期望
v-model
为您隐式更新底层元素。 In other words, you'll still need to handle that within the component itself and expose modelValue
as a prop for this to really work.换句话说,您仍然需要在组件本身中处理它,并将
modelValue
作为一个 prop 公开它才能真正起作用。 Something like that:像这样的东西:
<template>
<input
type="text"
@input="onChanged"
:value="modelValue"
:class="'input-text ' + additionalClass"
:placeholder="placeholder" />
</template>
<script>
// InputText.vue
import { defineComponent } from "vue"
export default defineComponent({
name: 'InputText',
emits: ['update:modelValue'],
props: {
modelValue: String,
placeholder: {
type: String,
default: ''
},
additionalClass: {
type: String,
default: ''
}
},
setup(props, { emit }) {
function onChanged(e) {
emit('update:modelValue', e.currentTarget.value);
}
return {
onChanged
}
}
})
</script>
with Vue3 script setup
syntax使用 Vue3
script setup
语法
<template>
<input type="text" v-model="val" @input="handleInput">
</template>
<script setup>
import {ref, defineProps, defineEmit} from 'vue'
const props = defineProps({
modelValue: {
type: String,
default: ''
},
})
const emit = defineEmit(['update:modelValue'])
const val = ref(props.modelValue)
const handleInput = () => emit('update:modelValue', val.value)
</script>
The VueUse helper useVModel
can simplify handling v-model
in a sub-component, see https://vueuse.org/core/usevmodel/#usage VueUse helper
useVModel
可以简化子组件中v-model
的处理,参见https://vueuse.org/core/usevmodel/#usage
<script lang="ts" setup>
import { useVModel } from '@vueuse/core'
const props = defineProps<{
modelValue: string
}>()
const emit = defineEmits(['update:modelValue'])
const model = useVModel(props, 'modelValue', emit)
</script>
<template>
<input type="text" v-model="model" />
</template>
with OPTIONS API
syntax使用
OPTIONS API
语法
<template>
<input type="text" v-model="val" @input="updateText" :value="modelValue">
</template>
<script scoped>
export default {
props: {
modelValue: String,
},
methods: {
updateText(event){
this.$emit('update:modelValue', event.currentTarget.value)
}
}
}
</script>
In vue2, this thing worked:在 vue2 中,这件事起作用了:
Your InputText component您的 InputText 组件
<template>
<input :value="value"
@input="({target}) => $emit('input', target.value)"/>
</template>
<script>
export default {
props: {
value: {}
}
}
Your parent component你的父组件
<template>
<inputText v-model="inputValue"/>
</template>
<script>
export default {
components: {inputText},
data: () => ({
inputValue: null
})
}
</script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.