New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow explicit control of setting attributes vs properties #114
Comments
The problem is that you would need to have an API that is something like:
We could definitely add a function that applies just attributes or just properties. It might look something like:
|
Well... I think taking attribute name/value pairs as alternating varargs is a bit of an odd API. Why not just take an array of key values pairs (I suggest this in #115). |
That would cause memory allocation for each element call on each render pass, which we are purposefully trying to avoid. If that is really an API that you need, you could just create a small wrapper that does an |
Hmm... I'd be very careful about assuming the allocation behavior of VMs these days, especially in cases like this where you're accessing It's possible that a similar allocation has to be made for large argument lists and/or when you access them via Did you measure that the argument list API result in less GC pauses or faster render? |
Before getting too far into discussing the name/value pair API, we recently landed an attribute mutator API that'll allow you to define how to set certain attribute/props. Would this suit your purposes? iDOM.mutators.attributes.attrName = function(el, name, value) {
el.setAttribute(name, value);
};
iDOM.mutators.attributes.propName = function(el, name, value) {
el[name] = value;
}; In fact, we even expose the default iDOM.mutators.attributes.attrName = iDOM.defaults.attributes.applyAttr;
iDOM.mutators.attributes.propName = iDOM.defaults.attributes.applyProp; |
I can't immediately see how to use that API, who makes the decision whether to call |
These are defined beforehand. IE, if you know you always want to set mutators.attribute.id = function(element, name, value) {
// Here, `name` = 'id'
element.id = value;
}; The same goes for
Tangent: If you wanted to get really crazy, you define a "separator" that separates the properties from the attribute in the arguments: elementOpen('div', 'key', statics, 'attr', 'value1', separator, separator, 'prop', 'value2'); Since iDOM will call |
In these templates we only know per source attribute whether you want to assign to an attribute or property. In Polymer attributes are suffixed with a
input/value is an attribute, but x-foo/value is a property. Interpreting this requires code like this:
Maybe I can do something with
I'll try this, however it seems like a complicated and hard to grok API to me. |
That was one of the reasons for
Is it the mutator interface? Or the name/value pairs? I'd love suggestions to make it easier to understand. |
Another option might be something like:
Though you would want to check for a diff yourself before trying to apply it. |
Ah, I didn't even think of that! |
On second thought, not a good idea since we would hold on to the arrays when we do our caching when checking for diffs. |
If it really is that much of an impact to allocate Arrays, then I think a function-based API like If micro-optimizations are important, it's even possible that in some limited cases that inlining and loop-unrolling could remove some of the cost of the extra function calls (maybe the same types of cases that hopefully kick in when you're iterating over |
Another need on the properties side is to be able to declare static properties. In the templates I deal with, attribute vs property and static vs dynamic are completely orthogonal. |
I'm not sure I like this direction, as it would require changes to consider attributes and properties fundamentally different. With the current configuration step, anything from Polymers But, it does have merits. This would allow formatters with attributes and properties, since we can extend the
My hope was this would be used to properly support setting/unsetting
They are global. We could potentially create iDOM instances, each being able to specify their own configuration.
I'd actually be really supportive of attribute maps (or arrays). It'll allow us to unwind the method inlining.
I've been using http://jridgewell.github.io/js-repaint-perfs/incremental-dom/ locally. We should definitely look into automatic benchmark testing. |
I don't understand the specific objection. The difference between attribute and properties only how they're set and read. You just need a single extra bit to flow with the name/value pair:
Yes, they are different in how they are set, but whether they are "fundamentally" different I guess is for you to decide. As I mentioned I think I can already get the effect I want by wrapping primitives in objects (and making sure I unbox Strings that I want as attributes?). This means there is a code path from
The syntax of the template doesn't really matter at all though. The attribute name in the template will be decoded to a target attribute name or property name. I don't see any reason to pass it down to incremental-dom APIs, unless names are really the only to get per-call attribute/property differentiation. Even then, there's no reason to use the template languages particular naming scheme, you could just as easily prefix attributes with something like Still, going through the configuration function is a few steps to many, and requires this encoding, when it doesn't seem necessary.
My question about the configuration API is what exactly is gained by putting the
Another way I think about this is the orthogonal attributes of attributes:
As an API user I find that hard to grok (even if incremental-dom is a compile target, I still need to write the compiler or interpreter). |
It can be done, but it would require some fairly substantial changes. In order to tell what attributes have disappeared, we need a full view of the attributes/properties. Even if you aren't doing arbitrary logic in the attributes declaration like for-loops and switches, you can still end up with cases where 'disappearing' attributes need to be removed. For example: if (condition) {
elementVoid('div', null, null, 'attrOne', 'value');
} else {
elementVoid('div', null, null, 'attrTwo', 'value');
} As far as Incremental DOM is concerned, it can't tell what happened other than then attributes are now different, so it needs to strip |
I was talking more about having different code paths to support both. That we'd be splitting the API into
Oh, absolutely. The current property setting was intended only for passing Objects around and event listeners. It's definitely ungainly for forcing property setting.
The main downside I see is doubling up the logic for attributes and properties. Things like caching, the list of currently set (so that we can unset missing as @sparhami highlighted). Speed would also be an issue, but it wouldn't be significantly worse than if we adopted attribute maps/arrays (taking away the var_args stuff).
That it's global is definitely a downside, no argument there.
I think I'm starting to see the issue here, thanks for the table. To iDOM, properties are just attributes. We treat Objects and functions a bit differently during setting, since no one wants those coerced to strings. But,
Additionally, if you want to intercept static or dynamic attributes/properties, providing the appropriate |
FWIW:
We absolutely require this be possible. See #254 (comment). If this is something that helps achieve the goal in this issue, then 2 birds, 1 stone etc. However, it seems that can be done separately to this. Should I raise an issue for that or convert my question into an issue for that (just not sure what workflow you prefer)? |
Compiling template syntaxes that allow users to specify whether an attribute or property is to be set, like Polymer or Angular 2, requires wrapping all primitive values in objects to force property setting. It'd be a lot friendlier of an API to just accept attributes and properties separately in
elementOpen
.The text was updated successfully, but these errors were encountered: