[Core Team RFC] New SFC macro: defineModel #503
Replies: 42 comments 99 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.
-
What are the use cases for |
Beta Was this translation helpful? Give feedback.
-
Very nice, it reminds me of how Aurelia just lets you write back into props to implement two-way bindings, great DX.
Speaking of |
Beta Was this translation helpful? Give feedback.
-
Examples show only usage with primitive types, how will it work with object props? Will it force (typewise) a factory for the default? const count = defineModel<{ foo: string }>('count', {
default: () => ({ foo: '' })
}) Will it emit? I guess at this stage no, but would you consider adding a const ob = defineModel({ foo: string }>();
ob.value.foo = 'foo'; // or <input v-model="ob.foo"> |
Beta Was this translation helpful? Give feedback.
-
I love this proposal for simple/standard cases because it can eliminate a bunch of boilerplate code, but I also am not a fan of the models now disappearing from the props definitions. I'm assuming (there's no example showing what it compiles down to, so I can't be certain) that I can still access the prop via prop.modelValue even if modelValue isn't defined in defineProps, right? In complex cases, where I need to watch the prop and not update the local ref in certain conditions, there's no way to hook into this, so I'd have to skip using this, right? |
Beta Was this translation helpful? Give feedback.
-
TS error "vue": "^3.3.1",
"vite": "^4.3.5", Type '{ defineModel: true; }' is not assignable to type 'Partial<Pick<SFCScriptCompileOptions, "babelParserPlugins">>'.
Object literal may only specify known properties, and 'defineModel' does not exist
in type 'Partial<Pick<SFCScriptCompileOptions, "babelParserPlugins">>' |
Beta Was this translation helpful? Give feedback.
-
export default defineConfig(
{
//... rest of configurations
plugins: [
vue({
script: {
defineModel: true,
propsDestructure: true,
},
}),
//... rest of plugins
]
} |
Beta Was this translation helpful? Give feedback.
-
Why not expose this idea as writable props? It's pretty simple to understand conceptually ( It would look something like: export default {
props: {
// New prop attribute: "model: true" or maybe "writable: true"
value: { type: Number, model: true },
},
setup(props) {
props.value = 100; // emits "update:value"
}
} |
Beta Was this translation helpful? Give feedback.
This comment has been hidden.
This comment has been hidden.
-
defineModel default has a "wrong" typescript definition. export function defineModel<T>(
options: { default: any } & PropOptions<T> & DefineModelOptions
): Ref<T> wouldn't it be better to just leave this out, so that the correct definition of PropOptions can be used ? |
Beta Was this translation helpful? Give feedback.
-
Anyone get this working in Storybook 7? Overriding the |
Beta Was this translation helpful? Give feedback.
-
Nothing much to add to the discussion other than I'm finding |
Beta Was this translation helpful? Give feedback.
-
should defineModel suppose to have a deep mode? It is convenient to bind vmodel with items of an array or object in v-for, for now, changes on item doesn't emit model event. |
Beta Was this translation helpful? Give feedback.
-
Might've asked this sometime before, can't rememeber when or where though, but when will this become stable? I'm just hoping it works by the time my code goes into production sometime in the distant future. |
Beta Was this translation helpful? Give feedback.
This comment was marked as disruptive content.
This comment was marked as disruptive content.
-
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.
-
defineModel
macro anduseModel
helper 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
.With
defineModel
, v-model props can be declared and mutated like a ref.<script setup>
only feature.update:propName
event.defineModel
, and it's disabled by default.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.
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.Demo
Drawbacks
N/A
Alternatives
defineModels
Declares multiple models in the same macro call. We opted for the single-model API for two reasons:
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.Adoption strategy
This is implemented and shipped as an experimental feature in 3.3 beta and requires explicit opt-in.
Vite
vue-cli
Requires
vue-loader@^17.1.1
Beta Was this translation helpful? Give feedback.
All reactions