guiprav / dominant Goto Github PK
View Code? Open in Web Editor NEWDysfunctional JavaScript UIs
License: ISC License
Dysfunctional JavaScript UIs
License: ISC License
Store boundNodes
as weak refs from d.el
. This could dramatically improve performance as MutationObserver
tree walks are probably slower than going straight for the boundNodes
as document.contains
seems much cheaper than I thought.
OTOH this could decrease performance of apps with lots of hidden but not garbage collectible bound nodes.
This is as simple as replacing the current "reconciliation algorithm" with a bruteforce one that, whenever a sort is detected (i.e. the detected changes are not only simple additions/removals at the end of the mapped array), simply removes all relevant nodes from their parent element and reinserts them in the correct order. This would only cause unreasonable performance problems if sorting occurs frequently (e.g. 1~2 seconds apart or less), which is very uncommon. A proper reconciliation algorithm can probably wait quite a lot considering my use cases for now.
Add try/catch blocks to prevent getter errors from breaking d.update()
, etc.
dom.el(tagName, { style: () => ({ ... }) }, ...)
seems to be working atm for some reason. Fix it.Current implementation requires style={() => ({ ... })}
structure, but this is too different from the new dynamic class
prop API.
d.update()
is automatically called after invoking event listeners, but synchronously. If an event listener returns a promise, it would be nice if we awaited on it and called d.update()
upon promise resolution as well.
let counter = { count: 1 };
<div context={{ counter }}>
<div onAttach={el => {
let { counter } = dom.contextOf(el);
console.log(counter.count);
}} />
</div>
dom.contextOf
will merge and return context data from every parent element. Future invocations for the same element should return cached context data unless the element has been reparented since the last invocation.
Elements "portaled" outside their original JSX context will require some kind of link to their JSX parents so dom.contextOf
can access it as well. This would require some special kind of portalling API that creates those links.
The shallow{Clone,Eq}
helpers increase too much the library size and we can do it manually, very easily, and more flexibly calling d.{on,off}
directly, storing and comparing the last values in regular variables in client code.
Like attach
, but executes after all added node bindings have executed.
Binding.specialUpdateFnsByKey
was a nice first step towards modular handling of special props like class/style/value
, but d.el
still contains hardcoded handling for those. A logical next step would be to separate those into their own functions and build something similar to Binding.specialUpdateFnsByKey
for those as well, so their behavior can also be overridden or extended without patching Dominant's source code itself.
Might even be able to keep separate prop handler npm packages for each prop. Even if special prop handlers for class/style/value
are unavoidable in a web environment, it seems that keeping them separate might add very minimal complexity to the implementation code itself. I should validate this before actually breaking everything up though.
Still, separating them internally and allowing overriding/extension by project seems like an important thing to have, if possible.
d.on('update', fn)
, d.off('update', fn)
.
setting getter-only property "viewBox"
d.map
currently compares array values, which are typically JavaScript objects, using regular identity comparisons.
Optionally allowing object values containing "key" props to be compared by key instead would allow the objects to be freely recreated without causing unnecessary re-renders.
mapFn(x, i)
should probably be replaced with mapFn(cursor)
, where cursor.value
is a property getter to the currently mapped value (so different object instances could be returned for keyed maps) and cursor.index
is a property getter to the current value index in the array.
d.el(tagName, ...)
creates bindings from d.props
so we can write e.g. <input value={d.prop({ get, set })} />
instead of explicitly creating the binding with d.binding({ get, set })
.
d.el(component, ...)
defines getter/setter properties from d.props
before passing props
to component code. This allows us to write just props.key
instead of d.resolve(props.key)
and props.key = 123
instead of e.g. typeof props.key === 'function' ? props.key.set(123) : props.key = 123
.
The downside of this is that it's more verbose than implicit getter props from bare functions in d.el(component, ...)
, and those can't be automatically converted into getter properties because not all function properties are getters (some are callbacks and only client code could tell the difference), and implicit getter bindings from bare functions in d.el(tagName, ...)
would make those APIs asymmetrical.
The upside is that this would allow setting arbitrary functions to node properties, something that's impossible today, but also I'm not aware of any use-case for that (event listener props are currently distinguished from bare function bindings by their key prefix, on
).
Missing setters should throw if called. The error message should include the prop name. d.el
can set key names to d.prop
instances on initialization, so we can throw e.g. TypeError: Missing setter for ${this.key} prop
.
The component instance or root nodes can be added to d.prop
instances in the same manner as prop keys to provide context that the default error logger can also log to help debugging.
Also export d.promoteBindings
and promote deep prop bindings to getter/setter properties.
Consider replacing d.binding
with d.ref
altogether (bindings would still be used internally, but would be created by Dominant from refs instead of explicitly like today).
My preliminary tests have suggested peformance comparable to React v16.x (keyed), although Dominant is a non-keyed library (array items are implicitly keyed by their values, which are usually objects), but I'm obviously biased.
js-framework-benchmark may not be the best JS frameworks benchmark out there, but it's the only one I know of atm.
Babelatrix broke style
props; fix it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.