Search posts, tags, users, and pages
Given my opinion of the train wreck laundry-lists of how NOT to use HTML, CSS, or JavaScript that are mentally enfeebled DISASTERS like vue and react...
I don't like 'em, you can have 'em, he's too fat for me...
I dislike Angular and React, but Vue has been fairly fun to learn, and seems to be a fair evolution and departure point away from jQuery.
I'm a fan of "vanilla" everything. But Vue seems interesting enough to continue the course I'm taking on it.
So, do me a favor, dive into it and "cut it down" for us - so we can avoid adopting a stepford child.
So, do me a favor, dive into it and "cut it down" for us
I had trouble getting through the TUTORIALS before my bullshit alarm was being triggered by vue... it actively encouraging methodologies and mindsets that run entirely contrary to what I had understood to be good practices.
Let's use something direct out of their tutorial, the event handling section:
vuejs.org/v2/guide/events.html
<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
Epic /FAIL/ at web development. This is obviously client-side code... so... Scripting only elements in the markup? Scripting onevent style methodology?
Even IF the v-on: is intercepted and built from the scripting instead of as an actual onclick, this reeks of the same mental huffing midgetry as the derps who spent time implementing target="_blank" with scripttardery because it was deprecated in 4 strict, completely missing WHY it was deprecated. Much less that in order to work they're either adding even MORE string processing, ACTUALLY using the onclick attribute we've been told for a decade and a half to stop using and doesn't even EXIST under the CSP, or are using "with" which means you can't "use strict" the code! NONE of those three paints a particularly rosy picture!!!
Pretty much NEITHER that input or paragraph have ANY business in the markup or being built via markup-style methodology. You're either adding string parsing for nothing, abusing the DOM, or a hideous combination of both!
... and even that DIV is negotiable, but for now we'll assume it's serving a purpose... as such if I were writing that functionality it is doubtful that what I'd write as HTML would be more than:
<div id="example-1"></div>
As simply put, NONE of the rest of that belongs anywhere except in the script as DOM generation.
Though I would more likely have written this:
<div id="example-1">
<noscript>
<p>
Notice here about needing JavaScript and/or
code providing a scripting-off/blocked fallback
</p>
</noscript>
<!-- #example-1 --></div>
I know, JOE FORBID we plan for what happens scripting off! It's NOT huffing rocket science people, get off your lazy asses and DO IT!
The scripting itself isn't too horrific apart from HOW it works with markup methodology.
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})
If you're going to have a complex structure to handle this, HUFFING HANDLE THIS!!!
This is made all the more DANGEROUS by the expectation that instead of just changing what changes, it actually seems to have that {{}} thing implemented in a manner that would require a complete reparse of that section of the live document or a replacement JUST to show the change, instead of isolatiing that one changing part in it's own DOM node and changing JUST what's different. JOE FORBID we be expected to control our own huffing output!
It's "false simplicity" -- blindly trusting their system to handle something for you that makes the actual task harder, less clear, and can very quickly lead to codebases that reek of "don't tug on that, you don't know where it's attached!". No matter how simple it LOOKS. Less code often does not == simpler!
Hence I'd probably end up doing it more like this -- this uses the upcoming version 4.0 of my elementals.js library and the DOM-JON format. (which I'm hoping to release sometime this week or next, internal testing taking longer than planned)
_.Node.write('example-1', [
[ 'button~Add 1', {
type : 'button', // so we don't have to preventDefault
onclick : function(e) {
var count = _.Node.getData(e.currentTarget, 'data-counter')++;
_.Node.setData(e.currentTarget, 'data-counter', count);
_.Node.write(_.ids['exampleCounter'], count, 'rewrite' );
},
'data-counter' : 0
} ],
[ 'p', [
[ '~The button above has been clicked '],
[ 'span#exampleCounter~0' ],
[ '~ times' ]
] ]
]);
Which is a hair heftier,. but it has scripting off graceful degradation, works directly on the DOM, and stores the data same. Since there's some sort of halfwitted nonsensical BULLSHIT about how storing information on the DOM is 'bad' or 'slower'. Hence that whole halfwitted 'virtual DOM' idiocy.
I have been considering adding "data-_variables" as a parameter that would be sent to all event handlers as 'this' (which I can do given how the wrapper and polyfills work). That would simplify it down to:
_.Node.write('example-1', [
[ 'button~Add 1', {
type : 'button', // so we don't have to preventDefault
onclick : function(e) {
_.Node.write(_.ids['exampleCounter'], ++this.counter, 'rewrite');
},
'data-_variables' : { counter:0; }
} ],
[ 'p', [
[ '~The button above has been clicked '],
[ 'span#exampleCounter~0' ],
[ '~ times' ]
] ]
]);
In any case, it would generate the scripting only stuff FROM THE SCRIPTING using the DOM, not some garbage markup methodologies with the parsing overhead that's just not worth it. Only the node that has a value change is changed, and we explicity see it being set so we can trust EXACTLY what's happening.
Though attaching an updateContent type handler to the SPAN might be a better choice depending on how many values are changing.
Yeah, I'm adding that data-_variables to the elementals to-do list. Tim, you listening? Oh wait, he doesn't have an account here because it doesn't work scripting off/blocked.
Thank you so much for this breakdown, Jason. The detail you went into is greatly appreciated. You have a way of dissecting code in ways that many developers are not capable of, and it's an awesome addition to this community.
Many will debate that Vue.js is a great way to "organize collaborative efforts", but after 20+ year of experience, to me, that's never been the end result with popular libraries and frameworks. This is why so many projects need to start with a "clean slate" - because the previous approach actually removed the effort required to collaborate correctly and create a product that has the ability to evolve correctly.
because the previous approach actually removed the effort required
You just described "false simplicity" -- it LOOKS simpler, but in the long term it either violated good practices or makes the actual job harder. It's a common problem in many codebases where they are so desperate to "dumb things down" they end up making it more difficult to actually do anything meaningful with.
We see this in interface design all the time, see these excellent articles on the topic which illustrates how so many "artists under the DELUSION they are designers" constantly cock-up the simplest of UX.
baymard.com/blog/false-simplicity
inspiredology.com/what-is-false-simplicity-and-ho…
There's a reason in many ways I find even the C language to reek of false simplicity in places! It hides flags, overflow from divide, and even how loops REALLY work from you making simple tasks often many times more complex and MORE code than it would be in the native assembly!
Though that's often one of my 'issues' when looking at solving problems in programming. I learned assembly first (RCA 1802, 8080, Z80) and often find a lot of cases where it would be SIMPLER without the high level language "in the way". Portability across processor targets being in many cases the only REAL reason to use high level languages. some HLL's like C often REEK of "false simplicity"...
Which is why over the top abstractions like vue, react, pretty much anything with the word "framework" attached to it end up feeling like more work, pointless abstraction to make it harder in the long term to work with, or just chock-full of outright bad practices.
Bad practices like putting presentation or behavior into the markup.
Actually, was thinking on it and I really used the wrong example -- or at least I used their most card-stacked example... and that too plays to "false simplicity".
A lot of these systems can make simple examples simpler, but harder examples harder, which is why they lead with their strength. If we move on to example #2 from that page, the markup again has a element that has no business in the markup or even stated AS markup.
<div id="example-2">
<!-- `greet` is the name of a method defined below -->
<button v-on:click="greet">Greet</button>
</div>
The new vue as it were is:
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// define methods under the `methods` object
methods: {
greet: function (event) {
// `this` inside methods points to the Vue instance
alert('Hello ' + this.name + '!')
// `event` is the native DOM event
if (event) {
alert(event.target.tagName)
}
}
}
})
// you can invoke methods in JavaScript too
example2.greet() // => 'Hello Vue.js!'
Now, if I were doing that in the upcoming elementals.js 4.0, again the only thing in the markup would be the DIV I was hooking.
<div id="example-2"></div>
Whilst for JS:
var example2 = make('button~Greet', {
type : button,
last : 'example-2',
'data-_variables' : {
name : 'elementals.js'
},
methods : {
greet : function(event) {
// `this` inside methods points to the Vue instance
alert('Hello ' + this.name + '!')
// `event` is the native DOM event
if (event) {
alert(event.target.tagName)
}
}
},
onclick : 'greet'
});
_.Node.method(example2, 'greet')(); // => 'Hello Vue.js!'
Damned near code parity... the more complex the example, the more the pendulum swings in my favor.
NOTE in elementals 4.0 the "data-_variables" and "methods" are currently placeholders and not indicative of the final implementation.
This type of element and event construction is something I've been trying to steer elementals.js towards doing. It's not the concept of doing these things I have an issue with, it's the implementation that bugs me.
Markup for things that have no business even being markup? Methodologies that if 1:1 implemented in markup don't even EXIST if the CSP is enabled or prevent you from going "use strict"? NOT ACTUALLY using the DOM and constantly diving for the mentally enfeebled 'innerHTML'? I'll pass.
-- edit -- actually, my bad, the "this" would not be normalized if directly called. Hmm... interesting that part of their implementation. Whilst handy I'm not sure the overhead would be worth it.
Actually Steven Ventimiglia I really have to thank you for the poke on this... it has prodded me into reviewing what my team on elementals.js had proposed, actually try using the functionality, and utterly and completely reject it for doing things too much like the things I don't like about vue, react, angular, etc. I have ripped that functionality out by the nerts and am investigating if there's a 'better' way of handling this type of data interaction.
My team was putting too much data on the actual DOM object -- that's a really BAD idea even with data- attributes.
Though I may be abusing my powers as "benevolent dictator" on the project, throwing out days if not months of other people's work. Wouldn't be the first time.
No problem at all, Jason. I love reading your replies, like the ones above, because it's always a strategic deep-dive dissection that's focused on proactive improvement - whether some folks like it or not.
It's been a long time that someone's writing style reminds me of ye olde 2600 (2600.com). If you published a book, I would buy it.
I'm also slowly digesting Elementals.js, and it's well documented - so thank you for that. I think if more folks knew it was out there, it would be extremely popular.