Is there any difference between class and staticClass in Vue.js? - javascript

Is there any difference between class and staticClass in Vue.js render functions? Using Template Compilation, I can see that it outputs different results depending on what is passed to HTML class attribute.
For example, when I pass a single string (for example 'foo') it outputs staticClass in data object:
<div class="foo"></div>
compiles to:
function anonymous() {
with(this){return _c('div',{staticClass:"foo"})}
}
but when I add a colon : (shortcut for v-bind) in front of class attribute it outputs class:
<div :class="'foo'"></div>
compiles to:
function anonymous() {
with(this){return _c('div',{class:'foo'})}
}
I am curious about the difference between class and staticClass, and which one should i use when writing own render functions.
I have googled a little, but have not found any clue.
Thanks in advance.

The key difference is that staticClass can only be a string. class supports all the other formats, such as arrays and objects.
The class attribute is special in many ways. For most attributes you can't specify both a bound and non-bound version on the same element. It also needs to be merged differently when combining the attributes from nested components. All of this merging happens here:
https://github.com/vuejs/vue/blob/531371b818b0e31a989a06df43789728f23dc4e8/src/platforms/web/util/class.js
When templates are compiled down to render functions they employ a number of undocumented features to take advantage of extra knowledge that comes from the template. This would be one such example, where it knows that an unbound class can only be a string so it tries to retain that knowledge by storing it separately as staticClass.
In theory there are a couple of advantages to that:
Manipulating the value doesn't need to worry about the array and object forms of class.
The staticClass can never change, so there's no need to check it when updating the DOM.
However, in practice that second optimisation isn't implemented (there's something that looks similar in the template compiler but it's not quite the same thing). Further, it's not entirely clear from looking at the code that there's much gained from a manipulation standpoint either. If anything it looks like it just makes things more complicated trying to maintain the two separate concepts right until the last possible moment. Perhaps the benchmarks suggest otherwise...
As for which one you should be using in your render functions, only class is documented so I'd stick with that:
https://v2.vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth

Related

What is it about Vue that enables developers to use the class property on DOM elements?

