Just want to point out that in the Sideburns issue I did mention that I have some other work to wrap up before looking deeper into the work you have been doing.
Fine, Iâll settle down. I already feel more heard today on this stuff than any other time since the initial announcement. I should have more code to submit toward this aim next week.
I absolutely love VUE.
My programming journey started this year, with Meteor. Blaze is easy to pick up and I would argue Vue is only slightly more challenging. Vue gives me the power and organization I want from React but with the excitement and beauty I found initially with Meteor and blaze. I truly hope the integration between Vue and Meteor increases over time.
The only issue I have with Vue is occasionally missing a small code adjustment to make Meteor happy. Does anyone know of an article that goes over the basics and/ or healthy practices of integrating Vue with Meteor? Also just want to thank Laracasts, and Level Up Tuts for getting me excited to learn programming.
Vue actually integrates easily already. Thereâs a package on atmosphere for it, and hereâs a little video on it. https://www.youtube.com/watch?v=vsqBue6bM9Q
My view on Vue:
Getting Started
- Hello World
- Two-way Binding
(stopped there)
Two way binding is evil. Thatâs why programmers have to do it themselves. Otherwise itâs too confusing. This is clean and easy to follow:
var Message = React.createClass({
getInitialState: function() {
return {message: 'Hello World'};
},
handleChange: function(event) {
this.setState({message: event.target.value});
},
render: function() {
var message = this.state.message;
return <input type="text" value={message} onChange={this.handleChange} />;
}
});
Now look at how confusing two-way binding would be:
var Message = React.createClass({
getInitialState: function() {
return {message: 'Hello World'};
},
render: function() {
return <input type="text" bindValue={this.state.message} />;
}
});
How come it is confusing? In the context of React or generaly?
The problems with two way binding happen when a lot of logic becomes encapsulated within the data binding engine. For example, should a text field be converted to a number or not? Now youâre either reading the type
attribute of the input field, or youâre adding an extra attribute to the input to add additional information (this is the Angular style), or you need a callback to change the value before itâs saved to the model. I feel like in super basic use cases data binding makes for a nice demo where you donât need to write any JS code to make stuff happen, but as soon as you need anything that the designer of the data binding system didnât think of, you need to add additional options or work around the system.
At the end of the day, you often end up with a whole new language to learn, for example Angularâs ngModel
directive: https://docs.angularjs.org/api/ng/directive/ngModel You need to learn about the entire API of the ngModelController
to use this feature: https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
In the React/Blaze model where you have explicit events, you have to write a bit of extra code up front, but at least itâs all in a language you understand (JavaScript) vs. a new meta-language of data binding that comes from a framework.
Itâs not confusing at all. Itâs completely obvious. But itâs problematic.
The reason itâs problematic is because you lose the old value for the field in your model. On insert, thatâs fineâbecause there is no old model. But the reality is probably 75% of the time you are in fact updating models. So the 2-way binding can only hold the state for the latest changes, not the old value. 99% of the time you want the old value. Perhaps if the new value is incorrect, or if you want to compare to the old value for whatever reason, etc.
So basically 2 way binding is basically uselessâwhen you can just do something like model.populate()
which will suck out all the values from, say, AutoForm, and populate your model. Or model.populateField('name')
OR: model.field('name')
if you donât want to replace the old value. In short, itâs one command to get all the values out of the formâwhy do you need the form to automatically populate your model on keyup? You donât. It hurts you if you are trying to do anything more than a basic example, like what was on the old Angular homepage which is meant to make you go âoohâ and âahhâ but have no practical purpose.
I might agree to this if it werenât for JSX and how itâs ruining markup and essentially taking front-end UI devs out of the picture. Angularâs (and somewhat vueâs) models may make HTML look ugly, but not nearly as ugly and problematic as jsx.
Thatâs exactly why the plan of migrating to React includes building templates for React. Then I would say you get the best of both worlds. (Even though I personally prefer JSX)
Itâs not confusing. I didnât include the /s
at end. There is no value in having developers write needless boilerplate code for no other reason than âthe framework requires itâ.
But what if I need to do an extra X when Y happens?
In those cases you write the necessary code. Plain and simple.
But you then need to know the name of the bind!
True, but thatâs also true for React as well. In React you have to know that you have to use onChange
and that it works differently than the browserâs regular change
event.
But Angular is a monster and it uses data bindings
Just because Angular has a huge API surface and uses data bindings doesnât mean data bindings are the cause of it.
At the end of the day a binding is just a shortcut. Nothing stops you from writing the following Blaze-like code:
<body>
<input id="name" type="text">
</body>
Template.body.viewmodel({
name: '',
events: {
'input #name': function(event) {
this.name( event.target.value )
}
},
autorun: function() {
var name = this.name();
$("#name").val( name );
}
})
Or the following React-like code:
<body>
<input id="name" type="text" {{b "change: updateName"}} value={{name}}>
</body>
Template.body.viewmodel({
name: '',
updateName: function(event) {
this.name( event.target.value )
}
})
But why would you if you can just write:
<body>
<input type="text" {{b "value: name"}}>
</body>
Template.body.viewmodel({
name: ''
})
@sashko @faceyspacey @manuel ok, thank you for clarification. Still some lose ends, but will come back with some extra findings
In reply to this topic in general, not just Evanâs post,
I am presently studying Vue.js.
I searched for this post thread because I am wondering (like others): Is there something I miss if I do not use React, but use Vue? I feel everything about a component should be in the same file.
I am looking for such UI tool because Meteor lacks:
-a safe and integrated way for managing housekeeping variables in a DIV (such as holding the previous value);
-a way to communicate between page parts (values and messages);
-beside the object structure that is also a plus for reusability.
-IMPORTANT: The most minimalistic/nonverbose syntax for accessing an element.
VUE seems the missing thing in Meteor (in my POV) in all these points.
I did not read well the present thread, and I am still questionning the necessity to continue learning React, and see that VUE has an impressive base of features.
(again, in my POV)
Many js tools do nice things in their way because they do not run with Meteor paradigm in mind. (such as generating a dropdown list). My point here is that, when we know Meteor (and I am a beginner), It feels like: Well, in meteor, it is natural, just do it the meteor way, without learning that other implementation that does not know about reactivity, templating, etc.
With Meteor and Vue, do we really need React?!
P.S. (edited) That threadâs title was also in my mind for a while (before I find this thread), and maybe in many othersâ mind. Is it so creasy?
Vue can do two-way binding, itâs not enabled by default. Itâs quite flexible.
The way to build Vue apps, emphasized in their docs is actually a uni-directional data flow in which data flows from the parent component to child components. However, you can have two-way binding to any degree that you want, or donât want.
I have just started playing with Vue.js. Iâll report back when I have a verdict. But so far, it seems awesome.
No offense, but people who avoid two-way binding like a plague in general donât really understand what two-way binding is.
First thereâs the <input>
box two-way binding, which is just syntax sugar for
- one-way bind its
value
to the state; - handle
onInput
oronChange
to update the state.
So Vueâs form bindings are basically sugar for simplifying this - even React has an official equivalent. And itâs totally optional; nothing prevents you from doing the one-way bind + event handler dance, if thatâs more of your thing.
I donât really see any point in avoiding form two-way binding, since the underlying model is still âstate-driven viewâ - the source of the truth is the state underneath.
On the other hand, there is the concept of âtwo-way binding between scopes/components/modelsâ etc., where it is in fact holding two pieces of state in separate places and trying to keep them in sync. This is what we have generally agreed to be a bad pattern and have stayed away from. In Vue the data flow between components is one-way by default. And because Vue separates the component from the state they observe (components only proxies to the state instead of owning it), the state tree can be completely externalized from the components, turning your app into more of a Flux-like architecture. (See vuex)
Next time when you evaluate a technology, try to understand what it really is - donât shun something just because youâve been hearing âtwo-binding is evilâ without actually understanding the reasoning behind it.
Sorry if my comment sounds a little bit offensive. I have nothing against Vue.js or how it works. If you do understand it deeply and have no problem dealing with it, then you should use, no questions asked
Thanks for this clarification @evanyou. Two-way binding (like too many things in our industry) has become a catch phrase, and the nuances of it arenât really understood.
Also thanks for bringing vuex to my attention. Iâm planning on using redux to manage my app state, but if vuex will provide smoother integration with Vue.js that would be great. Will check it out in the next day or two.
Agreed. 2 way binding to a model returned from Collection.findOne()
, for example, means you lose the previous value for a field while the user types in an input, which you may need if the new value doesnât validate and for various other comparisons you could make.
If you are using collection models directly with your form, as in @aldeed 's AutoForm, 2 way binding is nothing but hype and syntax sugar that will in fact mess you up. Itâs why AutoForm doesnât do it. But if itâs bound to component state, as @evanyou explains (and as @manuel 's ViewModel does), itâs fine and certainly an added bonus for that use case.
That said, when you arenât using tools that closely map collection models to forms (again like AutoForm, or whatever will emerge in the React or Vue worlds), and instead are using 2-way-binding component state-based tools (like ViewModel or I assume whatâs being talked about in Vue.js) you are forcing yourself to go through additional stepsâboilerplateâto wire the form elements to âstateâ to a Meteor/Mongo model coming through Tracker and (getMeteorData
or TrackerReact
). The react world advocates more explicitness, more boilerplate, and repetition to achieve better debuggability and reasoning about your application in preparation for when it passes a threshold of complexity. To be sure, itâs smart. But, in comparison to the immense amount of automation Tracker + Minimongo provides, and until that point (that your app reaches âFacebook level complexityâ), having to do all that extra work is absurd:
- to go from Redux actions
- to Redux Stores
- to your components
- to your componentâs state
- and while youâre at it retrieving models from
getMeteorData
- to form elements
- back to component state
- and finally back to updating/inserting your model
2 way binding between form elements and state automates only like 2 links in that long chain. Using Tracker + Autoform and Minimongo reduces all that to basically one step: embed a form and pass it the return of Collection.findOne()
. Well 2 stepsâsince it doesnât do 2 way binding (and you wouldnât want it to)âthen in event handlers you overwrite the previous values in the model or perhaps use previous ones if new ones donât validate.
Minimongo (/w Tracker) is basically Reduxâs "Single State Atom"+:
- State all stored in one central decoupled place.
- automated action creation (insert/update/remove/etc)
- automated component subscriptions to stores (Tracker-based reactivity)
- deep state querying capabilities
- easily snapshottableâit just hasnât been done yet (that i know of)
Not that some Minimongo+Tracker+Redux perfect combination on the horizon wonât be better (Iâm looking forward to this)âjust letâs not forget all that Tracker+Minimongo really gets us. In addition to tons of appropriate automation, it in fact gets you more performance than pure React+Redux for many things: it means smaller branches of your component tree need to re-render; only the smallest portion of the tree that depended on a reactive datasource. Thatâs as opposed to state functionally trickling through many components as props, forcing them to all re-render as it goes. In short, sideways data loading lets you easily reduce re-renderings only to affected branches in the component tree, no matter how deeply nested they are.
There are a lot of benefits to Meteorâs original Tracker-based approachâfrom performance in many areas (not all) to orders of magnitude less boilerplate code. As it is with everything, there is no clear winnerâjust better tools for certain challenges/goals. There are still many things Tracker+Minimongo is King for. Weâd be remiss to leave it behind. Forms + Models (as in AutoForm) without 2-way-binding is one of them. To me, proxying through âstateâ before I put my data in a model and save it (or directly insert/update it) is just an annoyanceâan unnecessary extra step or 2 or 3.
Not sure I clearly catched your point. Although the example of modal popup helped me see a good case for 2way binding: an OK button that will close the modal window. Here, it makes sense to use 2way binding of a button that will toggle a state for showing or not the modal popup.
On the other hand, YES!, one reason I was looking for a thing such as Vuejs is to be able to manage div related variable and one of these being the old value (before change, so to see if the value has changed) so I can evaluate an update/query to the DB, because I do want to avoid a full document rewriting. (I feel unsecure doing such update in a document), although maybe MongoDB, is doing anyway a full rewrite of the document in a new version of it.