For a simple site, it's probably not that big of a deal to hook in jQuery and write some basic scripts.
In my limited experience, if you are writing a Single Page Application, it gets really hard to rationalize changes when everything is hooked in through the DOM. It also gets pretty expensive with mobile browsers as DOM elements carry a huge list of properties and attributes; this why I think libraries like React were made as to have data change and manage state as opposed to the DOM.
At the end of the day, the end user and businesses don't care about what technologies that you use, they just want a site that works and can be delivered on time. I just think that with jQuery, there is a lot of cost in terms of making complex changes in the view that other libraries such as React/Angular/Mithril have been designed to get around. These libraries, however, do have a cost in terms of complexity that I think jQuery never really had.
I think it really depends on how you structure your HTML as well; having tortured myself into learning Angular has really helped with understanding how to think about data structures as opposed to strict DOM elements and this has carried over to how I write javascript nowadays.
One thing that I will mention is that I have worked really hard to not use jQuery over the last year, so my preferences may not be shared by you. I guess it depends on what is quicker and easier to maintain for you.
If download size is at all an issue, jQuery is the first thing to go. I have a tiny collection of helper functions that make 'plain js' almost as simple as jQuery in most cases. Almost.
For example, at the very least I'll have a '$' helper function that makes document.querySelector(All) simpler/quicker to use, and I use a helper function for events to make it a bit more like $(<selector>).on().
But considering the fact that I have quite a few projects where the client will upload some huge image for the home slideshow or where there's no time or incentive to do any lazy loading of images, jQuery is often still the pragmatic solution. Especially when other devs need to deal with the project at a later stage.
Besides, 400k of (blocking) JavaScript can be the difference between the site loading quickly on mobile and the user giving up.
That was one of the pains the Fetch API cured for me. The syntax and overall concept is just so much nicer.
I was using Nanoajax library before that. It's great (and light, 620 bytes gzipped), but I moved almost completely to Fetch as soon as i started getting used to Promises more.
I guess libs like these and maybe even the Fetch in current browsers were somehow inspired by jQuery's $.ajax…
Can you give an example of a typical line of jQuery that you prefer over vanilla?
https://connect.microsoft.com/IE/feedback/details/878564/ele...
With jQuery I'd often do
$(<root-element>).on('click', <target element>, callback);
crucially, because events bubble up, even a click on a child element of <target element> will register as a click on the target element.in plain js it doesn't seem to work that way. I'd do <root-elem>.addEventListener(), but I'd run into the problem that the event.target would point at the exact element that was clicked on instead of the parent element that I wanted to register clicks on.
Given the structure ".item .inner .title", I can't just check if event.target.classList contains 'item', because it might only contain 'title' or 'inner'.
event.path to the rescue! I can simply check if any of the parent nodes do contain the 'item' class. Except event.path doesn't work in safari mobile, so it needs a polyfill. Plus on every event handler I have to go up event.path to check.
Obviously it's not that hard to write a helper function that basically emulates .on(), but I can't help but feel that I'm maybe missing some simpler, plain solution. Any suggestions?
function delegate(el, evt, sel, handler) {
el.addEventListener(evt, function (event) {
let t = event.target
while (t && t !== this) {
if (t.matches(sel)) {
handler.call(t, event)
}
t = t.parentNode
}
})
}
delegate(document, 'click', '[data-behavior="open"]', function (event) {
event.preventDefault()
})You'll need a matches polyfill if supporting browsers that don't support el.matches
Unless I misunderstand, I think you might be looking for "event.currentTarget". event.target is the element that was clicked on, event.currentTarget is the element that has the event listener attached.
<root-element>
.querySelector(<target element>)
.addEventListener('click', function(event){
// event.currentTarget refers to
// <target element> no matter which of its
// children were clicked
});
Admittedly, this doesn't work as well for multiple target elements. I use a forEach polyfill which could loop through them, but that could create a lot of event listeners when possibly you'd only need one higher up. Depends how many there are, I suppose.This is why one of the early lessons you learn as a jQuery user is to use $().on() instead of something like $().click();
Plus, while I don't suppose it's a real performance issue much of the time, adding an event listener to each of, say, a few hundred items in a list is probably rather inefficient compared to adding it to the root element of the list.
In jQuery I can do something like this:
$(<Carousel>).on('click', <Item>, function(e) {
// using this 'this' gives you the <Item> element. Always. Even
// if you click on a child element of <Item>. And it works if
// you add or remove items. Also it doesn't add a listener
// to *every* single item, which matters if you've got a whole
// bunch of them!
});
The vanilla equivalent is often presented to be as simple as: <Carousel>.addEventListener('click', function(e) {
// e.target is the actual element you clicked. So now we need to
// figure out if this element is inside an <Item>, and perhaps
// also *which* <Item>. There's various approaches, and it's
// not rocket science, but it's all extra work for something that
// seems like a common scenario.
});