What's the difference between using observedAttributes() vs MutationObserver - javascript

With a custom component, you can use the static get observedAttributes() in your web component to specify what attribute changes trigger the attributeChangedCallback() lifecycle method.
However, it seems you can also achieve a similar callback by using the MutationObserver API, documented here, with {attributes: true} to watch all attribute changes, or to refine it more, using a {attributeFilter: Array<string>}.
What's the difference in using the two different methods? Seems like the MutationObserver offer much more flexibility, while the first method is equivalent to having defined an attribute filter.

Yes, minor functional differences.
But MutationObserver takes a lot more boilerplate, and you can't ask the MO which attributes are observed.
It is kinda like saying Why do we need Map, when everything can be done by extending Array
I don't have data, but would say observedAttributes is highly optimized. MO is taking a sledgehammer to drive in a nail.
But as you commented; observedAttributes doesn't give you dynamic attributes.

Related

In React, is it okay to use getElementById, querySelector, etc versus useRef if you don't perform any DOM manipulation?

Specifically used just to view the heights/widths (getBoundingClientRect) of elements. I recently encountered a need to find all the separate heights of a dynamic amount of child elements to perform a calculation. I added a ref within the child component, and passed a function down from the parent in an attempt to update the parent's list of child dimensions (which was in state). I found this to be overtly complex and confusing and unreliable. So, in the parent, I just did a simple for loop with getElementById after giving each child an id of child-${index}.
I know you are NOT supposed to do any direct DOM manipulation in React; however, if your goal is read some data only, then is it an issue or bad practice?
It might not be a problem right now, but I would consider using getElementById instead of a ref bad practice in general (or at least call it "a workaround").
1
getElementById works "outside" of React, so you are not using React here.
That might work for now, but also might interfere with what might do React at some time.
E.g. you might access or hold a reference to a DOM node, and React might decide to remove that node while you were reading it. I don't see why this might happen in your
example, but when using two separate systems it is hard to keep track of the possible consequences.
2
With the id child-${index} you have introduced a logical dependency (coupling) between the parent and the child.
The id child-${index} acts as a reference here, and has to be kept in sync manually.
This might be easier in a short term, but is actually more complex as a general approach (e.g. less maintainable, reusable, ...).
You could say, Reacts whole purpose is to avoid such complexities.
Your components should be as independent of each other as possible, and should only communicate through the props.
suggestion
I suggest to avoid both getElementById and passing a ref, and have the children know their size (e.g. using a custom hook),
and pass only the sizes up to the parent (not the ref).
If that is not possible, I would prefer to use refs.
Also note that "confusion" is not the same as "complexity": Confusion can be decreased by acquiring more information, but complexity is an
inherent property of a system.

Angular change detection on #Input object

I kind of understand how change detection works in Angular 2 but I'm really struggling to transfer/change my AngularJS methods over to NG2 regarding change detection.
Imagine I have a component that takes a single #Input() anObject and has a single function, logAllProperties() which, for arguments sake, logs all the properties to the console.
All I want to do is to call logAllProperties() every time anObject changes in anyway whatsoever.
I understand that treating the object as immutable (either with an external library like Immutable.js or by enforcing that the entire object changes even for a minor property change) will trigger ngOnChange but is there anyway to call a function whenever a change takes place aside from these or using DoCheck which I understand is potentially extremely inefficient.
As well as "is there a way", what is the correct way to do something like this? I'm new to Angular2 so I'm more than happy to learn the right way if Immutable and Observables are the way to go.
Thanks in advance
The straightforward way of executing an action everytime anObject change is by using a setter or ngOnChange (see Fals' answer).
Using immutable objects witch a change detection strategy of OnPush is a way to improve change detection performance. This is not the most obvious use of change detection in Angular.
For a complete explanation I suggest you read this really good article and if you have some time (45 minutes) you can check this video by the author of the article here
From there, you should have a good understanding of what's going on.
#input decorator is denoted your component is expecting to get some data from its parent which will be caught at that property
same way #output is the decorator in angular2 wherein parent component you can catch something from child.
Internally it uses observable and I don't think it's immutable.
ngrx provides a redux type immutable mechanism where every state is remembered and you can go back to them as well.
Observable and ngrx are running in parallel now.
I found out in our projects that using set works well in some cases, but others cases that need sync between components could be troubling, then we are using ngOnChange for those cases. Here's an example.
#Input() set myProperty(myProperty: MyPropertyType) {
if (myProperty) {
this.logService.log(myProperty);
}
this._myProperty = myProperty;
}
private _myProperty: MyPropertyType= new MyPropertyType();
The thing about Angular2 new lifecycle still confuse, and the documentation samples doesn't fit most of the real world cases.

Function that acts like a decorator, but uses mutation instead of wrapping?

A decorator adds additional functionality to an object by "wrapping" around the original value.
Is there a name for an object or function that ingests a pre-constructed object and adds additional functionality to it via mutation?.
Example:
function mutatesObjects(target) {
target.additionalFunctionality = "I've been mutated!";
}
This is similar to a contrcutor or factory except that it is adding functionality to an object that was already created.
Is there a name for this pattern?
Depending on the purpose for this change, Monkey Patching might apply.
"A monkey patch is a way for a program to extend or modify supporting system software locally (affecting only the running instance of the program)."
I would suggest Plugin name as a reference to jquery plugins.
But I also think this is actually an anti-pattern in most cases. This not only breaks the encapsulation (one of the main concepts in OOP), it goes even beyond it and changes object functionality.
Imagine a simple case where you do something like:
doSomething(object)
In the best case you can hope the object state was not changed. In the worse case you can suspect that it was mutated and it's state changed.
It's really unexpected if you get something completely different with new methods or properties.
But of course, there can be good usages (like jquery plugins).

