I've been using React with MobX and Typescript for the past year in production and it's been treating me and my team very well. The framework feels quite invisible at this point.
I've been using React with MobX and Typescript for the past year in production and it's been treating me and my team very well. The framework feels quite invisible at this point.
First, Vue shares most of the things that actually make React exciting. Component oriented, one-way databinding, virtual DOM, a first party Flux-inspired state management plugin. We didn't feel that we lost anything moving from React to Vue, and most of our existing components were trivial to port.
What we gained, on the other hand, is a whole lot of developer comfort. Vue's template syntax can be read and manipulated by people who aren't primarily Javascript developers. Directives and filters eliminate quite a bit of boilerplate. Opt-in two way binding eliminates noisy setter functions without any loss of clarity. Getters enable the use of computed values as though they were raw data. There's no single killer feature, but taken together Vue just feels much more pleasant to use than React.
React has the correct fundamental abstraction, but the actual API mistakes "small" for "simple". JSX, in particular, is trivial to explain and understand in theory, but in practice is often quite verbose and complex to use, as everyone who has asked themselves "how do I actually write an if/else block" has discovered to their dismay. Vue plux Vuex keeps the same conceptual simplicity and cleanliness as React, but it pairs it with a much larger, much more opinionated API that doesn't force us to reinvent every wheel we need.
The way I look at it, it's not a contest. If Vue is better for some developers and some teams than React, that's great! It's nice to have multiple good tools to choose from.
When you talk about "template syntax" and "directives and filters" are those a non-full-JS-style of templates? As in can you execute arbitrary JS like you can with JSX? Just curious.
For me JSX is one of the biggest reasons that React is much, much better than Angular. I've found that once you get into re-implementing for loops, if statements, fallback defaults, etc., etc., for the sake of templating in an entirely new DSL, it becomes super complex and hard to learn/remember.
The nice thing is Vue allows you a choice rather than making it dogma. As another commenter said, this can come in handy in certain situations (e.g. dealing with forms).
There is more of a learning curve, in the sense that it only took me 1-2 hours to feel like I fully understood JSX and maybe a day and a half to feel like I fully understood Vue templates. I, personally, don't find that argument very compelling. ~10 dev hours is a rounding error over the lifetime of a project, and anyway I spent at least that much time researching and/or reinventing JSX conventions and idioms that are obvious or trivial in any real templating DSL. I only had to climb the conceptual hill once for each framework, and the view from the top is much nicer in Vue.
As an aside, Vue actually supports JSX out of the box. Any component can optionally include a `render` function that's almost exactly like React's `render`, and it falls back to using Vue templates only if no `render` is specified. Anecdotally, though, there is only a single component in our entire application where the team decided it was cleaner in JSX than with a template.
The other is that you now have "directives" that are defined elsewhere, in other files, that are included into templates via strings, instead of anything that is easily statically (or quickly) analyzable. Some of these directives ship with core, but some are third-party, so you have to remember which is which, and which your team has added.
But that's not it, those "directives" can have "modifiers" that can augment the already blackbox directives however they want.
Not only that, but it seems that bindings can actually execute arbitrary Javascript as expressions. Which is great, except apparently you can do that in strings too, so you end up writing code like:
<div v-bind:id="'list-' + id"></div>
Now you're basically writing JSX, you're just doing it all inside of strings that are hard to lint, analyze, etc in the HTML attributes of your templates instead.It all adds up to lots of redirection and re-inventing the wheel, when you could just be using Javascript itself. (Although I'm sure there's _way_ less redirection than Angular.)
Not to nitpick, but I think this might be the nut of our different reaction here. Some of our directive are core, and some are third-party. 99% of the time I don't have to know or care which is which. I just use them and they work and I don't have to think about how or why.
Perhaps this would be clearer with an example. Our API serves numerous types of copy as markdown strings. In our React code, embedding a markdown string (assumed to be in `this.state.copy`) into a div looked like this:
<div dangerouslySetInnerHTML={{__html: md(this.state.copy)}} />
In Vue, it looks like this: <div v-md="copy" />
The first one is easier to statically analyze, but the second one is far easier for humans to read and to write. Vue allows me to abstract away all the details of how `copy` gets turned into HTML so that my templates can clearly express what I want them to do. The signal to noise ratio remains high, and if it starts to feel verbose or boilerplatey I have a large box of tools with which to fix it.Maybe you're hitting a pathological use-case because of the nature of your API. In which case you can always wrap it inside a single function and just do `<MyMarkdown text={bla} />`
But it's not just contrived examples. Here's a list:
<ul>
{(this.state.items || []).map(item => (
<li>{item}</li>
))}
</ul>
vs <ul>
<li v-for="item in items">{item}</li>
</ul>
And here's a simple if/else let loginOrLogout
if (this.isLoggedIn()) {
loginOrLogout = <LogoutButton />
} else {
loginOrLogout = <LoginForm />
}
// snip
<div>{loginOrLogout}</div>
vs <div>
<logout-button v-if="isLoggedIn" />
<login-form v-else />
</div>
React is conceptually simple, but that often forces me to write complex code. Vue lets me keep the code I write (i.e. the only code I actually care about) simple.The reason I say that is because you say "conceptually simple" as if that's a bad thing. Maybe we have to agree to disagree, but in choosing a framework I would much, much rather go for the one that is conceptually simple (at the cost of some extra verbosity in certain cases) over one that is conceptually complex but covers up that complexity with a terse-but-incomplete API.
You're not going to understand the benefits of the Vue vs. React choice by looking at idealized code samples, which is all your comment is showing. You'll only know it once you get into the edge cases. For example for list iteration in Vue...
- ...how do you change that example to omit the last item?
- ...how do you change that example to render a different element for every other item?
- ...how do you render something different if there are no items?
That's what makes the JSX approach simple. Once you understand that you can use any Javascript expression you want, you don't need to learn further. All of those questions can be guesstimated by a newcomer.
But with Vue you have to learn each and every "directive" and "modifier", and consult the docs again each time you forget them.
Just how Vue has JSX support I'm sure react could add template support. I personally wouldn't want anything to do with it as I find JSX a lot easier to work with but it wouldn't be that hard to do.
I also imagine this HN thread will quickly turn into a thread dominated by framework comparisons (it's the main reason I clicked through...)
I would update the article to include this.
Had the exact same experience. After Angular 1, Ember, and React, Vue is the first JS framework that I'm actually excited to use. My three biggest gripes with React are solved with Vue 1) better out-of-the-box experience (CRA is still not ideal), 2) single file components that strike a great balance between templating, logic, and styling, 3) Vuex is a slick Flux architecture with much less boilerplate than something like Redux.
Vue is opinionated enough to give you a sane structure and guidance, but not so opinionated that you feel trapped in their domain and get lost in domain-specfic magic. You might say it's the goldilocks of frameworks. Doesn't introduce any radical new ideas, but MAN does it strike the right balance.
Yes, there is redux-form but the fact that it exists seems like a drawback for React and Redux. Its APIs can be very clunky and not straightforward at all. setState(...) is not a good solution either as things can get more complicated with nested objects and such.
In Vue, you don't even think about this problem. There's v-model which makes forms a breeze.
vue is "easier" with probably less boilerplate at the cost of more magic and less type safety due to magic string templates (if using typescript like I love to)
Definitely not a good tradeoff for me, but it is for some.
How is Vue easier if we only consider components?
How can it offer something simpler than functions as components?
For example, Backbone is much simpler than React. React keeps a full virtual copy of the DOM in runtime and uses complex diffing algorithms to decide when and how to actually update the DOM in a manner which is entirely opaque to the developer. Backbone just does the DOM updates you tell it to, when and how you tell it to. And since Backbone is so much simpler, it logically follows that building an application in Backbone much be much easier than building the same application in React, right? Right?
In Vue, a component generally consists of a raw JS object, an (almost) HTML template, and a block of raw CSS. The framework does some opaque but straighforward work to bind these three together into a single conceptual entity. This is indeed more complex, but the added complexity follows the grain of my preexisting intuitions. The end result, in practice, is components which have a clean internal structure and much less boilerplate. Slightly more complex, but easier.