JavaScript frameworks like React and Svelte don't allow developers to use the class property on a DOM element because the class keyword is reserved in JavaScript. Meanwhile, other frameworks like Vue somehow get around this.
What is it about how Vue is implemented that makes it possible for Vue developers to use the class keyword on elements? I'd imagine it's something with how Vue converts .vue files to HTML, CSS, and JavaScript but I'm curious about specifics.
Edit: Svelte does not use virtual DOM and you can use the class prop with Svelte.
tldr;
JSX (React's language) is a superset of JavaScript (where class is a reserved keyword), while Vue and Svelte both have templating languages which are supersets of HTML, thus allowing the use of class as you would in HTML.
Speaking for Svelte here.
First, let's fix the false premise:
JavaScript frameworks like React and Svelte don't allow developers to use the class property on a virtual DOM element because the class keyword is reserved in JavaScript.
Svelte does allow the class keyword, both on elements and components. You just have to work within the applicable constraints. We're coming back to this.
Let's start with React. Well, JSX actually. JSX is a strict superset of JS. Let's refer to this nice explanation. JSX is a superset of JS both syntactically (any JS program is valid JSX) and semantically (any JS program behaves the same when interpreted as JSX).
In order to be so, JSX has to respect every constraints of JS, of which "class is a reserved keyword". That's why React doesn't allow the class keyword.
Note that this is not a technical constraints. React could reinterpret the class keyword and make it work in JSX. But that would make JSX not strictly a superset of JS. Why? Because then, in some cases, the same JS code would not behave the same when interpreted as pure JS or as JSX (namely, having a variable named class must crash to be JS).
This is a philosophical constraint. At one point, JSX developers must have weighted the inconvenience of not being able to use the class keyword against suddenly not being a strict superset of JS. On one hand, you gain one little nicety, on the other you abruptly downgrade from being a mathematically pure superset to being just "yet another random template language".
It's easy to feel the strong mathematical incline that emanates from React, with its emphasis on pure functions, the "view as a function of the state", unidirectional data flows, etc. This is actually a very important taking from React. They imported a lot of benefits from mathematics into everyday application development. And so, quite understandably (to me), this group of developers favored (favors) purity over minor conveniences.
Being a superset of JS does bring many advantages. Even if you know nothing of JSX, you can write some immediately by using your existing JS knowledge. As long as you don't start using JSX extra features, you can predict all the behaviours of your code, because everything will behave the same.
Now, to the Svelte specifics... Svelte does not use JSX (and neither Vue in most cases, as far as I know). They use their own templating language. Not sure for Vue, but for Svelte it is a superset, not of JS, but of HTML. Rich Harris, creator of Svelte, once called that HTMLX in a talk (not sure how official this terminology currently is). Personally, this is one of the main reason why I'm so comfortable with Svelte. I find it cumbersome to write HTML is JS, while writing natural looking HTML(X) to, in the end, produce HTML feels just... Natural! But I digress...
So, the thing is Svelte too has to play within the limits of its own chosen laws. There are 2 of them that are relevant to the matter at hand. Both makes sense, and both can be worked around.
But first, to clear any misconception, Svelte does allow the use of the class keyword for native elements (as opposed to Svelte components):
<div class="whatever">No problem with that</div>
It wouldn't be a proper superset of HTML if it didn't.
In this context, class is actually a "directive", meaning it has added power, as compared to a pure HTML class. For example:
<script>
let blue = true
</script>
<!-- will render as: <div class="blue"></div> -->
<div class:blue />
<!-- will render as: <div class="red"></div> -->
<div class:red={blue} />
<!-- you can have several of them too... -->
<div class="foo" class:red class:blue />
So Svelte allows the use of the class keyword, there's no doubt about that. For native elements that is.
Now, for components the story is a bit different. Here come the 2 laws I have mentioned earlier.
The first one is that Svelte components do not enforce having a single root elements. Or any elements at all, for that matter.
<script>
console.log('I am a valid Svelte component with no elements')
</script>
<!-- no code omitted -->
<p>I am a valid Svelte component</p>
<p>Too.</p>
The consequence of this is that Svelte can't know for sure to what element(s) it should automatically apply a class set on the encompassing component. And so, in this situation, it doesn't do anything. It hands the controls back to you.
That doesn't mean that you can't implement it if you want. You just have to abide by our second law: the code inside the <script> tag of a Svelte component has to be valid JS. Here again, this is not a technical limitation, but a philosophical one. It has been reiterated again and again by Svelte's creator and core developers on many occasions. On the syntax level, we're not even speaking of a superset anymore, but of equality. Any Svelte JS is valid JS (note the members of the relation have been swapped, as compared to "any JS is valid JSX").
On the other hand, Svelte JS is not a semantic superset of JS either. Some JS programs wont behave the same when interpreted as pure JS as when interpreted with Svelte, because Svelte overloads some constructs (like $: or export let prop) with a different meaning.
This constraint impacts us here because class is not a valid variable name is JS, and Svelte components' properties are defined as JS variables. However you can bypass it:
<script>
// can't do, not valid JS:
// export let class
// but:
let cls = ''
export { cls as class } // valid JS
</script>
<div class={class} />
This component would be then used like this (live example):
<script>
import MyComponent from './MyComponent.svelte'
</script>
<MyComponent class="blue" />
So you can also use the class keyword for components in Svelte.
Phew. Hope you enjoy a developed answer!
To sum it up, if some of the major frameworks allow the use of the class keyword and some don't, it is for philosophical reasons. It makes full sense for JSX, as a superset of JS, to respect this constraint. It would make no sense for Svelte's HTMLX to implement this constraint for no reasons (and to stop being a superset of HTML in the process). Further, React has a stronger focus on mathematics purity, and Svelte has a stronger focus on code expressiveness and convenience. As always with good software, it's all in the trade-off!
You can't use class with React because React uses React DOM, which uses camelCase property names, not classical HTML attributes.
This is why in JSX (React render language), you have to use className, not class.
Vue is using classical HTML template, so class is allowed.
With Svelte, you should be able to use class keyword in your template.
React library uses JSX to render any DOM elements. JSX is a kind of extension for JS to render HTML from javascript. JSX is transpiled before rendering into the browser. Hence className has to be used instead of class. But, there are several advancements taking from one reactjs version to another.
Looks like a similar question is already asked. Find more explanation on
class vs className in React 16
According to my research answers: thanks to their built function.
I found on the side of Vue.js https://github.com/vuejs/vue/blob/dev/dist/vue.js that Vue is binding the class from a JavaScript object to Node. The (vue) node element is used with JavaScript to assign to a DOM elm all classes.
The JavaScript code el.setAttribute('class', cls) is confirming it.
function transformNode (el, options)
and from this you'll find function at line 5503:
function genClassForVnode (vnode)
which use the
function renderClass (staticClass, dynamicClass)
This function is then used by
function updateClass (oldVnode, vnode) {
var el = vnode.elm;
var data = vnode.data;
var oldData = oldVnode.data;
[...]
var cls = genClassForVnode(vnode);
// handle transition classes
var transitionClass = el._transitionClasses;
if (isDef(transitionClass)) {
cls = concat(cls, stringifyClass(transitionClass));
}
// set the class
if (cls !== el._prevClass) {
el.setAttribute('class', cls);
el._prevClass = cls;
}
}
note: the following functions are interesting:
function addClass(el, cls) line 7873 function bindObjectListeners(data, value) line 2866
Does it helps ?

Does I10n.js's toLocaleString(opts) merge the options?

I'm looking to use l10n.js for a project. Seems like defining the localization strings is fairly easy. l10n.js defines the toLocaleString method. Is the input of that call merged or overwritten? I'd like to have two separate inputs into the methods be served into one and I'm trying to figure out the best way to do so.
Yes. A comment in the source suggests that the store of translations is extended when String.toLocaleSource is called. Looking further reveals that existing strings are overwritten and new ones are added next to the existing ones.

Should you use named functions when developing a JavaScript library?

For example:
module.exports = {
myLibraryFunction: function myLibraryFunction() {
...
}
}
The disadvantage is obvious. It's not very DRY, which means it can easily become out-of-sync if you're not careful. It also makes your code a little more verbose.
So what are the advantages? Is the tradeoff worth it?
I use this approach when writing JS libraries. The largest advantage is that tools like the Chrome debugger will have a definite name for your function as opposed to either "anonymous" or some name composed of the function path based on the variable names containing the function. If, however, you don't care about having method names when debugging, then it really comes down to a matter of taste. If you were to minify the resulting JS code, naming elements like that would get stripped out anyway.
As far as to how DRY this approach is, consider that the repeated names occur right next to each other. A quick copy & paste is all it takes to keep them in sync. It would be nice if a JS included a feature that causes a function to be named according to the variable it has been assigned to at the point of creation (or at least the ability to dynamically re-assign the function's name). Sadly, however, this is the only way JS allows for us to name these otherwise anonymous functions.

How to properly structure a KnockoutJS application

I am wondering how to structure a KnockoutJS application the right way.
The official documentation almost always uses just one single ViewModel!
After only a few implemented functions my code became very confusing and coming from an object-oriented background I am very allergic to architecture like that. So there must be a better solution.
Being not very experienced with JavaScript I was searching Stackoverflow and found those three options. So I tried the first two options and I am not happy with them:
Having multiple ViewModels like here.
I find it very difficult to decide what DOM-element gets what ViewModel. Also there were several functions called from outside the DOM-element. Maybe I used too little ViewModels with this kind of architecture but communicating between ViewModels seemed to be different and somehow shouldn't be necessary I hope. So how to do that properly?
Having sub views and utilizing the with binding (the second option from those three).
This was my preferred type of architecture because you can have document-wide bindings out of one view model but you can also structure your code into sub-chunks and bind them to wherever you want by using the with binding. This option though requires object literals instead of functions, which are inferior as described in this answer.
I haven't tried method three because it seems a little overkill and also uses object literals.
So is there a method to structure my code and also have full control without using object literals?
I hope this was not too confusing :-P
For any of the options that you mentioned, you do not need to use object literals. The samples just used them to simplify the code. You can choose to create the individual view models in any way that you see fit.
For example in #3, you can use a constructor function like: http://jsfiddle.net/rniemeyer/PctJz/149/. Of course, the actual data would get passed into the function rather than being static. Same with #2, you just would have it wrapped in the "View" object.

How can I write reusable Javascript?

I've started to wrap my functions inside of Objects, e.g.:
var Search = {
carSearch: function(color) {
},
peopleSearch: function(name) {
},
...
}
This helps a lot with readability, but I continue to have issues with reusabilty. To be more specific, the difficulty is in two areas:
Receiving parameters. A lot of times I will have a search screen with multiple input fields and a button that calls the javascript search function. I have to either put a bunch of code in the onclick of the button to retrieve and then martial the values from the input fields into the function call, or I have to hardcode the HTML input field names/IDs so that I can subsequently retrieve them with Javascript. The solution I've settled on for this is to pass the field names/IDs into the function, which it then uses to retrieve the values from the input fields. This is simple but really seems improper.
Returning values. The effect of most Javascript calls tends to be one in which some visual on the screen changes directly, or as a result of another action performed in the call. Reusability is toast when I put these screen-altering effects at the end of a function. For example, after a search is completed I need to display the results on the screen.
How do others handle these issues? Putting my thinking cap on leads me to believe that I need to have an page-specific layer of Javascript between each use in my application and the generic methods I create which are to be used application-wide. Using the previous example, I would have a search button whose onclick calls a myPageSpecificSearchFunction, in which the search field IDs/names are hardcoded, which marshals the parameters and calls the generic search function. The generic function would return data/objects/variables only, and would not directly read from or make any changes to the DOM. The page-specific search function would then receive this data back and alter the DOM appropriately.
Am I on the right path or is there a better pattern to handle the reuse of Javascript objects/methods?
Basic Pattern
In terms of your basic pattern, can I suggest modifying your structure to use the module pattern and named functions:
var Search = (function(){
var pubs = {};
pubs.carSearch = carSearch;
function carSearch(color) {
}
pubs.peopleSearch = peopleSearch;
function peopleSearch(name) {
}
return pubs;
})();
Yes, that looks more complicated, but that's partially because there's no helper function involved. Note that now, every function has a name (your previous functions were anonymous; the properties they were bound to had names, but the functions didn't, which has implications in terms of the display of the call stack in debuggers and such). Using the module pattern also gives you the ability to have completely private functions that only the functions within your Search object can access. (Just declare the functions within the big anonymous function and don't add them to pubs.) More on my rationale for that (with advantages and disadvantages, and why you can't combine the function declaration and property assignment) here.
Retrieving Parameters
One of the functions I really, really like from Prototype is the Form#serialize function, which walks through the form elements and builds a plain object with a property for each field based on the field's name. (Prototype's current – 1.6.1 – implementation has an issue where it doesn't preserve the order of the fields, but it's surprising how rarely that's a problem.) It sounds like you would be well-served by such a thing and they're not hard to build; then your business logic is dealing with objects with properties named according to what they're related to, and has no knowledge of the actual form itself.
Returning Values / Mixing UI and Logic
I tend to think of applications as objects and the connections and interactions between them. So I tend to create:
Objects representing the business model and such, irrespective of interface (although, of course, the business model is almost certainly partially driven by the interface). Those objects are defined in one place, but used both client- and server-side (yes, I use JavaScript server-side), and designed with serialization (via JSON, in my case) in mind so I can send them back and forth easily.
Objects server-side that know how to use those to update the underlying store (since I tend to work on projects with an underlying store), and
Objects client-side that know how to use that information to render to the UI.
(I know, hardly original!) I try to keep the store and rendering objects generic so they mostly work by looking at the public properties of the business objects (which is pretty much all of the properties; I don't use the patterns like Crockford's that let you really hide data, I find them too expensive). Pragmatism means sometimes the store or rendering objects just have to know what they're dealing with, specifically, but I do try to keep things generic where I can.
I started out using the module pattern, but then started doing everything in jQuery plugins. The plugins allow to pass page specific options.
Using jQuery would also let you rethink the way you identify your search terms and find their values. You might consider adding a class to every input, and use that class to avoid specifically naming each input.
Javascript is ridiculously flexible which means that your design is especially important as you can do things in many different ways. This is what probably makes Javascript feel less like lending itself to re-usability.
There are a few different notations for declaring your objects (functions/classes) and then namespacing them. It's important to understand these differences. As mentioned in a comment on here 'namespacing is a breeze' - and is a good place to start.
I wouldn't be able to go far enough in this reply and would only be paraphrasing, so I recommend buying these books:
Pro JavaScript Design Patterns
Pro Javascript techniques

Categories