Open OliverJAsh opened 10 years ago
i'm definitely interested in some way to modify trees. my most recent need for something like this was being able to display a popup when a user clicked an arbitrary node. i'd love to be able to have the popup.render
take any vnode and add a click handler to it rather than needing to wrap that node in another one with the handler or any number of other just as ugly workarounds.
What about a h.extend(tree, { style: { fontWeight: 'bold' } })
that's basically an immutable deep extension of an existing vnode's properties.
:+1: i had figured that what i needed should come from h
due to the extra logic it has for parsing and applying events, etc.
h.extend
with vtree-select might be a powerful combination for transforms.
I just came here after reporting https://github.com/parshap/vtree-select/issues/4 .
I attempted to clone a vtree and got vtree-select
failing on it.
Excuse me, but, I can't find h.extend
in virtual-hyperscript. Perhaps you meant it as a feature suggestion, @Raynos ?
yes, it's a suggestion.
Thanks, @neonstalwart . +1 to that!
But, actually, I'm not sure if it is what I'm looking for. In my case, I would like to receive vtree input as a library and I would like to clone it or for it to be immutable so that it would no longer be subject to change by the user.
@mightyiam
a vtree node is effectively immutable. All virtual-dom
and mercury
related code should treat it to be immutable.
The only reason it's not actually immutable, i.e. we don't call Object.freeze
is because that is too expensive, causes large de-optimizations.
With that said, you can create a simple clone of a vtree if you wanted too, but that requires a deep clone that is prototype aware, that's all. Try ultradeepclone which will correctly set the prototype of the cloned object.
@Raynos Thank you. I'm developing a virtual-dom–based document editor for browsers. At the core of its state is a vtree, which represents the document.
In implementing undo/redo, I'm thinking:
But now I'm thinking that maybe things could go wrong with this, as even the ultradeepclone can't clone objects that were constructed with a constructor, because there's no access to that scope.
Can you please advise?
@mightyiam you don't do undo/redo on vtree instances.
I recommend you create a function render(appState) { return vtree }
that is pure. i.e. given the same appState
it always returns the same vtree
.
Then you can keep track of an immutable list of history for the appState. This way you just have to remember the last state of the application.
If you want to do any kind of time rewinding just render(oldAppState)
and diff that against the current vtree.
You can see an example here ( https://github.com/Raynos/mercury/blob/master/time-travel.js ).
:smile: i was just writing the same thing as @Raynos - use immutable state that you track and then derive your rendering from the state rather than tracking the rendering for each state. undo/redo is then just a matter of calling your render
function on the relevant state object.
@mightyiam I don't know if this helps, but I know Scribe (a rich text editor) is looking to move to a virtual DOM. See https://github.com/guardian/scribe/issues/236.
@OliverJAsh @mightyiam
ultradeepclone should work.
We do not do anything fancy in our constructors.
Thank you very much. Yes, indeed, ultradeepclone seems to provide clones of vtrees that are reusable. I can createElement
out of them.
Here's what I ended up with:
function render(count) {
// Ultra deep clone then mutate. I wish we had an immutable virtual dom
const newTree = udc(initialTree);
newTree.properties.style = { color: 'hotPink' };
return newTree;
}
I wish there was an immutable virtual tree object…
I wonder if we could come up with a way of merging two virtual trees, so you could do:
merge(h('div', 'foo'), h('div', { style: 'hotPink' }))
Is it possible to [deep] clone an existing virtual tree? Doing a standard deep clone on the object will not suffice because the virtual tree has a special object type.
Would it make sense to have modifier functions for trees which were immutable and returned cloned copies of the tree? E.g., you could have
tree.withStyle('font-weight', 'bold')
, instead of mutating the object attree.properties.style
. This would provide an immutable API for modifying trees.