[Core Team RFC] New SFC macro: defineModel
#503
[核心团队 RFC] 新 SFC 宏:defineModel #503
Replies: 42 comments 95 replies
-
Could we also consider doing the same for the Options API (which is still a popular way of writing components)? export default {
models: [
'foo', // name: 'foo', event: 'update:foo', required: false, default: undefined
{ name: 'value', event: 'updateValue', default: 0 },
{ name: 'bar', required: true }, // event: 'update:bar'
],
props: {
foo: String, // error: model is already declared
},
} We could then (finally) close #140. |
Beta Was this translation helpful? Give feedback.
-
It's definitely a very nice feature idea, but I think it has its drawbacks :
I think that something is missing to be very easy to understand for a newcomer. If we had different semantics for :
We could argue that this is, somehow, what we are doing here, but I feel like it's partially wrong: It would require a In an utopic world, without the need for backward compatibility, it would even make sense to me to not be able to define an emit such as Anyway, very interesting feature, that I will definitely use :). I'm not sure why it made me wonder about all this ^^. |
Beta Was this translation helpful? Give feedback.
-
How could this be confusing for newcomers? It's super easy, it's just a reference to the variable in the vmodel. Like writable props. Using emits is way harder far more unintuitive. And overuse? You either need it or you don't, how could you possibly use when you're not supposed to? |
Beta Was this translation helpful? Give feedback.
-
i recently come back learn coding and i pick vue, I'm quite headache with the how to create my custom input component. End up I use emit, then notice that definemodel is helpful. as user who not familiar with vue my first issue is props is immutable, is that anyway can use syntax like below? props = defineProps<{prop1:string, modelValue:{type:string, changable:true}}> then you guys run 'defineModel' behind the scene? Or there is another approach i feel workable: |
Beta Was this translation helpful? Give feedback.
-
How does defineModel handle v-model modifiers? Are v-model modifiers never used with defineModel? |
Beta Was this translation helpful? Give feedback.
-
Is it possible to use defineModel inside a component with v-for? <SchemaCollectionProvider v-for="schema in schemas" v-model:schema="schema" :key="schema.id">
<SchemaCard :schema="schema'/>
</SchemaCollectionProvider>
This is really simplified of course. Would the only option be to use a prop with event and do this? <script setup lang=ts>
const schemas = ref<SchemaCollectionModel[]>([])
function updateValue(index: number, schema: SchemaCollectionModel) {
schemas.value.splice(index, 1, schema)
}
</script>
<template>
<SchemaCollectionProvider v-for="(schema, i) in schemas" :schema="schema" :key="schema.id" @update:schema="(event) => updateValue(i, event)">
<SchemaCard :schema="schema">
</SchemaCollectionProvider>
</template> |
Beta Was this translation helpful? Give feedback.
-
@yyx990803 or somebody at Vue, could we please get an update on the status of this feature? It's been experimental for a long time now and we have not heard anything about it's future. There have been many patch updates since v3.3. I assume if it is kept we'll have to wait for v3.4? |
Beta Was this translation helpful? Give feedback.
-
I just want to share my feedback about this feature. Our team has been using it for about two months and it does make using v-model much more enjoyable, looking back defining props/emits before feels like boilerplate. I guess the only concern I have is that we always export our props interface, so other component consumers can extend it if needed. Since defineModel is separate thing it sometimes easy to miss, but you can still define modelValue prop and they do not clash, so that isn't major issue. |
Beta Was this translation helpful? Give feedback.
-
Overall, I think this is a nice addition. There are a few minor inconsistencies that can occur in local mode. Whether these are worth fixing I'm not sure, but if not then they might impact how the feature is documented. I think people will perceive The relevant Vue code that leads to these differences can be seen here: Problem 1 问题 1Consider this example: 请看这个例子: This uses If you change the example to Perhaps the local watcher should use Problem 2 问题 2The same example shows the second problem. This time, take a look at the value for With It could be argued that this is not an inconsistency, it's just what the Problem 3 问题 3This is the flip-side of the previous problem. Consider this example: 请看这个例子: The parent attempts to apply upper and lower bounds to the value. With Just to reiterate, I'm not necessarily suggesting that these inconsistencies need fixing, but I do think they're worth pondering. It might impact the documentation if nothing else. |
Beta Was this translation helpful? Give feedback.
-
To enable it in quasar, add the following line to quasar.config.js:
|
Beta Was this translation helpful? Give feedback.
-
If it's not a props:{
foo: {tyep: Number}
} |
Beta Was this translation helpful? Give feedback.
-
How do I approach this case where when I For example, I have a component that I need both the current and previous value because I have to compare them before doing other things. So I have this kind of component:
I also have a case where it isn't necessarily a previous value, but some other data. If I've approached this solution wrong even in the previous way, please correct me. |
Beta Was this translation helpful? Give feedback.
-
I'm having an issue with getting the same behaviour that I got with |
Beta Was this translation helpful? Give feedback.
-
Congratulations on the release of Vue 3.4! I find defineModel to be a very useful feature. However, I've also realized that defineModel can be props with non-one-way data flow. Consequently, it's important to encourage developers not to use v-model too much for data exchange between parent and child components. |
Beta Was this translation helpful? Give feedback.
-
Using defineModel with an array does not seem to work when splicing. model.value.splice(idx, 1) does not update the model. Is this intended?? 这是故意的吗? |
Beta Was this translation helpful? Give feedback.
-
I have a small issue with the trim Modifier: Example 示例Parent 家长<script setup>
import { ref } from 'vue'
import Child from 'Child.vue'
const testModel = ref("foo bar")
</script>
<template>
<Child v-model.trim="testModel" />
</template> Child 儿童<script setup>
const model = defineModel()
</script>
<template>
<input v-model="model" />
</template> If I Backspace 'bar' the cursor will jump to the end of 'foo' -- I would expect the result to be 'foo ' until blur. I've tried this in Playground with the same result. |
Beta Was this translation helpful? Give feedback.
The content you are editing has changed. Please copy your edits and refresh the page.
Nothing to preview
-
defineModel
macro anduseModel
helper core#8018实现 PR: feat(编译器-sfc):引入
defineModel
宏和useModel
辅助 core#8018Summary 摘要
This proposal introduces a new SFC macro called
defineModel
that enhances the developer experience when declaring two-way binding props to be consumed byv-model
.该提案引入了一个名为
defineModel
的新 SFC 宏,可在声明将由v-model
使用的双向绑定道具时增强开发者的体验。.With
defineModel
, v-model props can be declared and mutated like a ref.使用
defineModel
v 模型道具可以像 ref 一样声明和变异。<script setup>
only feature.宏仅具有
<script setup>
功能。update:propName
event.编译后,它将声明一个同名道具和一个相应的
update:propName
事件。defineModel
, and it's disabled by default.试验性功能。引入了一个新的编译器脚本选项
defineModel
,默认为禁用。Basic example 基本示例
Comp.vue
Parent.vue
Motivation 动机
Detailed design 详细设计
If the first argument is a string, it will be used as the prop name; Otherwise the prop name will default to "modelValue". In both cases, you can also pass an additional object which will be used as the prop's options.
如果第一个参数是字符串,它将被用作道具名称;否则,道具名称将默认为 "modelValue"。在这两种情况下,您还可以传递一个附加对象,作为道具的选项。
Local Mode 本地模式
The options object can also specify an additional option,
local
. When set totrue
, the ref can be locally mutated even if the parent did not pass the matchingv-model
, essentially making the model optional.选项对象还可以指定一个附加选项
local
。.设置为true
时设置为true
时,即使父节点没有通过匹配的v-model
,也可以对 ref 进行本地变异。时,即使父代没有通过匹配的v-model
,也可以对 ref 进行本地修改,从而使模型变得可有可无。Demo 演示
Drawbacks 缺点
N/A 不适用
Alternatives 替代品
defineModels 定义模型
Declares multiple models in the same macro call. We opted for the single-model API for two reasons:
在同一个宏调用中声明多个模型。我们选择单一模型 API 有两个原因:
It is more common for a component to declare only one model binding.
更常见的情况是,一个组件只声明一个模型绑定。
The default usage
defineModel()
, which omits the prop name, aligns with the parent usage ofv-model
, which omits the argument. This completely removes the need for themodelValue
prop name convention.默认用法
defineModel()
的默认用法与v-model
的父用法一致,后者省略了道具名称。一致,后者省略了参数。这样就完全不需要使用modelValue
的道具名称约定。Adoption strategy 采用战略
This is implemented and shipped as an experimental feature in 3.3 beta and requires explicit opt-in.
该功能在 3.3 测试版中作为实验功能实施和发布,需要明确的选择加入。
Vite 螺钉
vue-cli
Requires
vue-loader@^17.1.1
需要vue-loader@^17.1.1
Beta Was this translation helpful? Give feedback.