6 ms·
> Vue uses a templating language closer to default HTML than to JSX, which makes it much easier to write conditionals and loops in template files, without havin
by have_faith 3y ago
> Vue uses a templating language closer to default HTML than to JSX, which makes it much easier to write conditionals and loops in template files, without having to reach for workarounds like map and ternaries
I like react/jsx precisely because I can use language constructs like filter, map, reduce, etc, instead of a custom implementation of basic things like if statements and loops. I find this much more ergonomic and didn’t realise some people see this as a “workaround”.
Worth also pointing out that when you write these templates, as strings or template literals, they might resemble HTML in appearance but really have no relation to actual HTML except what they output after processing. All of the added directives also have no equivalence in HTML. You’re just writing JS indirectly.
- no_wizard 3y agoIn defense of those directives and template languages, they compile down to efficient operations that every developer can take advantage from. I like that `v-for` is likely more efficient in regards to how it operates than how an average developer might write such a function, especially when dealing with nested data or more complex situations. Other efficiencies can be gained by using a template language as well via the compiler. Not that you can't with JSX (Solid and Qwik use JSX and have transparent ways of doing optimizations as consumer of those frameworks) but its not currently the default, most (if not all) optimizations must be done "by hand", is a big tradeoff for some places.
- MrJohz 3y agoThis can be the case, but as I understand it typically isn't so, at least with most big frameworks. For example, I believe Vue templates are typically translated to a hyperscript-like render function that has a similar efficiency to the average React render function. Indeed if anything, I would imagine Vue would be slightly less performant, because the v-for loop is quite abstract and can handle things like looping through objects, so there must be a reasonable amount of machinery to handle all the different loop cases. The state of the art is less about handling things like loops, and more about reducing the amount of work needed to render static elements. For example, say you have a single component that renders a static table, and in each cell of the table you need to render something dynamic. In the classic vdom system, you'd construct a `table` node, with a `tbody` child, which in turn has `tr` children, which was contain `td` nodes, and then finally in the `td` nodes you render the dynamic content. This works, but most of the content isn't actually changing, only the contents of the `td` nodes. What modern frameworks like Solid and Svelte do is to compile that whole nest of nodes into a single HTML string, and then add instructions that specify where exactly the dynamic content lives. That way, on the initial render, the browser is doing more work natively, and on later updates, only the new content needs to be checked and changed. I know there's a library for React that adds similar capabilities there, albeit with a few more constraints than in other frameworks. I do know Solid does for-loops differently than in other frameworks, but this is less to do with efficiencies gained by compiling, and more about how to optimally use the signals system that it uses for reactivity. Apart from that, I don't really know of any optimisations that would make something like `v-for` any faster than `.map(...)`.
- no_wizard 3y agothe Vue compiler does do optimizations you can't get if you were to write the components by hand, most of the time. I did only use `v-for` as an example of sorts though, and in the common case, `v-for` vs a regular `for` loop are similar if not the same, IIRC, but in some cases where your children may show or hide based on downstream data, it can be more efficient
- mmcnl 3y agoThis discussion never ends. It's so subjective and totally not important at all. Templates shouldn't contain complex logic anyway, only formatting logic with some for loops. You can learn any syntax in 30 minutes if needed. The battle isn't fought on the hills of templating logic. It's sad because there are many interesting differences other than templating logic between frameworks, but they are less superficial so they get little attention.
- yid 3y agoYou know you can use JSX with Vue right? https://vuejs.org/guide/extras/render-function.html https://vuejs.org/guide/extras/render-function.html
- remram 3y agoGP was reacting to this statement from the article: > Vue uses a templating language closer to default HTML than to JSX, which makes it much easier to write conditionals and loops in template files
- stevage 3y agoIn practice with Vue you tend to write that stuff in JavaScript (eg in a computed property) and keep the HTML as simple as possible. I've done a lot of Vue and your bit of React and overall I prefer the Vue way here.
- tiku 3y agoBut you want to avoid using to much code in HTML, because this isn't "page.php?page_id=welcome" anymore..
- marksomnian 3y agoPlus, the power of being able to treat JSX as any other JS object means that you can use standard JS constructs like loops - slightly contrived example: const items = []; let runningTotal = 0; for (const item of someArray) { runningTotal += item; items.push(<li>Item {item}; running total {runningTotal}</li>); } return (<ul>{items}</ul>); The closest example I can find in Vue would require a computed property to implement something like this.
- mmcnl 3y agoIt's technically possible, but it looks horrible and should be avoided because of lack of readability. Keep the templates plain and simple, and store your business logic elsewhere.
- dglass 3y agoDisagree. I would argue your example is hard to read compared to the equivalent in Vue, and it mixes business logic (computing the running total) with the rendering logic. <script setup> const items = [1,2,3,4,5,6] let runningTotal = 0 const getRunningTotal = (item) => { runningTotal += item return runningTotal } </script> <template> <ul> <li v-for="item in items"> Item {{item}}; running total {{ getRunningTotal(item) }} </li> </ul> </template> No need for a computed property. Plus, getRunningTotal can be unit tested, or extracted to another file for reusability.
- gsuuon 3y agoDoes syntax highlighting or lsp stuff work for things like v-for?
- porridgeraisin 3y agoYep. There's a vscode extension.
- nenaoki 3y agoYou've still mixed the logic, just in a horrendously oblique manner. If you rendered the list twice the second list's running totals would be wrong from re-use of the global variable (in what is meant to be render-only logic). If you're after keeping the concerns separate you would need to precompute the running total for each item. See also: mustache(5) which completely embodies this philosophy.
- snorremd 3y agoThis. Most of the value-proposition of JSX is that it is just JavaScript and as such you just write code logic like you would normally do. Need to filter some items? You can do that with the Array.prototype.filter method you already know. Do you need to return a list of components based on some list of object values? Just use Array.prototype.map. I never really understood those that see this as a weakness and would rather learn a more limited set of template string functions that work kind of like, but not entirely like, the native JavaScript collection functions. Yes, using a ternary operator in JSX to conditionally render components/values looks a bit ugly, but nothing is stopping you from making a wrapper component like: <If cond={...}><div>Conditional content</div></If>. Also with JSX/TSX scopes behave exactly like they do in regular JavaScript, because it is regular JavaScript. Templating languages often invent their own form of scoping mechanism.
- jcparkyn 3y ago> nothing is stopping you from making a wrapper component like... I'd suggest avoiding that, since the inner JX expression will be evaluated even if cond is false. In the best case this just means some unnecessary allocations, but in other cases it can cause unexpected errors (e.g. you check obj != null then try to use it inside the if).
- jpochtar 3y agoYeah you have to do <If cond={...} then={() => ... } els={() => ... } /> so the `then` and `els` branches only get evaluated if needed
- the_gipsy 3y agoI get using plain JS, but JS's lack of expression-statements (see rust for contrast) just makes most of it EXTREMELY awkward. Ternaries, booleans that cast to JSX, switch statements wrapped in IIFs...
- hajile 3y agoThe crazy part is that there's not a really good reason why we couldn't make if..else function as either a statement or expression depending on the context. I think there's a proposal to do that.
- bafe 3y agoIndeed, at least there's a TC39 proposal for that. It should be the default for all statements and it's shocking that python went to define the new match clause to be just a statement and not an expression
- bafe 3y agoOnce you try any languages where (almost) anything is an expression, it is hard to accept statement-oriented languages
- the_gipsy 3y agoThat's true. But in JSX you have the extra constraint that you can't really use imperative code so this magnifies even more.
- bafe 3y agoIndeed, having if-then-else being an expression (as well as switch) would be great in JSX. It seems there's a proposal for a match expression in TC39...
- babyshake 3y agoEspecially with copilot, which is clearly well trained on React and JS, I find I often just need to write the first few characters of an array method or other common method and it will generate 10 or so LOC that are at least 90% of what I want.
- WuxiFingerHold 3y agoI liked JSX a lot when I was using React. However, writing business or view logic in templates is a maintainability nightmare. With JSX it's very tempting to do this and I did this often, but it's still a mistake and I regretted it every time I visited my spaghetti JSX months later. When it comes to comparing React with Vue or Svelte, the templating is not the critical factor.
- mmcnl 3y agoI totally agree. Templating is not the critical factor indeed. The templates shouldn't contain business logic so they should be simple by default. If not then you're following an anti-pattern.
- tshaddox 3y agoThe JSX bits in a React codebase aren't templates, at least in the traditional sense where a template is a static file that looks like some desired runtime output and contains some "slots" which are analyzed at build time (or program start time) and then filled in with dynamic values at runtime. JSX kinda looks like that, but there is actually no "templatey" stuff happening at build time, i.e. React does absolutely no analysis whatsoever of your JSX and has no idea what it contains until each new time a component renders at runtime.
- mmcnl 3y agoStricly speaking it's a render function indeed, but it does serve the same functional purpose as what people usually call "templates", i.e. defining a dynamic view only once.
- tshaddox 3y agoThat’s true, but the technical differences between a render function and a traditional template is arguably the biggest fundamental difference between React and most other UI rendering tools.