"Fake" argument into class constructor

I'm using a js API and I have to instantiate a class that requires a <div> element in its constructor. However this is only used by the class to do some rendering in the element and I don't need it, I just want to use a method of this class.
I came up with this which seems better than linking to a random <div> element of the page :
service = new API.service(document.createElement("div"));
service.useMethod();
Do you have any better ideas about how to do this ? I don't really know what is good practice in this case.
FYI the class I'm actually using is google.maps.places.PlacesService from Google maps javascript API in order to use the method getDetails on some info I retrieved earlier.
Your approach is OK (I don't know a better approach).
But the issue:
This required node isn't there for fun, the API will print there Copyright-details for the requests(if there are any), and these details must be visible(at least when you display something that is based on the data returned by the service).
So your approach is correct from a programmers view, but it would violate the TOS

I want to stop using OOP in javascript and use delegation instead

After dabbling with javascript for a while, I became progressively convinced that OOP is not the right way to go, or at least, not extensively. Having two or three levels of inheritance is ok, but working full OOP like one would do in Java seems just not fitting.
The language supports compositing and delegation natively. I want to use just that. However, I am having trouble replicating certain benefits from OOP.
Namely:
How would I check if an object implements a certain behavior? I have thought of the following methods
Check if the object has a particular method. But this would mean standardizing method names and if the project is big, it can quickly become cumbersome, and lead to the java problem (object.hasMethod('emailRegexValidatorSimpleSuperLongNotConflictingMethodName')...It would just move the problem of OOP, not fix it. Furthermore, I could not find info on the performance of looking up if methods exist
Store each composited object in an array and check if the object contains the compositor. Something like: object.hasComposite(compositorClass)...But that's also not really elegant and is once again OOP, just not in the standard way.
Have each object have an "implements" array property, and leave the responsibility to the object to say if it implements a certain behavior, whether it is through composition or natively. Flexible and simple, but requires to remember a number of conventions. It is my preferred method until now, but I am still looking.
How would I initialize an object without repeating all the set-up for composited objects? For example, if I have an "textInput" class that uses a certain number of validators, which have to be initialized with variables, and a class "emailInput" which uses the exact same validators, it is cumbersome to repeat the code. And if the interface of the validators change, the code has to change in every class that uses them. How would I go about setting that easily? The API I am thinking of should be as simple as doing object.compositors('emailValidator','lengthValidator','...')
Is there any performance loss associated with having most of the functions that run in the app go through an apply()? Since I am going to be using delegation extensively, basic objects will most probably have almost no methods. All methods will be provided by the composited objects.
Any good resource? I have read countless posts about OOP vs delegation, and about the benefits of delegation, etc, but I can't find anything that would discuss "javascript delegation done right", in the scope of a large framework.
edit
Further explanations:
I don't have code yet, I have been working on a framework in pure OOP and I am getting stuck and in need of multiple inheritance. Thus, I decided to drop classes totally. So I am now merely at theoretical level and trying to make sense out of this.
"Compositing" might be the wrong word; I am referring to the composite pattern, very useful for tree-like structures. It's true that it is rare to have tree structures on the front end (well, save for the DOM of course), but I am developing for node.js
What I mean by "switching from OOP" is that I am going to part from defining classes, using the "new" operator, and so on; I intend to use anonymous objects and extend them with delegators. Example:
var a = {};
compositor.addDelegates(a,["validator", "accessManager", "databaseObject"]);
So a "class" would be a function with predefined delegators:
function getInputObject(type, validator){
var input = {};
compositor.addDelegates(input,[compositor,renderable("input"+type),"ajaxed"]);
if(validator){input.addDelegate(validator);}
return input;
}
Does that make sense?
1) How would I check if an object implements a certain behavior?
Most people don't bother with testing for method existance like this.
If you want to test for methods in order to branch and do different things if its found or not then you are probably doing something evil (this kind of instanceof is usually a code smell in OO code)
If you are just checking if an object implements an interface for error checking then it is not much better then not testing and letting an exception be thrown if the method is not found. I don't know anyone that routinely does this checking but I am sure someone out there is doing it...
2) How would I initialize an object without repeating all the set-up for composited objects?
If you wrap the inner object construction code in a function or class then I think you can avoid most of the repetition and coupling.
3) Is there any performance loss associated with having most of the functions that run in the app go through an apply()?
In my experience, I prefer to avoid dealing with this unless strictly necessary. this is fiddly, breaks inside callbacks (that I use extensively for iteration and async stuff) and it is very easy to forget to set it correctly. I try to use more traditional approaches to composition. For example:
Having each owned object be completely independent, without needing to look at its siblings or owner. This allows me to just call its methods directly and letting it be its own this.
Giving the owned objects a reference to their owner in the form of a property or as a parameter passed to their methods. This allows the composition units to access the owner without depending on having the this correctly set.
Using mixins, flattening the separate composition units in a single level. This has big name clash issues but allows everyone to see each other and share the same "this". Mixins also decouples the code from changes in the composition structure, since different composition divisions will still flatten to the same mixed object.
4) Any good resources?
I don't know, so tell me if you find one :)

Categories

Resources