Hacker News new | ask | show | jobs
by dmitriid 2899 days ago
> The amount of special cases in Vue templating syntax is comparable to the special cases and gotchas of JSX

This is patently not so.

Vue has:

- three different html-like attributes

- three different scripting languages in templates (two Javascript-like, one Javascript, but only expressions)

- one scripting language for controller/model which actually breaks JS assumptions (about what `this` is, for example) by magiacally hoisting some (but not all) properties of an object

https://pbs.twimg.com/media/DbVEoKOX0AEEen6.jpg:large

1 comments

    This is patently not so.
Maybe if you are used to JSX.

    - three different html-like attributes
: and @ are just shorthand for v-bind and v-on attributes.

v-bind and v-on (and v-if) accept regular javascript, and it's not just expressions... you can use `active = true` to change a data value, for instance.

The only exception is v-for, as you mentioned, but it is close enough to ES6 for syntax to make sense, at least IMO.

    - three different scripting languages in templates (two Javascript-like, one Javascript, but only expressions)
This is splitting hairs a bit, isn't it? Apart from v-for, you can write pretty much anything you want in the other two.

    - one scripting language for controller/model which actually breaks JS assumptions (about what `this` is, for example) by magiacally hoisting some (but not all) properties of an object
You mean the script part of components? Do you have any examples of that?
> just shorthand

> accept regular javascript... The only exception is... but it is close enough to ES6

So you basically validated all I've said. And it's also incomplete. Because the amount of gotchas and things that you have to constantly keep in mind in Vue is mind-boggling compared to JSX. Because JSX is a paper-thin wrapper on top of React.createComponent, and goes out of its way to keep everything in Javascript. Unlike Vue.

Lets see your defence:

- : and @ as shorthands

It means new syntax that you have to learn, and know differences between. For all intents and purposes Vue has three different types html-like attributes. JSX has only one: javascript names.

- v-bind etc. accepting regular Javascript

Let's see how this is false:

    <label @click="edit(todo)">
This is not Javascript. If it was, it would assign the result of the function call to @click. It doesn't. It's a Javascript-like scripting language that has magical binding into regular Javascript.

- exception is v-for, as you mentioned, but it is close enough to ES6 for syntax to make sense

So, it's not Javascript (unlike some other places where it is Javascript), and it's not ES6 syntax, but it's "close enough to ES6". So it's not. It's a different Javascript-like scripting language.

The only place where Vue allows regular unadulterated Javascript is inside curly braces: {{}}. And there it only allows expressions (Note: JSX also only allows expressions inside curly braces).

However. Even there it's not Javascript. Not really:

    {{ record.commit.message | truncate }}
Valid Vue. Invalid Javascript.

- You mean the script part of components? Do you have any examples of that?

Of course. See inline comments. Example from here: https://vuejs.org/v2/examples/tree-view.html

    Vue.component('item', {
      template: '#item-template',
      props: {
        model: Object
      },
      data: function () {
        return {
          open: false
        }
      },
      computed: {
        isFolder: function () {
          // `this.model` magically hoisted into `this`
          // from `object.props.model`
          return this.model.children &&
            this.model.children.length
        }
      },
      methods: {
        toggle: function () {
          // `this.isFolder` magically hoisted into `this` from
          // `object.computed.isFolder`
          if (this.isFolder) {
            // `this.open` magically hoisted into `this` from
            // `object.data` which is a function that 
            // returns an object whose keys and values are hoisted 
            // into `this`
            this.open = !this.open
          }
        },
        changeType: function () {
          if (!this.isFolder) {
            // this.open can be set directly. Magic
            // this.model.children cannot. Not magic
            Vue.set(this.model, 'children', [])

            // `this.addChild` magically hoisted into `this` from
            // `object.methods.addChild`
            this.addChild()
            this.open = true
          }
        },
        addChild: function () {
          this.model.children.push({
            name: 'new stuff'
          })
        }
      }
    })
Just wanted to add to your argument an inverse argument (for JSX, instead of against Vue):

JSX is actually just JavaScript with this one special rule:

    <foo bar={baz}>child1 {child2}</foo>
becomes

    transform("foo", { bar: baz, children: ["child1 ", child2] })
That's it. All the rules of JSX can be inferred from that one transformation.
> Let's see how this is false:

    <label @click="edit(todo)">
> This is not Javascript. If it was, it would assign the result of the function call to @click. It doesn't. It's a Javascript-like scripting language that has magical binding into regular Javascript.

You're wrong. The contents of the event handler is JS, the whole snippet is obviously HTML.

    <button onclick="alert('Hi')">Say Hi.</button>
This is also plain regular HTML and has been since HTML4 (1997). The value of the onclick attribute is a string of JS. There's no assignment of the result happening. It registers a click handler. The only difference between the two, on a surface level, is that the Vue example has things in scope (edit and todo) that aren't globals.
I love it how you chose just one of so many things listed. And how you got it so wrong:

> This is also plain regular HTML and has been since HTML4 (1997).

What below is plain regular HTML? Taken from here: https://vuejs.org/v2/examples/tree-view.html

    <div
      :class="{bold: isFolder}"   <--- binding to JS-like objects doesn't exist in HTML
      @click="toggle"             <--- If it was HTML it would've been toggle()
      @dblclick="changeType">     <--- If it was HTML it would've been changeType()
      {{ model.name }}            <--- etc
      <span v-if="isFolder">[{{ open ? '-' : '+' }}]</span>
    </div>

