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

In the source code to perform el.classList = v.classes the author uses:

  for (const name of v.classes)
    if (!el.classList.contains(name)) el.classList.add(name)
  for (const name of el.classList) 
    if (!v.classes.includes(name)) el.classList.remove(name)
Why the standard decided to make classList read-only?

Could ele.className=(v.classes).join(" ") be a valid and performant solution?, perhaps is to avoid the string to token traslation for performance reasons?, then why don't they include a classList.set method?



> Why is classList read-only, I can think of any valid reason.

Because it's a live DOMTokenList, not a computed property. That is if you keep a reference to a classList and mutate the className parameter, classList will reflect the changes.

classList could also be a computed property which, when assigned to, clears the underlying token list and adds all elements but I'm guessing the developers of the API saw this as unnecessary complexity given you can do the same thing by setting className.

The point of classList is the ability to more easily check for and toggle individual classes, if you don't need that capability you just don't use classList.

> Perhaps ele.className=(v.classes).join(" ") is a valid solution?

Yes.


Great answer, thanks! Embarrasingly, I didn't even know about className :-)


I’m not sure this is the right place, but... I see a potential subtle bug there too: it doesn’t seem at first glance that the classes get added in the same order as they’re specified in the virtual element? If I made div.bar and then changed it to div.foo.bar, properties of .foo could override properties of .bar because it looks like it would end up with classList [“bar”, “foo”] instead of [“foo”, “bar”]? Maybe?

Edit: please don’t take this as criticism. I love the project and think it’s awesome! That’s why I took the time to read through the source and grok it!


> If I made div.bar and then changed it to div.foo.bar, properties of .foo could override properties of .bar because it looks like it would end up with classList [“bar”, “foo”] instead of [“foo”, “bar”]? Maybe?

What properties are you talking about here? Despite the name, classes are really an unordered set, the order of classes on the element should not matter: when CSS gets applied, properties are prioritised based on the most specific rule, then the latest rule. That is the prioritisation of CSS properties should depend entirely on the CSS and not in any way on the order of the class attribute / className property.


So let’s say .foo sets “padding: 8px;” and .bar sets “padding: 4px;”. It’s been a while, but I’m pretty sure that <div class=“foo bar”> ends up with 4px padding, and <div class=“bar foo”> ends up with 8px padding. I could be wrong though and will test it out when I’m back in front of a real computer.

Edit: Woah... It looks like I am incorrect. Nifty! I'm amazed I have never been burned by that before!

Edit 2: I suspect the reason I've never been burned by that before is because overrides like that have generally been applied over top of some kind of generic CSS file and the generic one was loaded first; since whichever rule is declared later is considered to have precedence, the override file wins over the generic file. My mind is kind of blown right now that over 20 years of web development I have never encountered this problem!


Agreed, let me know if you find a better way! I feel if the browser APIs were slightly more declaratively inclined, this article could be "10 line React".


to merge the properties of two objects you could use

  let merged = {...obj1, ...obj2};  See (1) which has 2808 votes.
(1) https://stackoverflow.com/questions/171251/how-can-i-merge-p...




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

Search: