-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1.0 binding syntax (discussion thread) #1308
Comments
@yyx990803 , thanks for answer =) Directive syntaxhttps://github.com/yyx990803/vue/issues/1173#issuecomment-137326936 👍 Component syntax
I have suggested this option. It pretty good for me 😋 |
Looks good! I like the possibility to have both the v- prefix and the shorthand option. I also like the : and ^ being a prefix and not an affix. Maybe we can have a consistency between the full notation and the shorthand? Example: <div
v-bind:href="address"
v-bind:src="imgSrc"
v-on^click="doThis"
v-on^keyup:esc="doThat">
</div> I'm not sure if it's an improvement. Maybe it makes it harder. What do you think? Another (maybe stupid) question about expressions & literals; can we use quotes for literals, and leave the quotes for expressions? Something like; <div v-text=msg></div>
<div v-link="/a/b/c"></div> |
I really like the latest proposal. It's clear that there are two major groups of Vue users - some of us are mostly back-end developers and are using Vue as a front-end library (and we really wish to keep the consistent I can't speak for everyone, but I came to Vue because I really disliked how verbose all of those other front-end frameworks got (Angular 2 is a good example) by introducing a ton of new syntax, which can be very confusing for a back-ender like me. And a simple rule like |
I am new Vue user, but I use Angular almost 3 year. One of my public angular modules placed here (sorry for ad). I can create a long list of what I like in Vue 😊 |
@dennisver |
@yyx990803 I agree, thanks! When I tried Vue for the first time, one of the first things that were not clear to me, was whether I should use quotes or not. I'm coming from Ember, haven't really tried Angular and I've always associated quotes with literal strings. Could you also explain what the downside is of using mustaches for expressions? |
@dennisver In Ember, all templates are parsed as strings, so it can actually be non-valid HTML - e.g. So in short, always quote your attribtues in Vue. |
I like the new proposal but I prefer @ for events instead of ^, although it clashes with two-way syntax. The literal,dynamic,two-way,one-time shortcuts, I think they should be enforced on the prop definition instead, dynamic props would be the standard, then literal could reuse the "#" shortcut and two-way and one-time on the component prop "schema" |
@thelinuxlich yeah, I like Dynamic props by default would imo be confusing because there's nothing that differentiate them from normal attributes (directives have |
Then we should have another symbol for two-way binding to avoid misunderstanding, maybe like Ember "mut var" |
yeap
+1. ie in javascript. I think about component like about function: // definition
/**
* @param {Number} a
* @param {Object} b
* @param {Array} c
*/
function foo(a, b, c) {
// some code here
}
// using
foo(1, {}, []); You need know how it work when you deal with it. |
That's not a correct analogy. It's more like this: foo('literal')
var a = 'dynamic'
foo(a) |
This topic made me sleepless... So, I came to the next. ProblemFirst off, what are main goals of all these changes? I see two:
And I'm Captain Obvious, yep. And, in my opinion, next things are confusing now:
ProposalStep 1. Let's replace terminal directives with control-flow tags:
<v-if condition="{something}">
<!-- conditional code here -->
</v-if>
<v-unless condition="{some condition}">
<!-- conditional code here -->
</v-else>
<!-- there will be no v-else, as one can put something between <v-if> closing tag and <v-else> -->
<v-for collection="{arrayVariable}" item="currentItem">
<!-- each collection item will be exposed as a local variable currentItem -->
<!-- repeated part here -->
</v-for> It's much more readable IMO, and should feel more intuitive for people who are familiar with any template engine. Step 2. Make directive expressions uniform.Now we have "literal" and "non-literal" directives. Let's get rid of the term "directive" for now and call them just "expressions". We need 3 types of expressions:
Possible problems and solutionI see some room for errors: <!-- String instead of the function reference -->
<button v-on-click="clickHandler">
<!-- Readonly expression for binding -->
<input v-bind@="{'mr.' + user.name}">
<!-- Binding to literal value. "user.name" -->
<input v-bind@="user.name"> But, these errors can all be caught automatically at the directive code and appropriate warnings can be displayed. ExampleLet's doodle a little bit and build a shopping cart sketch: <script>
module.exports =
data: function () {
items: [
{name: 'iPhone 6s', quantity: 1, price: 299},
],
/* validation errors object, name: value format */
validationErrors: {},
checkoutForm: {
name: '',
email: '',
/* so on */
}
},
methods: {
validateForm: function () {/* some validation code here */}
},
filters: {
nameFormatter: {
read: function(value) {return value;}
write: function(Value) {return value;}
}
}
</script>
<template>
<ul class="cart-items">
<!-- collection binding is two-way, because we can click at "delete item" link at the list and the list will be modified -->
<v-for collection@="{items}" item="product">
<!-- at this point a "product" local variable is defined and we pass it to the <product> -->component
<cart-item item@="{product}"></cart-item>
</v-for>
</ul>
<form id="checkout" v-on-submit="{validateForm}">
<label>Name</label><input type="text" v-bind="{checkoutForm.name} | nameFormatter" />
<label>Email</label><input type="email" v-bind="{checkoutForm.name} | nameFormatter" />
<!-- so on -->
<v-if condition="{validationErrors.length > 0}" transition="fade">
<div class="validation-errors">
<v-for object@="{validationErrors}" item="error" key="field">
<div class="error">
<!-- the only thing that worries me is that these mustache bindings may be confused with assignment syntax -->
{{field}}:{{error}}
</div>
</v-for>
</div>
</v-if>
<v-pre>
Some freeform markup that will not be compiled
</v-pre>
</form>
</template>
|
@karevn I appreciate your ideas, but:
Finally, please note that we are trying to "fix issues with as few changes as possible", which is why I toned down the original proposal to this one. We want 1.0 to be a natural progression of 0.12, and there should be a clear upgrade path. We are not trying to "reinvent the syntax" (which is a mistake I made with the original proposal). |
@yyx990803 From tech standpoint,
Basically, my thougts are: 1.0-alpha breaks ALL the existing code that relies on Vue. So, if rewriting all the dependent code is inevitable already - it's a very good time to polish the syntax not to revisit it once again in future. I don't have any experience with Angular (came from Backbone directly), but when I took a look at it the first time - the impression was "what the hell is going on with the syntax"? While Polymer and React's syntax look much more elegant and "natural". Taking in account Angular hype is over, and React / Polymer are taking over - may be it's the sign not everything was good with the syntax and Vue should learn this lesson too? |
@karevn I would argue that with the latest proposal, the migration process from 0.12 to 1.0 has been drastically simplified. And it's certainly not true that "it breaks all the existing code". Some changes in the view layer will be required for sure, but very few in the actual logic itself. Furthermore, the current syntax has proven to be very popular with a lot of developers due to its simplicity and clarity. And judging by myself, the learning curve is already very low compared to some other frameworks like React or Angular2 which I was never able to fully comprehend. |
|
@yyx990803 I think you misunderstood me. My proposal's key points are:
@acasar you were totally right - React's syntax is a nightmare sometimes. But I am offering to steal it's best properties (simple attr binding syntax), not worst ones like mixing HTML and JS syntax. |
I want to make it clear that the syntax change is not because "the current syntax sucks": in fact, it's been working well for many of us. What we are trying to do is "fix the small issues within the current syntax", not "let's just move to something completely new". That sounds more like a goal for maybe Vue 2.0. |
@karevn Regarding the upgrade experience - we upgraded a medium sized app to 1.0.alpha1 and it took a few hours. I can't say it went completely smoothly because there were some frustrations along the way. But overall not anything drastic. We still have a bigger app waiting for the upgrade, but I'm going to hold off until 1.0 is finished. With your proposals I'm afraid that the upgrade process would be even harder. Also, I'm personally not a big fan of the syntax you proposed, but I do acknowledge that we come from different backgrounds, so it probably seems a lot more natural to you than it does to me. :) |
It took me 2 minutes to memorize new changes. I thougth you have good memory. If you mean "general learning curve" - I still think Vue's API makes perfect sense and learnable in a day or two. It's funny for me how you are comparing Vue to those libraries mentioning learning curve. New API is to bring more sense, explicity and I think it makes it easier to learn compared to those libraries' API. |
@azamat-sharapov calm down please, it's just discussion ;) |
Sorry, forgot to insert smiley 😄 |
@acasar two accounts? :) Imagine I went from Ruby On Rails, Backbone or WPF world, and I see `:attr="src: 'something"'. Hmm, what does this colon mean?? I have to read the docs to make sure. Now, with the same background, when i see |
Personally me, I took like 3 days off just to read Vue docs first, so that I won't annoying to the public with simple questions :) because it was my first JS library. Yeah I also did Backbone in the past, but probably not much as you.. I think it's mandatory to learn docs first and Vue docs seem to be easy to understand. Yeah I understand you mean "people with different backgrounds", but that colon thing is optional, like if/else vs ternary, so use it if you are sure about it. Or did I miss something? (I personally wouldn't use that short-syntax, I better type "v-bind/v-on" so I can later read HTML like plain english). |
@karven Posted from company account by mistake. It seems it didn't get unnoticed :) I'll just add one more comment about familiarity. I came from Angular v1 and I felt right at home with Vue. Not only that, it even felt much easier and more intuitive to use. And judging by how popular Angular v1 was (and still is) there are many who feel the same. It seems that changing the syntax completely in v2 didn't end well for them... but well, I guess the jury is still out on that. @azamat-sharapov I also prefer the longer syntax but I see no harm in offering a more concise shorter one. It seems there are some valid use-cases for that. And from what I understand it is optional. |
@azamat-sharapov it just indicates that you are not like other 95% of people. If you'll take a look at Vue gitter thread, you'll see that most of question would not appear if people have read docs. @acasar I think it is not new syntax that is the problem in Angular, but the fact that syntax was changed. People just don't trust Angular anymore. |
@yyx990803 Could you maybe add a changelog to #1325 the next time you change it? I don't think we can see a timestamp of when you did edit it the last time, can we? |
@yyx990803 After some thought I am still rooting to make adding a class with condition a little easier. Right now I understand that <input v-on:keyup.enter="doSomething" v-on:keyup.esc="doSomethingElse" /> So I think that By the way, is it also possible to define multiple event handlers using object literals or is that exclusive to |
@acasar I wouldn't call the Object literal microsyntax - because it's a JavaScript expression. If you know how to write JavaScript, you know how to write an Object literal. The point about "removing microsyntax" is that now we can always safely assume "a directive takes a single expression." For event handlers - you use multiple attributes to handle different events with the native syntax too, e.g. On the other hand, I don't see how I think there should only be "two ways of doing the same thing" when there's a clear benefit for each (for example |
Since curly braces are used for mustache expressions, seeing single braces used for object literals is a bit jarring (even though we don't allow mustaches in attributes anymore).
What do you mean by that? Wouldn't the directive just get an object? |
@JosephSilber an object literal is a valid JavaScript expression. |
@yyx990803 the latest syntax is wonderful , it reads really well and intuitively, respect 👍 |
@yyx990803 Thanks for the latest alpha release! I really like the syntax. Do you think we could find even more concise wording for <div v-dirname.raw="abc"> |
@acasar I like that! Since literals will be used all over the place (99% of Not sure about |
Maybe |
I thought about shortening it to |
@JosephSilber I like In the end I'd be fine with just using quotes, which will probably work anyway since it's a valid expression: <div v-dirname="'abc'"> |
Another viable option is |
I think As an aside, I didn't even know what the Most of my props/bindings are not literal. |
@simplesmiler I laughed at |
There would be no mistake about knowing if the value would be string or number. |
I prefer |
Are a few extra letters really that hard to deal with? Imo being semantically accurate is more important than being concise, especially when it's just a few letters' difference. |
@yyx990803 it looks a bit long compared to others for me. It makes |
@yyx990803 Noticed |
@fullfs this is because
|
@yyx990803 Regarding the <!-- Will `v-link` get a string or a number? Both are technically literals... -->
<my-component v-link.literal="5280"></my-component>
<!-- Ah, it will get a string. -->
<my-component v-link.str="5280"></my-component> The same case can be made using Now, this problem is solved by sufficient documentation, but I felt it was worth drawing attention to what I felt was a really good point that might have been missed. |
@Morgul I don't think we should evaluate the syntax based on "does it make sense without the docs", because that's impractical. Rather, I think we should evaluate the syntax by "does it make sense enough so that you only need to read the docs once". The |
That said, I agree now with @yyx990803 |
+1 for |
@yyx990803 Alright, I agree with that. I'm completely onboard for |
@yyx990803 if it's about reactive/non-reactive, maybe |
@yyx990803 Besides, though not very important, Rails users would feel a bit inconvenient to handle attributes which contains colons when they use Rails code to generate HTML. So at least I hope that By the way, can directives have alias? Only for that basic directives like |
@CicholGricenchos the colon is necessary because directive names can contain hyphens. How do you know |
Closing this issue now - if there are any specific concerns, please post at the forum instead. |
Note: This post may contain outdated content. Latest reference is now maintained at #1325
Here's yet another long post on the new binding syntax. I know we have gone through a lot of changes during the alpha phase, but please, bear with me - I want to make sure we land on something that is good enough to be called a 1.0 - something that is consistent, explicit, and most importantly, stable. We are going to strictly follow semver post 1.0 - I don't want to have to release 2.0 in a few months ;)
I've been thinking about all the discussion on consistent
v-
, and I feel that the new syntax may indeed be a bit too different from what we have in 0.12. Some of the justifications about the additional prefixes was based on the fact that Angular 2 and Aurelia are both introducing custom syntax for bindings; but then I realize Vue is not Angular or Aurelia, because these two are full-stack frameworks, where Vue aims to be flexible in as many use cases as possible.So, let's take a step back and think about the original problems that we set out to solve with the new syntax, and evaluate what we have so far:
Confusion about expressions vs. literals for directives
Example:
Here
msg
is an expression buta/b/c
is a literal string. There's no way to tell which should be literal except looking at the directive's documentation.Current solution in alpha.4:
Explicit syntax for literal directives:
v-link#="123"
. This also simplifies implementation of custom directives. I think this is a good change.Confusion about where mustaches are allowed.
Example:
The general rule is that mustaches are only allowed in literal strings but not in expressions. But mustaches just make people think in the string template mindset and assume it should work everywhere.
In addition, mustaches inside attributes have some subtle gotchas, for example when used in
src
it causes a 404 error; when used instyle
it causes IE to ignore it.Current solution in alpha.4:
No more mustaches inside attribute values. Attribute bindings use the
bind-
special prefix.As someone pointed out, this introduces an additional prefix and isn't as distinctive and consistent as
v-
. Butv-attr
also has its own warts, mostly related to the "arguments + multiple clauses" micro-syntax. We will discuss this in more details below.Directive micro-syntax
Example:
The problem here is that it looks like an object, but it is not; it also becomes awkward to format (different indentation, no syntax highlight) when you have a lot of handlers/attributes:
Current Solution in alpha.4:
I think breaking each binding into a single attribute is definitely the right move. But we also introduced yet another prefix:
on-
.Not-so-good prop syntax.
Example:
First, this looks like normal attribute bindings. Second, as we noted above, mustache bindings indicates that it evaluates into a literal string. However, the 0.12 prop syntax is ambiguous in this aspect:
^ This passes down the actual object.
^ This will try to concatenate "abc-" and the object, resulting in "abc-[object Object]".
The binding indicator can also be confusing:
Current Solution in alpha.4:
By getting rid of mustaches and move the binding type indicator into the attribute name, I think we've solved most of the issues above, but it relies on the extra
bind-
prefix.Recap
I think with the current 1.0.0-alpha.4 syntax we've addressed most of the original issues, but also introduced some new ones. Most of the negative feedback is concerned with the fact that we now have three prefixes instead of one:
v-
,on-
andbind-
. Do event handlers and attribute bindings really deserive their own special prefix?My original intention was that
on-
andbind-
would allow us to get rid of the "micro-syntax" issue mentioned above. But I also agree that more top-level prefixes also introduce additional cognitive overhead. So here's an update that attempts to address this issue:So, instead of what we currently have in 1.0.0-alpha.4:
We would write:
A little more verbose, but more consistent, more Vue-specific, and maps to 0.12 concepts better.
When we are using Vue alone to build an SPA, the
v-
prefix may not be that important anymore. So it is still possible to provide optional, more concise sugar on top ofv-bind
andv-on
:You probably would prefer the shorthand for component props as well (changing two-way indicator to
&
instead of@
):The text was updated successfully, but these errors were encountered: