Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I feel like I'm in an alien world when it comes to Vue - it has this weird pattern of making strings do loads of heavy lifting.

The Github Commits[1] example on their documentation has a load of stuff that just doesn't sit right with me.

Things like

    v-for="record in commits"
to loop over something is insane to me - this isn't code, this is a string inside a html attribute! How can you get any sort of good type analysis/variable checking/syntax highlighting inside this?

Similarly, accessing properties like

    :href="record.html_url"
has the exact same issues - what if there's a typo here? My IDE can't highlight that this is wrong because it's *not code* and is just a string.

Maybe I'm just the odd one out here, but vue (and angular) love to use strings as a makeshift programming language, which to me is a major smell.

^[1]: https://v3.vuejs.org/examples/commits.html



> My IDE can't highlight that this is wrong because it's not code and is just a string

Code is just a string too, treating the 'code' inside the string literals after the v-for is just an extra level of syntax handling - The IDE I use (Intellij) can handle it just fine.


Yeah, this isn't really an issue; it's just a templating language. You can get an extension for your IDE to make it syntax highlight correctly. That's like saying a .js file is just a string. Um, yes I guess sure? All code is just a string. HTML is also just a string. Vue's HTML templating syntax is also just a string, but it's also code. It's code that's mainly HTML, with certain spots that allow full JavaScript. And just like normal code, you can have compile time errors, syntax errors, runtime errors, etc.

Also as a side note: I'd say the best thing about Vue isn't it's templating system, but the fact that it's truly reactive. In react, only rendering is truly reactive. If you have reactive variables that depend on each other, then you have to manually mark those dependencies. Vue can deduce that dependency graph automatically, which makes coding much easier. It's like a giant spreadsheet.


This is exactly the point of vue. On the surface, it looks a lot like a cleaner angularjs, but it's very different. There's no need for a digest cycle to re-evaluate watch expressions on each iteration, because it uses getters and setters to detect changes (though it still supports watchers too). Vue is also very different from React, which (when I last used it) required components to implement shouldComponentUpdate. Vue does this at the cost of breaking compatibility with older browsers (which were not old at all when React and Angular 1.0 came out); I think the tradeoff is worth it.


Vue is brilliant when you actually use it. Nothing you've mentioned is remotely ever a problem in my experience. Also :href="xxx" isn't a string, that is javascript in there.

You won't ever have more than 10 characters at most in an attribute, and if you do you make a method for it and call the method.

The other alternative is JSX type stuff in react where you are injecting full JS into the templates which is like committing seppuku to me. Vue is so much nicer to use than react IMO, and I've used both extensively.


> :href="xxx" isn't a string, that is javascript in there.

This is the part I don't really follow, though. Technically:

    <a href="print(1//3)"></a>
href here isn't a string, it's python, but it's stored as a string, representing python. In the :href example for JS, that's not JS - an engine isn't seeing that - that's a string that is evaluated as JS at some point in the vue lifecycle.


Without refreshing my knowledge on it, I don't think it's actually a string. A <template> block is actually a "single file component" which is a special vue plugin/loader/whatever for webpack. It compiles template/script/style tags into a single compiled version.

I'm like 60% sure that your "string' example is never run in production. So I believe that it gets compiled before vue even sees it (at build time, or dev-server compile time) into the standard method that vue is used to... a vue component:

    Vue.component('button-counter', {
      data: function () {
        return {
          count: 0
        }
      },
      template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })
https://v3.vuejs.org/guide/single-file-component.html


Then that sounds pretty good that it's not ran in production and compiled out!

I guess my remaining alien issue is that the DSL for Vue is a mish-mash of JS, custom syntax, dom attribute context and possibly more?


I think it won't really make sense until you try the alternatives. I've used react since it's inception, vue, ember, angular (going back all the way to angular 1), knockout, etc etc etc.

All these frameworks try to solve what you're mentioning in different ways.

Obviously people have different opinions, but after seeing the way things are done from all these different frameworks, Vue is extremely "clean" and minimal feeling, while remaining extremely flexible. I have built multiple very complicated apps and there's nothing that I'm not absolutely DELIGHTED how it's solved, especially with the new composition API. It feels extremely elegant compared to the other ones I've mentioned.

Perhaps consider the alternatives, and you most certainly will have a much worse development experience if you're not willing to play ball with 2-way data binding (ie use html attributes to bind things, etc). As I said, other frameworks have tried other methods to minimize attribute use and they're excruciating to use. Ember is literally one of the most painful frameworks I've ever used to do even the most simple of things.


Vue template HTML can be parsed by an HTML parser - lots of them available. Can you do that with JSX ? Personally, I find JSX is more of an "alien" than Vue template HTML.


Well, no, because JSX is meant to be parsed by a JS parser and not a HTML parser.


It's not stored anywhere. You seem to be upset that it's written with quotes around it. Are you aware that most computer programs are just text?


Yes.


Not exactly. Template are first compiled to a render function. https://medium.com/glovo-engineering/dissecting-vue-3-templa...

Vue first parses the template into an AST in a process known as the template parsing:

    function compile(template) {
     const ast = parse(template)
     transform(ast, transformations)
     return generate(ast)
    }


All code is text. There is no pure "code" representation, text inside attributes being parsed as JS is no different than parsing text inside some <script> tags.

Also modern component-based JS frameworks all work the same way. The UI definition is a template that's compiled into a render function which produces the final output during runtime. Each framework uses different syntax: React uses JSX which is a domain specific language (DSL) that mixes HTMl-like tags into Javascript. Vue uses HTML with directives on top. Angular, Svelte, etc all use their own formats.

You can even mix and match (use JSX with Vue) or write your own render function if you want, but it's the same text->parsing->lexing->compilation cycle that every language goes through before turning into actual CPU instructions.


> text inside attributes being parsed as JS is no different than parsing text inside some <script> tags.

It is different. Because "text inside script tags" is Javascript. Vue's templating syntax is a weird and inconsistent mishmash of custom DSL, Javascript subsets and Javascript expressions.

And it also depends on when it's parsed.


Text inside script tags is parsed as JavaScript by default. It can be other languages too, like typescript inside a .Vue file.

Again, it’s all just text in different syntax. Programming languages are just a very large and well defined syntax compared to a template language, but that’s all it is.

Vue’s directives offer just enough control to handle 99% of scenarios while remaining within HTML.


> Text inside script tags is parsed as JavaScript by default. It can be other languages too

It can be, but usually isn't.

> Again, it’s all just text in different syntax.

Again, it's not. And the reason is simple: the browser literally knows nothing about other syntaxes but Javascript [1]

So, no, "text in Vue" is literally not the same as "text in script tags". It is a mish-mash of:

- Vue's own DSL (see v-for)

- JS expressions that are wrapped in some scope (see v-if)

- JS-like DSL where function cals are not function calls, there are magic vars, but objects are also fine (see v-on)

- Maybe JS expressions in v-bind? But depends on the attribute name? Can use string concatenation, but anything else?

- Actual JS expressions in {{}} which can't be used just anywhere... but then these expressions can have pipes into filters in them? And filters once again are JS-like, but are not

None of this has any coherent specification, and we rely on Vue to properly parse and break it down into actual Javascript code that can then be included in a <script> tag.

Edit: I had the same laundry list of things for Svelte before Svelte 2, but Svelte 3 is significantly more consistent and coherent in what it expects in a template.

[1] There are ways to make it know other syntaxes, but that is rare and has largely fallen out of favor.


The point is that all code starts as simple text, and is parsed and compiled into some lower layer until it finally gets to machine code. What actually does the compilation is irrelevant.

All of these JS frameworks (React+JSX, Vue+HTML, Angular, Svelte, etc) require template compilation into an actual JS render function before a browser ever runs it, but compilation is the same fundamental process regardless of language or environment: https://en.wikipedia.org/wiki/Compiler

So yes it's all just text following a different syntax, and Vue's documentation already describes exactly what you can run: https://v3.vuejs.org/api/directives.html


> The point is that all code starts as simple text, and is parsed and compiled into some lower layer

Yup

> What actually does the compilation is irrelevant.

Nope. It is relevant. For the stuff you put between script tags there's at the very least https://github.com/tc39/ecma262 that you can look at and tell exactly what's going on with your code.

With Vue (and, yes, React and Svelte and Angular): who knows? It might very well evalueate strings at runtime for all we know.

> All of these JS frameworks (React+JSX, Vue+HTML, Angular, Svelte, etc) require template compilation into an actual JS render function before a browser ever runs it,

Yup. It's an additional, different step before it can even get to the browser. The problem with this step is that for most of this code there's not even a coherent specification of what it is, and how it's compiled.

> and Vue's documentation already describes exactly what you can run

It really doesn't. For example, here's the "documentation" on v-for:

    Expects: Array | Object | number | string | Iterable
Expects where? Is this correct:

    <div v-for="{ a: 1, b: 2 }"></div>
Answer: no. Because the actual description of what is expected is written in examples. Same goes for every single other directive. I mean, v-bind expects "any (with argument)" (what does this even mean?) and v-if expects "any", and both of these are false statements.


The topic is that all code is text, and everything can be parsed and understood based on specific language grammars, even if they're embedded within each other.

What are you even arguing at this point? This isn't about compilation or strings anymore. You don't like Vue's specific DSL? Or you don't understand it? Or you found a problem with the documentation? Or do you need a full grammar and syntax definition before you can do anything?

It's basically any valid `for..in/of` expression but you can always solve your mystery of "who knows" by just looking at the source code: https://github.com/vuejs/vue-next/blob/master/packages/compi...


> What are you even arguing at this point?

That Vue isn't "the same as text between script tags". Because "text between script tags" is fully specified, and known to the browser.

Vue's ad-hoc mish-mash of DSLs has to go through an unspecified series of transformations before it can even become a "text between script tags". And that's the issue not just with Vue, but with any other templating layers.

> but you can always solve your mystery of "who knows" by just looking at the source code

Ah yes. The good old "code is the source of truth" fallacy. Can you point to me where exactly in code it specifies this: `Expects: Array | Object | number | string | Iterable (since 2.6)`?


Yes, Vue directives aren't JS. It's a separate DSL. The whole point is that it is a syntax that can be parsed, compiled and understood rather than just "strings".

I'm not sure why you're stuck on this. Templates are just a more simplistic programming language. That's how so many IDEs can still provide help with them.


> It's basically any valid `for..in/of` expression

This isn't true at all though, because `for x in y` is invalid JS.


How is it invalid? Here's the syntax about a for..in loop: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

   for (variable in object) {
     statement
   }
The only difference in Vue is not having to explicitly declare the variable. But so what?

You said "strings are magic and not code" to which I said "all code is text so there are no magic strings". Now you and the other poster keep saying "well this string isn't the same syntax as JS" but I don't see what the point is. Why does it have to be valid JS?

Again, you can embed syntax within each other just fine. JSX has HTML tags inside JS. HTML has tags like <style> and <script> for other languages (regardless of what the default language is or what parses it).

So, for the last time, what's the actual argument?


> How is it invalid? Here's the syntax about a for..in loop

   for (variable in object) {
     statement
   }
And here's the syntax for Vue's for..in loop. Only one of it is somewhat Javascript:

   item in items
   (item, index) in items
   (val, key) in object
   (val, name, index) in object
And, of course, there's an extension to that

   v-for="item in items" :key="item.id"

Edit: additionally, from that very link: "for...in should not be used to iterate over an Array where the index order is important." But this doesn't concern Vue, it maintains the order in its for..in.


Because that loop doesn't do what you think it does?

for...in iterates over the keys of an object, but for in in vue iterates over the elements of an array.


Actually, for ... in does both.

It is you who doesn't think that loop does what it actually does.

Please read the spec and verify with your favorite JS runtime before continuing this argument.


    for (x in [6,1,6,2,6,3]) {
      console.log(x);
    }
Please run this in your browser console and tell me if it iterates over the elements of the array.


It does exactly what I think it does, which is either iterate over the properties if it's an object or the elements if it's an array. This is true for Vue and Javascript. I suggest you read the documentation I linked earlier.

Also Vue's directives are not JS. It's a separate DSL. I've repeated this enough so I'll end this discussion here.


> This is true for Vue and Javascript.

This is not true for javascript at all.

    for (x in [6,1,6,2,6,3]) {
        console.log(x);
    }
Please run this in any javascript runtime.


In Javascript, `for..in` prints the keys. In an object, the keys are the properties. In an array, the keys are the indexes. If you want the values then use the key to lookup the value from the object or array.

Either way it's entirely consistent: an iterator that works on both objects and arrays and prints the keys without guaranteeing order. Does that clear up the confusion?


This is not a regular string, it is a template. And the tooling handles it just fine.

You get type checking, linting, syntax highlighting etc.


If it's a template then it's a very complex one, and under closer inspection it reads almost like storing code in a string and evalling it.

Let's say we want to iterate over commits in reverse. A google shows that we can do something like this:

    v-for="item in items | orderBy 'field' -1"
So, there's pipes now, and Vue has essentially re-invented a programming language inside HTML attributes. But then comes this example below it:

    v-for="item in _.reverse(items)"
And this line is terrifying! If this string is able to use lodash, then that means it's able to access the JS global scope, and therefore is very powerful - yet the resulting template is nonsense js, but still at some point involves JS evaluation?

Maybe I'm missing something though - I don't use Vue and if something is this big with this approach, I'm definitely missing something.

EDIT: A search for *new Function(` calls in the vue github repository shows quite a lot of code that essentially evals strings.


I don't know if you haven't had much experience with templating engines, but having the ability to write programmatic expressions to make a layout dynamic is a basic necessity that pretty much every known templating engine has. "It reads like storing code in a string and evalling it" sounds very funny in this context because that's exactly what every solution does and it works pretty well in practice.


My issue isn't the existance of programmatic expressions (yeah, it's the point of templating languages), but more that the way vue (and angular) do it is a mess of syntaxes that creates a really, really strange template.

The lodash example is the main critique because that is not JS, but it involves evaluating JS - it's created its own programming language with its own rules -- when one was right there from the beginning!


Like any templating engine there's always just enough power given to have the ability to write something stupid or complex in the template. Again not really a problem in practice.

The scary underscore expression you're referring to can easily just be written as a reversedList variable in "normal" JS and get referenced plainly in the template. So the template expression syntax never has to be as messy as you might think it is.


The "scary underscore" expression isn't scary because it's an underscore, it's because it implies the evaluation of JS, such that you could (and obviously wouldn't) do things like

    v-for="x in console.log('hello world!') && fetch('/') && [1,2]"
(my syntax might be off since I don't use Vue, but the merit should still apply)

My point is that when your templating language starts doing things like this (and inevitably, all of them do) - you've created a new programming language that is generally less thought out as one than deliberately made programming languages. Although the above for loop is evaluating JS, the syntax is decidedly not JS.


Angular doesn’t evaluate the code of the template. Example with lodash will not work out of the box in Angular.


> "It reads like storing code in a string and evalling it" sounds very funny in this context because that's exactly what every solution does.

Its not, though. JSX-based solutions (not just React, but Solid and others) don't (actually, neither do many frameworks with more traditional-looking templates, including, AIUI, Vue, actually compile templates to render functions, so it just looks like old school “string with embedded code which is evalled” ttemplates)


I know it's pedantic but this is still JavaScript we're talking about not binary so the "compiled render function" is still ultimately just "a string that gets evaled".

In any case the implementation details aren't important it's what it appears to be that is apparently the problem.


> it's what it appears to be that is apparently the problem.

Yep, Someone mentioned in another part of this thread that Vue compiles most of this out before production, so my remaning confusion pretty much stems from the DSL being a mishmash of html attribute context, vue custom syntax, and evaluated JS.


Templating is the wrong approach. Component-based approaches where you use polymorphism rather than putting logic in your templates are much better. Look at Wicket for a HTML UI framework done right, IMO.


People like templates, and the clear and declarative correspondence between input and output.

You can write React without using JSX, and I assume Vue without templates, but unless the components system has a declarative layer so thin it might as well be templates (e.g. elm, or clojure’s hiccup) and it is entirely expression based, they’ll want templates.

Wicket looks like absolute nonsense of the worst kind. It completely reminds me of Struts and Spring and friends, and that is not a positive comparison.


> People like templates, and the clear and declarative correspondence between input and output.

You don't get that clear correspondence if you can have logic in your templates, and even supposedly simple expression languages in templates somehow always end up growing ifs, looping constructs and so on. Plain HTML fragments are good, but they need to be kept absolutely simple.

> Wicket looks like absolute nonsense of the worst kind. It completely reminds me of Struts and Spring and friends, and that is not a positive comparison.

I don't understand your position at all. The problems of Struts and Spring are the problems of templates only more so - if I were to make a spectrum I'd have Struts (and Tapestry) at one end, Wicket (and hiccup) at the other, and traditional templates somewhere in the middle.


> You don't get that clear correspondence if you can have logic in your templates

You absolutely do.

> I don't understand your position at all. The problems of Struts and Spring are the problems of templates only more so - if I were to make a spectrum I'd have Struts (and Tapestry) at one end, Wicket (and hiccup) at the other, and traditional templates somewhere in the middle.

The struts I got to use was full of "smart JSP custom tags" because "components are the right way" and subclasses all the things, it looked exactly like the examples I see of Wicket: keep bouncing through layers and files of useless nonsense because all the logic has to be out of the markup but all of the markup has to be out of the code, and formatting a list takes you through 3 templates and 5 classes.

> Wicket (and hiccup) at the other, and traditional templates somewhere in the middle.

That makes no sense whatsoever. Wicket and hiccup have nothing in common.


> The struts I got to use was full of "smart JSP custom tags"

Which is very much the opposite of how Wicket does things: there are no custom tags, the templates are inert HTML and there's a very small, non-customizable set of wicket tags/attributes (IMO the right way to do it is just IDs).

> That makes no sense whatsoever. Wicket and hiccup have nothing in common.

What they have in common is that all your logic is in code, not markup.


would you have preferred

  {{ for item in items | orderBy 'field' -1 }} ?
I feel like you're getting hung-up on the fact that the template directive is also a valid attribute and not something similar to jinja - but that's just syntax


I don't really see much of a difference - that is still storing it as a text attribute inside a DOM node.

To be clear, I vastly prefer Reacts approach of putting HTML into JS, rather than Vue/Angulars approach of putting JS into HTML.


It never ends up on a DOM node. The template is compiled into a render function.


This has been the debate of templating systems for as long as I can remember. Do you want your looping construct to use the same syntax as your markup language (so all the tools you use that operate on the markup "just work", without any modifications)? Or do you want to use the same looping constructs as the language you are programming in (so there's no need to invent or learn a DSL built on top of a markup language)?

Both approaches are valid, and each comes with its own set of tradeoffs.


Yeah well, its not really HTML - its JSX and it reads quite differently. Most folks who create HTML prefer to read HTML not Reacts domain language. HTML is a documented world-wide standard implemented by web-browsers. JSX is not.


You are trying to discuss things you have never tried in practice, just saw some examples in the docs. Your opponents are trying to explain this fact politely.


>My IDE can't highlight that this is wrong because it's not code and is just a string.

Webstorm has zero problems letting me refactor it, because it can parse vue code in .vue files. This is seriously a non-issue.


> My IDE can't highlight that this is wrong because it's not code and is just a string.

WebStorm and its bigger brother IntelliJ IDEA can handle this.


Which IDE are you using ? There is probably a plugin that parses and offers checking for Vue Template Syntax https://v3.vuejs.org/guide/template-syntax.html


This purism is why we can't have nice things.


A long, long time ago, in a galaxy far, far away, there was a thing called Coldfusion. And js peeps seem to want to reinvent it.


Many users - who weren't programmers by training - loved CF for the ease of understanding. They had a DX paradigm that worked and I understand why people try to emulate it. It's a question of audience, and not for the HN crowd.


Except that SPA frameworks are designed to complicate things, not to make them easier to understand. And SPA framework developers are crazy expensive, mor expensive than seasoned C++ systems programmers. (The two facts are probably linked.)


Have you ever developed a complicated front-end system? Not using a vue/react style framework would be ludicrous (ie, building something like Facebook Ads UI or Google Analytics UI). I find it super bizarre you say "complicate things" when they do 100% the opposite. I would love to understand what you would use if you were tasked with building FB Ads manager interface: https://disruptiveadvertising.com/static/61a4440576bffd6e6a2...


> I find it super bizarre you say "complicate things" when they do 100% the opposite.

They're way, way overengineered for the very limited use cases they're designed for.

If you're going to ditch the browser API's and re-write the world in Javascript, why not take into consideration all of the history of GUI development and do it right? I.e., make a real layout engine, proper widget hierarchies, real encapsulation, etc.

Instead there's some sort of frankenstein in-between state where you've ditched all the benefits of native browser API's but haven't arrived anywhere that's a true paradigm shift.

TL;DR - yeah, they make some things easier to reason about, but for any sort of non-standard webapp you'll still need to write an equivalent mountain of hacks and framework adaptors.


"very limited uses" mmmmm what? Reactive frameworks are one of the widest used front-end design patterns.

You answered my questions with a bunch of theoretical non-answers that comes off like a tech purist who hasn't actually used the technologies but has a lot of opinions about them. Do you have a lot of experience designing non-trivial/complicated web apps with very heavy front-end features? "layout engine", "widget hierarchies" what _exactly_ does that mean in the context of designing something as complicated as Google Analytics/FB Biz Manager using javascript. If you are proposing not using primarily JS logic but rather server logic, or not as a SPA (or isometric hybrid like nuxt/next), then that makes me want to hear your answer even more.

Answer the question of: how would you do it?


> Coldfusion

another dsl? mind-blowing! where haven't I seen that.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: