Comments (11)
Actually with v3's flat vnode data implementation, declaring props is unnecessary. When you pass data down it doesn't matter if it's a prop or not.
So the wrapper can simply do
<input v-bind="$attrs">
Regarding the input event re-emit, I kinda want to avoid this event vs. value mismatch altogether. Maybe the code v-model
generates should just handle both event and plain values. e.g. value = value instanceof Event ? value.target.value : value
from core.
Actually with v3's flat vnode data implementation, declaring props is unnecessary. When you pass data down it doesn't matter if it's a prop or not.
Yay! 😄
Regarding the input event re-emit, I kinda want to avoid this event vs. value mismatch altogether. Maybe the code
v-model
generates should just handle both event and plain values. e.g.value = value instanceof Event ? value.target.value : value
I think that'd be great, but I still feel like the default event for components should be update:value
. It's not only more consistent with other 2-way bindings, but also feels more semantically accurate for a component, since updates may be triggered by things other than "input" from the user (e.g. responses from an API, images loading, etc).
Making v-model
smarter with components
One other thing I think we need to really improve v-model
with components is detecting the kind of element that arbitrary attributes are passed through to. That way, v-model
can be as smart with components as it is with normal elements and always "just work", using the correct attribute and event. (This would also eliminate the need for the model
option on components.)
Otherwise, I worry it might be confusing if, depending on the element, v-bind="$attrs"
sometimes just works (e.g. <input type="text">
), but often doesn't work (e.g. <select>
, <input type="checkbox">
, etc). In my experience, most developers don't know the exact attributes and events necessary to work with every form element, so offering the same convenience for components that we do for elements would save a lot of development hours.
from core.
@chrisvfritz yeah, I agree regarding emitting update:value
instead. #8 also makes sense.
Making v-model
smart can be tricky, because we can't know at compile time what element the $attrs
will be spread on in the child component.
One possible implementation: v-model
generates code like this:
<input v-model="foo">
h('input', {
modelValue: this.foo,
'onUpdate:modelValue': value => {
this.foo = value
}
})
When used on a component:
- A component that expects to work with
v-model
should expect a propmodelValue
- To trigger update, it should emit an event named
update:modelValue
When used on an element, the runtime will dynamically transform modelValue
and update:modelValue
to appropriate values depending on target element type when patching the element:
modelValue
->value
orchecked
based on element typeupdate:modelValue
->input
orchange
based on element type, also handles extracting the value from raw DOM event.
This way, v-model
will generate the exact same code when used on elements AND components. A component with v-model
can simply spread $attrs
on any element and it will just work.
from core.
@yyx990803 Brilliant! I love it. 😻 A few follow-up questions:
-
Should
v-model="foo"
actually translate to anonModelUpdate:value
event (instead ofonModelUpdate:foo
)? -
For consistency, should
v-model:my-prop="foo"
translate tomodelMyProp
andonModelUpdate:myProp
, which could also be transformed at runtime to the correct attribute and event? -
Should registering
myProp
as a prop also automatically register:modelMyProp
onModelUpdate:myProp
onUpdate:myProp
That way, all of these would automatically stay out of$attrs
. ThenmodelMyProp
andonModelUpdate:myProp
could just be aliases formyProp
andonUpdate:myProp
, but with special behavior when bound to an element. Would that make sense?
With those final tweaks, I think we might actually have the perfect v-model
API!
-
The simplest cases remain as simple as possible: just
v-model="foo"
on an element, withv-bind="$attrs"
added for a component. -
In cases where users want to manage
v-model
behavior for a prop manually, they can just usemyProp
andupdate:myProp
without having to worry about the specialmodel
/onModel
-prefixed attributes. -
When users need full access to
v-model
's magic on an element, they can choose to explicitly usemodelMyProp
and/oronModelUpdate:myProp
to achieve the exact behavior they're looking for, with minimal boilerplate.
from core.
I just edited my proposal a bit. When used without an argument the generated props should not care about what key it is.
When used without an argument:
<input v-model="foo">
h('input', {
modelValue: this.foo,
'onUpdate:modelValue': value => {
this.foo = value
}
})
When used with an argument it will compile like this:
<Comp v-model:someProp="foo">
h(Comp, {
someProp: this.foo,
'onUpdate:someProp': value => {
this.foo = value
}
})
So someProp
is passed down with value bar
, and the child can emit update:someProp
to perform 2-way sync.
I don't think it makes sense to use v-model
with arguments on a plain element, it seems the use case is really for two-way binding on component only. So the runtime special handling will only apply to modelValue
and onUpdate:modelValue
.
from core.
I don't think it makes sense to use v-model with arguments on a plain element, it seems the use case is really for two-way binding on component only. So the runtime special handling will only apply to modelValue and onUpdate:modelValue.
@yyx990803 I agree it doesn't make sense to use v-model
with arguments on plain elements, but I was thinking about cases where a user might still want to bind props to individual elements within a component, e.g.:
<InviteeForm
v-model:name="inviteeName"
v-model:email="inviteeEmail"
/>
where InviteeForm
is defined as:
<script>
export default class InviteeForm extends Component {
static props = ['name', 'email']
}
</script>
<template>
<form v-bind="$attrs">
Name: <input v-bind="{ modelName, 'onModelUpdate:name' }">
Email: <input v-bind="{ modelEmail, 'onModelUpdate:email' }">
</form>
</template>
Though maybe we could actually abstract away the implementation details of:
<input v-bind="{ modelName, 'onModelUpdate:name' }">
by simplifying to something like:
<input v-model.prop="name">
What do you think?
from core.
Sorry. Why not use value
directly but choose modelValue
by default? Did I miss something?
from core.
Why not use value directly but choose modelValue by default?
@Jinjiang I don't think I understand the question. Could you elaborate?
from core.
Sorry for my bad description. 😅
As we discussed above, now
<input v-model="foo">
will equal to:
h('input', {
modelValue: this.foo,
'onUpdate:modelValue': value => {
this.foo = value
}
})
not:
h('input', {
value: this.foo,
'onUpdate:value': value => {
this.foo = value // or `value = value instanceof Event ? value.target.value : value`
}
})
right? So my question is why we choose the name modalValue
but not value
here?
from core.
@Jinjiang Ah, I see. If I understand correctly, it's because modelValue
has special behavior specific to the element it's added to. For example, on a <select>
element it will not map to a value
attribute, but instead add selected
to the appropriate <option>
. Does that make sense?
from core.
Closing in favor of vuejs/rfcs#8 and vuejs/rfcs#31
from core.
Related Issues (20)
- v-html 在 SSR 与 CSR 时的表现不一致
- Vue not able to extract prop from `ReadonlyArray` and `readonly` HOT 2
- Slots render issure HOT 2
- Two-way binding can directly modify without emit 'update:model-value' event when using object to create ref() or reactive() HOT 4
- Multiple Dom nodes in template use emits will warn Extraneous non-emits event listeners (eventName) were passed to component but could not be automatically inherited HOT 1
- Props are mutable in the template HOT 2
- v-html error for commented(inactive) children elements HOT 2
- SSR hydration mismatch when conditional slot wrapped in transition HOT 3
- VueUse computedAsync helper HOT 1
- Throw TypeError when writing html comment in teleport HOT 1
- "Unhandled error during execution of render function" when decreasing an array size HOT 3
- 模板中 定义 异步箭头函数, 并在函数内部将 (其他)异步函数返回值赋值, 出现 ` 'await' is only allowed within async functions and at the top levels of modules.` HOT 2
- Lazy loading images only works on first load HOT 2
- The search function of the Chinese official website is not available HOT 6
- defineModel does not preserve all runtime types in prod when types contain boolean HOT 5
- TypeError: Cannot read properties of null (reading '0') in product mode HOT 19
- Storing the props in a `const` before passing them in `h` function causes reactivity problems HOT 2
- The slots objectless prototype function obtained by useSlots HOT 12
- Unhandled error during execution of setup function at <App>:Maximum call stack size exceeded HOT 3
- computed function executed with in an error HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from core.