I've built semi-large applications in both Vue.js and React. I like both but prefer React.
For me Vue.js is like a light-weight Angular 1, in a good way. It's very intuitive and you can start working immediately. It does however easily end up in confusion about where the state lives with the two-way binding. I've run into a lot of implicit state changes wrecking havoc. The declarative nature of React definitely wins here, especially working with stateless functional components. If you're serious about Vue you should adhere to unidirectional bindings, components and use Vuex.
The best thing about Vue.js for me is the single file components. It's such a nice feeling to know that everything affecting a certain component is right before your eyes. That's also the reason I started adapting CSS-in-JS in my React components.
The biggest problem for me with Vue.js is the template DSL. You often think "how do I do this complicated tree render in Vue's template syntax? In JSX I would just use JavaScript". For me, that was the best upgrade going from Angular to React and it feels like a step backwards when using Vue.js.
Thanks! That's cool and yes, it supports JSX but it's still not a first-class citizen like in React. I don't know the practical implications though since I haven't used so maybe my fear is unfounded.
I have been building web apps for 19+ years. I like many of the frameworks out there but for some reason I HATE React. I think JSX is a huge turnoff for me. I just can't get past html in javascript. It feels wrong.
With that said, there are so many VERY smart people embracing React, so I am always questioning my "hate". Maybe one day I will change my mind.
I haven't use Vue but watched/read about it and seems very cool and simple to use.
For now, my favorite framework by far is Ember JS and it really blows my mind why it is not the most popular framework out there. The amount of stuff you get out of the box and the incredible productivity and happiness it brings to the developer experience is IMPRESSIVE. It will take you 2 weeks of work to make a new React app have the same feature set as an Ember app*
For a long time, people have been saying "separation of concerns" to support the idea of keeping HTML, JavaScript, and CSS in separate files.
The problem with that is that the document, application state, and styling is all highly coupled when dealing with web apps. Web pages which are content based are fine with these being separate, changes to one don't necessarily affect another.
For web pages, the separation of languages is a separation of concerns. However, for web apps, the separation of languages becomes a barrier, since everything about a certain behavior in your program could be in three different languages or more.
React changes this notion with the idea of a component. A component is ideally pure, meaning that it affects itself and it's children, and nothing else in the application. Components are composable, so you can combine multiple components, allowing for very DRY view code.
Idiomatically, React components have elements, styles, and the relevant code in a single file. This keeps things encapsulated and easily maintainable.
Separation of concerns means put your styles in a <style> tag rather than the style attribute of a tag, and behaviour in a <script> tag rather than in an onclick/onhover/whatever on the tag.
Grouping logically related components together makes perfect sense (and this is coming from a backend Rails dev who thinks the rails directory structure is totally wrong as well).
While it didn't start out this way, these days Ember apps lean heavily on components and all of the apps I work on use a pod structure that groups each component into a directory containing a component.js, a template.hbs, and a style.scss file. This maintains the spirit of "components should be self-contained" while not having to define html and css within javascript. Ember has React to thank for the idea, but I prefer Ember's implementation.
Interestingly, I had recently joined a team that was using Ember, and we found that Ember hampered our productivity. We switched to React and was able to rebuild 4 months of Ember work in about 3 weeks of work in React (not sure how many developers were working on the Ember app originally, but it was mainly 2 of us who built the React app), including requisite tests.
I’m of the opinion that Angular is much better than Ember (note: I have 4.5 years of experience in the Angular ecosystem, including in open source), and I think I am overall perhaps more productive with React than Angular, although I feel like there are less issues with state management in Angular, which has been a pita in React. All the libraries/frameworks have various tradeoffs ultimately, so I don’t believe there is a cure all for everyone’s preferences.
A note about JSX - I am not a big fan of it, but I see it more as having tradeoffs like more traditional templating languages, but different ones. I have been a bit resigned that this is the direction the ecosystem has turned towards, so I have personally decided to hold that dislike more loosely and focus on more important architecture issues. It does little good to let dislike over style paper over higher level issues if you can help it IMO. I don’t think we’ll ever see a perfect template language.
A rewrite is always going to take less time to build than the original poorly-specified version when people were trying to figure out what to do.
And the original team could have been more junior, or if similarly-experienced than your 2-person team, adding more people to the team without good leadership can also affect productivity---or as they say in Scrum, "velocity".
Regarding state management, have you tried MobX? It makes state management almost ridiculously simple. I've noticed a slight performance hit using it for deriving values for 60fps animations on React Natuve but in normal usage you'd never notice.
I worked with Ember for a few months and I like it a lot - it definitely deserves more recognition. One thing that frustrated me a lot in Ember was the run loop. The docs suggest that you don't have to worry about the run loop at all and its merely an implementation detail, yet we had to constantly us Ember.run, Ember.run.schedule, etc. all over the app. But of course in order to know which Ember.run methods to use, you end up diving deeply into the implementation details of the framework itself.
> It will take you 2 weeks of work to make a new React app have the same feature set as an Ember app
You're probably right about this. But it's not always the whole story - maintain and grow your app for a year, and you may find your experience shifts dramatically.
Disclaimer: I haven't used Ember for anything but the tutorial, and I hear it's pretty good these days.
* when you find yourself reaching for jQuery to change DOM, eg add/remove a class, think again. v-if depending on component state data variables worked well for me.
* after trying several authentication libraries, found it simpler to build my own layer, storing user state in Vuex
Anybody has more tips to share? Something you wish you knew earlier?
working anything with loops and conditionals, Vue is way nicer than JSX all the way around, especially the more complex it gets with *-level nested json data trying to mix in with conditional portions of the view, and even saving reactive data back the scope of the loop, etc. i'm not sure why you'd think otherwise. JSX code with many loops and conditionals can start look incredibly ugly pretty fast. if you can provide an example, we can compare between the two to see which is nicer.
Side effects and testability. Two way binding is great for simple forms, if you have like a dozen or so variables on a page? Two way binding is awesome and allows you to write very terse code and logic.
If you start adding dynamic forms, multiple developers, unit tests, and advanced interactive application logic, then you are left with a spaghetti code mess (with 2-way binding). The problems really creep up when you start adding observables or watchers, which watch a particular variable for changes. If you two way bind a UI element with a controller variable, and then have watchers or observables on that variable...it is now no longer clear what side effects you're triggering as your interacting with that UI element. Wonky things can and will happen to you as your app's complexity grows.
> If you two way bind a UI element with a controller variable, and then have watchers or observables on that variable...it is now no longer clear what side effects you're triggering as your interacting with that UI element.
I've heard this argument before, and I really don't get it.
Let's say I have an input bound to a model variable. What does that mean? Well, the model is the single source of truth of state. And the user can change it. Sometimes we have derived state, like computeds in Knockout. These are read-only and are not ultimately sources of truth (though they will never contradict non-derived values).
In this model, I cannot see what is wrong. Why do you need to reason about the side effects your input triggered? Your input should be bound to something that is a fundamental, atomic, irreducible element of the app state. When it changes, the app changes. You never need to reason about this happening because there should never be a moment where a model changes and the app does not.
Excuse me for my naïveté, but it looks to me like two way binding can only cause problems if you are binding inputs to derived values, or if your model is not truly irreducible. In which case, you are knackered before you start: how is your app ever supposed to guarantee consistency of state?
If you are writing Angular or Knockout code properly, in my opinion, the data flow should be unidirectional just by dint of using an irreducible model and never manually overwriting a derived value.
Just because the template has a two way binding to a model does not mean the data flow is pandirectional. Likewise, one way binding does not guarantee unidrectionality: I am fairly sure you could write a React-Flux app where components emit arbitrary actions in response to state changes. Perhaps this is banned in Redux, though.
Input Field <-> Controller/ViewModel field two way data bindings are fine when they are kept simple, as I said in my comment. Two way binding is great for simple web form apps. If all you're doing is pairing a Name input field with a name variable on your controller or viewmodel, you're golden.
But having worked on complex dynamic form generators and enterprise apps at scale, I've seen the mess that KO observables and Angular $scope watchers create in practice.
Neither KO nor AngularJS actively encourage great patterns for data flow in their architecture design. It becomes all too easy, in some deeply nested directive or KO observable, to reference external/parent context or scope. React was specifically opinionated about this because Facebook hit real problems in production with two way binding.
Another benefit of one-way flow is that it becomes trivial to refactor your UI into modular components. Because the data flows in a top down manner passed in as props, it's easy to break up a complex component into several sub components.
React encourages you to fall into the "pit of success" by its design and there's very few traps.
I recommend taking a look at how Angular 2+ does it - the Angular team originally intentionally omitted it, but they found a way to make it work in a technically sound fashion (output changes being evented).
The side-effects problem was certainly true with Angular.js - it is not true with Angular.
Angular2+ is an improvement, no doubt, and the eventing based system is not unlike React's in that sense. Although it does require you to instantiate an EventEmitter which is somewhat arbitrary. Still, it's a better data flow model overall for sure.
It's pretty much an issue of getting to a "stable" state, which means that model stabilizes to a certain value after all the actions by user and code. That can be a problem with 2way binding and sometimes it causes very subtle bugs, but it boils down to the infamous event storm. So that's why they gave up on 2way binding and made it more optional and deliberate
I honestly don't remember since I don't use two-way binding anymore but the last problem I had was something with copying one person in a list of people with inputs from one place on the page to another and things got really messy. Sorry, don't remember the details. :/
The problem with two-way binding is that people use more than one source of truth and blame that questionable (to not use stronger words) decision on the framework.
I love single file components. I used Polymer before React and that is the thing I miss the most. I've also been using CSS-in-JS for the same reason. I landed on JSS for now, but I'm hoping we'll see a solid scoped CSS solution soon.
Doesn't that depend on pipeline? I've been doing for polymer components with html css and js split into separate files.
They get concatenated into single file in build process.
> I've built semi-large applications in both Vue.js and React. I like both but prefer React.
> If you're serious about Vue you should adhere to unidirectional bindings, components and use Vuex.
> The best thing about Vue.js for me is the single file components. It's such a nice feeling to know that everything affecting a certain component is right before your eyes.
>The biggest problem for me with Vue.js is the template DSL. You end up with the "how do I do this complicated tree render in Vue's template syntax?
For me Vue.js is like a light-weight Angular 1, in a good way. It's very intuitive and you can start working immediately. It does however easily end up in confusion about where the state lives with the two-way binding. I've run into a lot of implicit state changes wrecking havoc. The declarative nature of React definitely wins here, especially working with stateless functional components. If you're serious about Vue you should adhere to unidirectional bindings, components and use Vuex.
The best thing about Vue.js for me is the single file components. It's such a nice feeling to know that everything affecting a certain component is right before your eyes. That's also the reason I started adapting CSS-in-JS in my React components.
The biggest problem for me with Vue.js is the template DSL. You often think "how do I do this complicated tree render in Vue's template syntax? In JSX I would just use JavaScript". For me, that was the best upgrade going from Angular to React and it feels like a step backwards when using Vue.js.