Oh. Ooops. None of it. It's a custom HTML-like DSL with three types of magic attributes (magically bound to some Javasdcript code) with three different scripting languages in it.

For reference: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Ev... etc.

Edit

Let's add more "plain old HTML". Plain old HTML v-ifs that accept JS booleans. Ah, plain old HTML v-fors that accept a ES6-like (but not truly ES6) mini-DSL. And other plain old HTML attributes.

    <ul v-show="open" v-if="isFolder">
      <item
        class="item"
        v-for="(model, index) in model.children"
        :key="index"
        :model="model">
      </item>
      <li class="add" @click="addChild">+</li>
    </ul>
Have you ever made a graphql server with apollo-tools? Do you complain that SDL is a "new syntax" that you have to learn when you can just use regular javascript?

> <label @click="edit(todo)"> > This is not Javascript. If it was, it would assign the result of the function call to @click. It doesn't. It's a Javascript-like scripting language that has magical binding into regular Javascript.

Great, so it's not javascript.

To a lot of folks it looks a lot nicer than

<label onClick={() => this.edit(this.state.todo)}>

There's a lot less noise, and it's _much_ friendlier for (most) designers.

I have never felt that I had to keep hundreds of gotchas in my mind while using vue. The syntax is extremely intuitive (unlike angular). Takes maybe one hour to read through the docs, and you have it.

> Have you ever made a graphql server with apollo-tools?

Have I ever mentioned apollo or graphql tools? Let me check: no

> There's a lot less noise, and it's _much_ friendlier for (most) designers.

I love how you could find exactly one thing out of a whole list of things that may be just ever so slightly better than JSX.

And of course, it's not better than JSX for very obvious reason that you chose to ignore: how { } in JSX accepts plain JS with the only exception that it has to be an expression. And (and it's the most important part): curly braces in JSX mean and accept the same thing everywhere in JSX.

In Vue though: What do @ attributes accept? What do : attributes accept? What do curly braces accept? etc.

My only point in mentioning apollo-tools is that DSLs are very powerful, and have the potential to make complex problems much simpler. SDL is a great example of is, as are vue templates. You may not appreciate the DSL, but, believe me, there are a lot of people who much prefer it. I'm specifically calling out designer type folks here.

> I love how you could find exactly one thing out of a whole list of things that may be just ever so slightly better than JSX.

It's not a question of "better" or "worse". It's a question of tradeoffs on spectrum of abstraction.

I'm not here to bash JSX or react. But you apparently are, and I'm just trying to open your eyes a bit.

When vue came out with JSX, I tried to force it on my team, and there are a serious backlash, to the point where I came to realization that the vue's major strength is actually the templates, and the magic.

You may not like the magic, but a lot of folks do.

As for your specific questions

@ and : are just short hands. That's like saying: what's the difference between `map` vs `reduce` in my component to iterate over an array. They _can_ do the same thing, but map is shorter. In plain JS I can do `i = i + i` `i += i` or `i++` to increment an variable.

@ just means "event handler". @click = "onClick" : just means "use a dynamic value for this prop { } you can put any JS expression, with the plus that you don't have to litter your code with `this`.

Additionally:

> with the plus that you don't have to litter your code with `this`.

"Littering code with this" is exactly how plain old vanilla JS works. Besides, "littering your code with this" very much depends on where your callbacks and variables come from... as in any old plain vanilla Javascript code. Because JSX is a paper-thin DSL on top of vanilla JS. Brilliantly and succintly described in this comment: https://news.ycombinator.com/item?id=17474370

In Vue you don't litter your code with this. You litter your code with hoisted variables and functions that are arbitarily hoisted into scope and injected everywhere. See my comment here: https://news.ycombinator.com/item?id=17471199 starting at "Of course. See inline comments."

The amount of gotchas and special syntaxes, and special cases, and the amount of moving part you have to understand to see where things come from and go to in Vue is insurmountably larger than in JSX.

> My only point in mentioning apollo-tools is that DSLs are very powerful, and have the potential to make complex problems much simpler.

Yes. But just because it has that potential, doesn't mean that Vue's DSL(s) are not without the many problems anf gotchas I described. Just because Apollo's/GraphQL's DSL is potentially good, doesn't mean that Vue's is. etc.

> It's not a question of "better" or "worse". It's a question of tradeoffs on spectrum of abstraction. > I'm not here to bash JSX or react. But you apparently are, and I'm just trying to open your eyes a bit.

My eyes are wide open. Where in JSX I see a uniform approach that works in all JSX contexts, in Vue I see several DSLs bound together by magic of the library.

> @ and : are just short hands. That's like saying: what's the difference between `map` vs `reduce`

Shorthands mean:

- new syntax. For all intents and purposes it's a new syntax (call it a DSL syntax). And you have to know the difference and gotchas of that syntax. You have to know where you can:

-- provide a thing that looks like a function ref

-- provide a thing that looks like a function call

-- provide a thing that looks like a bound variable

-- provide a thing that looks like a Javascript expression

etc. etc. etc.

And that is further compounded by the fact that `v-` attributes sometimes take single Javascript-like expressions, sometimes not (v-for), some have additional "arguments". some have additional modifiers etc. etc.

And of course, some of it is Javascript expressions inside strings (`v-` attributes), some of it is Javascript-like (but not really Javascript) DSL inside mustache's curly braces (inside tags).

So here's the original statement that started this thread: "The amount of special cases in Vue templating syntax is comparable to the special cases and gotchas of JSX"

This is demonstrably provably patently not so, as this thread has demonstrated.