patrick-steele-idem / morphdom Goto Github PK
View Code? Open in Web Editor NEWFast and lightweight DOM diffing/patching (no virtual DOM needed)
License: MIT License
Fast and lightweight DOM diffing/patching (no virtual DOM needed)
License: MIT License
Applaud your work, and looks like a great project!
I just want to pick a little hole in your premise for why people use things like react - it's categorically not because the DOM is slow, but more to do with the logic around handling competing updates to a nested tree structure.
Expanding on this example - a set of nested views. A call to render higher up the tree should (probably) not cause the child views to re-render. It is of course possible to compute this logic, store references, and replace them or not depending on this, but the code to do so is often fragile and has its own series of abstractions. I use react/reactish library x because I don't have to worry about any of this. At no point have I ever considered the DOM to be slow - in fact, I accept the compromise that react is in general slower than direct DOM manipulation because of the lighter mental overhead and stronger abstractions when building complex stuff.
Does this make sense..?
I think there could be a use case for adding an onBeforeNodeDiscarded
callback that could return false
if the node should not be discarded. You can't use the onNodeDiscarded
callback because that could be called on a deep node that isn't possible to retain in the tree. But if it can be retained (i.e. it's going to be removed from a node that we're keeping), then we can use the callback to allow it to be kept in the tree.
The reason I think this would be great is because it adds the ability for third party libraries to insert nodes without morphdom clearing them out.
Example use case:
A third party library I'm working with injects a DOM node when I use it. However, when I create a render a new HTML string, that node is not present in the render (because it was added by the third party lib, and is not a part of my template). Morphdom sees this new node, and notices it isn't present in the new markup, so it removes it.
In this case, you could just add a onBeforeNodeDiscarded
callback that returns false
on the injected node, thus keeping it in the tree.
There is a reference to document.body
in morphdom right here.
I'm using webpack and including the scripts in the head, which is causing errors because the body has not been parsed yet.
Browser Support?
Not sure whether this is bug or correct behavior - if I'm morphing DOM tree containing SELECT element, first option (or option with selected attribute) is always set while morphing that tree, event if this particular element nor his children are changed.
this happens after a fresh npm install:
$ npm test
> [email protected] test /Users/julian/dev/juliangruber/morphdom
> npm run test-browser && npm run lint
> [email protected] test-browser /Users/julian/dev/juliangruber/morphdom
> node test/mocha-phantomjs/run.js test
Preparing client-side tests...
Config: { runBenchmarks: false, runTests: true }
/Users/julian/dev/juliangruber/morphdom/test/mocha-phantomjs/test-page.marko.js:13
lasso_page({
^
TypeError: lasso_page is not a function
at render (/Users/julian/dev/juliangruber/morphdom/test/mocha-phantomjs/test-page.marko.js:13:5)
at Object.Template.render (/Users/julian/dev/juliangruber/morphdom/node_modules/marko/runtime/marko-runtime.js:192:9)
at Object.Template.(anonymous function) [as render] (/Users/julian/dev/juliangruber/morphdom/node_modules/marko/hot-reload/index.js:84:34)
at run (/Users/julian/dev/juliangruber/morphdom/test/mocha-phantomjs/run.js:107:18)
at Object.<anonymous> (/Users/julian/dev/juliangruber/morphdom/test/mocha-phantomjs/run.js:135:1)
at Module._compile (module.js:397:26)
at Object.Module._extensions..js (module.js:404:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:429:10)
<!DOCTYPE html>
<html>
<body>
<script src="node_modules/morphdom/dist/morphdom-umd.js"></script>
<script>
var fromEl = document.createElement('div');
var toEl = document.createElement('div');
fromEl.innerHTML = '<div id="qwerty" class="div1"></div>';
toEl.innerHTML = '<div><div id="qwerty" class="div1"></div></div>';
var div1 = fromEl.querySelector('.div1');
morphdom(fromEl, toEl);
var div1_2 = fromEl.querySelector('.div1');
console.log(div1 == div1_2); // false ???, should be true
</script>
</body>
</html>
Might be able to squeeze out some perf if we use the DOMParser API, (ie9+).
https://jsperf.com/domparser-vs-innerhtml-vs-createhtmldocument/8
What are your thoughts on this?
Edit:
Found a better JSPerf, https://jsperf.com/domparser-vs-createelement-innerhtml/6.
Seems to suggest that caching the "createRange" and the "innerHTML el" would yield better results which we are doing.
Also http://jsperf.com/childnodes-vs-firstchild could help.
Hey @patrick-steele-idem ,
Continuing mathieuancelin/js-repaint-perfs#53 so not to clutter the pull req with OT discussion...
I'm seeing nearly identical performance compared to React
React is quite slow (not sure how much faster v15.0 is). Though you could make the argument that it doesn't matter from its popularity.
morphdom
is tiny (network overhead is often more important... especially in developing countries)
Well, 7.7k (morphdom) [1] vs 10.9k (domvm) [2] or others [3][4][5] is a negligible difference. Even less so after gzip. Developing countries also have slow, shitty phones :)
While the dbmon benchmark is interesting it is just one use case that is likely not representative of real world usage
True, it's unrealistic for 100%, 50% and even 20% mutations, but is realistic for 0%-5% mutations.
For example, morphdom provides hooks to avoid diffing/patching DOM subtrees (e.g., onBeforeUpdateEl)
To be fair, many (most?) vdom libs also provide this.
morphdom
avoids the memory overhead of maintaining a parallel virtual DOM tree in memory
From the example [6] at least, it looks like it actually creates a much more expensive detached DOM to do the diff, no?
morphdom plays nice with vanilla DOM libraries and web components...
morphdom
can be used with any library that produces HTML or DOM nodes..[doesn't rely on non-standardized vtree represenations, treats DOM as the truth]
This is really the main selling point, which is nice.
morphdom will get faster as browsers optimize the DOM
True, perhaps one day: https://air.mozilla.org/bay-area-rust-meetup-february-2016/#@25m50s
Using morphdom for animation is not recommended (use hardware accelerated CSS transitions or an animation library instead)
I think that using any vdom lib for tick/step based animations is terrible practice.
Disclaimer: I'm the author of domvm [7]...dbmonster [8] (optimized a bit for low mutations yields 145fps @ 1%) or dumb re-diff everything [9] (70fps @ 1%)
[1] https://github.com/patrick-steele-idem/morphdom/blob/master/dist/morphdom-umd.min.js
[2] https://gist.github.com/leeoniya/baa5b971f3421d2a628729e456766b8e
[3] https://github.com/paldepind/snabbdom
[4] https://github.com/joelrich/citojs
[5] https://github.com/developit/preact
[6] https://github.com/patrick-steele-idem/morphdom#usage
[7] https://github.com/leeoniya/domvm
[8] http://leeoniya.github.io/domvm/test/bench/dbmonster/
[9] https://github.com/mathieuancelin/js-repaint-perfs/blob/gh-pages/domvm/app.js
I ran into this today. I tracked it down, but it wasn't obvious, so I'm posting to help anyone else who may get the same issue.
The problem was caused by generating duplicate ids. When morphdom creates an internal map it uses the id. When it reaches a second node with the same id, it seems to pull from the map. If that node is already removed from the dom, you'll get this error.
To track it down, render the view in question without running through morphdom or do so in a way that does not remove nodes. Then use a tool like HTML Codesniffer to find problems in your markup.
Cheers.
I create test:
it('patch tags by id', function() {
var el1 = document.createElement('div');
el1.innerHTML = '<span id="boo" class="foo"></span>';
var el2 = document.createElement('div');
el2.innerHTML = '<div id="boo"></div>';
var morphedEl = morphdom(el1, el2);
expect(el1.innerHTML).to.equal('<div id="boo"></div>');
});
Failed:
AssertionError: expected '<span id="boo"></span>' to equal '<div id="boo"></div>'
+ expected - actual
-<span id="boo"></span>
+<div id="boo"></div>
I think it would be beneficial to have some way to have morphdom handle keys similar to how they are handled in virtual-dom (https://github.com/Matt-Esch/virtual-dom/blob/master/virtual-hyperscript/README.md#key).
Maybe a non-standard HTML attribute (such as key="someKey"
) could be used along with the tagName to determine if a node is identical?
I'm happy to make a PR for whatever you're are happy with, I just think something like this would be helpful!
The npm package installs with a .cache
folder which is 22mb in size
Any way to detect the reorder of siblings? Perhaps optionally to avoid a performance penalty for this edge case. I have a list of videos. If video 2 is playing and video 1 is removed or reordered, video 2 is stopped because its source attribute is changes.
Morphing <head>
element should have a different algorithm because we have a set of immutable elements such as: <style>
, <script>
and <link rel="stylesheet">
. Changing these element's attributes or re-creating of these elements causes style flickering and script reloading which breaks any app.
My proposal would be:
src
value for <script>
and href
value for <link rel="stylesheet">
. We need this for handling attributes re-ordering and changing of those attributes which are irrelevant for script or style reloading.<script>
, <style>
and <link rel="stylesheet">
nodes inside <head>
element if morphing to a new state requires to remove them.For example,
We have a head element:
<head>
<title>First title</title>
<style type="text/css">some styles1</style>
<script type="application/javascript">some scripts1</script>
<script type="application/javascript" src="someScriptSrc1"></script>
<link rel="stylesheet" href="someStyleLink1">
<link rel="author" href="Author">
<meta name="name1" content="value1">
</head>
New state is:
<head>
<title>Second title</title>
<style type="text/css">some styles2</style>
<script type="application/javascript">some scripts2</script>
<script type="application/javascript" src="someScriptSrc2"></script>
<link rel="stylesheet" href="someStyleLink2">
<link rel="author" href="New Author">
<meta name="name1" content="value2">
</head>
After morphing we have:
<head>
<title>Second title</title>
<style type="text/css">some styles1</style>
<style type="text/css">some styles2</style>
<script type="application/javascript">some scripts1</script>
<script type="application/javascript">some scripts2</script>
<script type="application/javascript" src="someScriptSrc1"></script>
<script type="application/javascript" src="someScriptSrc2"></script>
<link rel="stylesheet" href="someStyleLink1">
<link rel="stylesheet" href="someStyleLink2">
<link rel="author" href="New Author">
<meta name="name1" content="value2">
</head>
As far as I use morphdom inside Catberry.js, I have to implement a separate algorithm for solving this problem, you can see it here. But I believe you would come up with a better solution using morphdom approach.
I'm using document.registerElement to create custom elements. I'd like to update the contents of the element without touching the existing parent and without creating a new parent element. In essence, the effect of setting .innerHTML
but with morphdom's diffing.
The childrenOnly
option gets me half way there. For example, the following does what I want:
<!-- before -->
<my-dashboard>Hello</my-dashboard>
import morphdom from 'morphdom';
import {register} from '../../scripts/util/dom';
export default register('my-dashboard', HTMLElement, {
createdCallback() {
// called twice
},
attachedCallback() {
this.render();
},
render() {
morphdom(this, '<my-dashboard>World</my-dashboard>', {
childrenOnly: true
});
}
});
<!-- after -->
<my-dashboard>World</my-dashboard>
However, two instances of <my-dashboard>
are created in this case, so the createdCallback
is fired twice. I only ever want one created. Ideally, I'd like to do something like this:
import morphdom from 'morphdom';
import {register} from '../../scripts/util/dom';
export default register('my-dashboard', HTMLElement, {
createdCallback() {
// called once
},
attachedCallback() {
this.render();
},
render() {
morphdom(this, 'World', {
innerHTML: true
});
}
});
Would you be interested in a PR that adds this? I didn't see a way to implement this using the existing hooks.
Shouldn't we create a DocumentFragment
here instead?
Line 14 in b7654c5
https://gist.github.com/anonymous/71cec266f8e04f3bf05f1fc67116c5a1
Here is a snippet of the HTML. If you could, repeat the <tr>
s until you reach about 1.5MB.
This acts as #pick_table.
Some very small changes are made (background color, maybe a 0 to 1 in quantity, etc.)
I generate the HTML as a string inside of my app. I then flush it straight to the DOM.
Offending code:
var element = document.createElement('tbody');
element.innerHTML = html;
morphdom(document.querySelector('#pick_table tbody'), element);
Is there any way I can improve the performance? It's 300ms on my speedy MacBook Pro. I have customers complaining (this is code in a production app) that it takes 5s+ :/
I'm sure I'm doing something wrong, so any input would be greatly appreciated! Please let me know if I can provide any further information.
Would it be possible to support the following use case:
// Example element, could be a reference to an existing DOM node.
var element = document.createElement('div');
element.innerHTML = '<span>Hello</span>';
// Build the fragment to match the children.
var fragment = document.createDocumentFragment();
fragment.appendChild(document.createElement('span'));
fragment.firstChild.appendChild(document.createTextNode('World'));
// This currently does not error, but does not diff the children.
morphdom(element, fragment);
Example using diffHTML: tbranyen/virtual-list@5500f1c#diff-9ec5f0d45b1fdec47275a0f431b03f62R75
I'd like to make this work with morphdom as well.
When updating the dom sometimes we want to keep existing input values. Would be handy to have an option that kept the existing 'value' attribute and only override it if a new one is in the new dom.
Please watch this video:
http://youtu.be/X33mMzkzR-A
HTML:
<input type="text"/>
Javascript:
var input = document.querySelector('input');
input.addEventListener('input', function (e) {
var newNode = document.createElement('input');
newNode.value = e.currentTarget.value;
morphdom(e.currentTarget, newNode);
});
I know it's hard correct handle same cases, but it's very useful feature, because you can easy make two-way data-binding and don't care about "dirty hacks".
Line 222 in ea14445
Is there any particular reason to not use strict equality comparison here?
Some weird bug occurs in IE only (8-11 and Edge as well). When morphing a button
element with a class and a name attribute to a button
that only has the class but not the name, the resulting button will have an empty class attribute.
The critical part of code is a call of removeAttributeNode
in morphAttrs
function:
https://github.com/patrick-steele-idem/morphdom/blob/master/lib/index.js#L190
I don't know the reason for use of removeAttributeNode
method, but I tried using removeAttribute
instead and it seems to fix the bug.
The same issue can be reproduced with this simple snippet:
var btn = document.createElement('button');
document.body.appendChild(btn);
btn.setAttribute('class', 'btn');
btn.setAttribute('name', 'myButton');
btn.innerHTML = "TEST";
btn.removeAttributeNode(btn.getAttributeNode('name'));
console.log(btn.getAttribute('class') === 'btn'); // => false!
Hello. Is it possible for morphdom to support creating elements with namespace? I've tried to morph my SVG and I had svg
element on the page, but it had namespaceURI
which does not correspond to SVG, so element is present but not working.
I've been trying to work out a sensible way to handle the lifecycle of elements. It would be useful to know when an element is added to the document, when it's morphed, and when it's discarded. Though this functionality exists (aside from creation), it's not very well set up to allow you to respond to these changes on a per-element basis.
var button = document.createElement('button')
button.on('update', function () {
button.focus()
})
Some other inspiration...
https://github.com/substack/virtual-hyperscript-mount
https://github.com/substack/virtual-hyperscript-hook
virtual-dom: https://github.com/Matt-Esch/virtual-dom/blob/master/docs/hooks.md
React: http://facebook.github.io/react/docs/component-specs.html
What do you think? I would like to put a library together that wraps morphdom to provide this functionality, but I'm not sure if I've got the wrong idea.
On version 1.4.1 I have a problem with patching svg.
In DOM:
<svg class="icon icon--pin">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-pin" class="js-icon"></use>
</svg>
Patching remove xlink:href
attribute.
I create test:
it('should transform svg', function() {
var el1 = document.createElement('div');
el1.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon--search"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-search" class="js-icon"></use></svg>';
var el2 = document.createElement('div');
el2.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon--search"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-search" class="js-icon"></use></svg>';
morphdom(el1, el2);
expect(el1.innerHTML).to.equal('<svg xmlns="http://www.w3.org/2000/svg" class="icon icon--search"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-search" class="js-icon"></use></svg>');
});
Failed:
-<svg xmlns="http://www.w3.org/2000/svg" class="icon icon--search"><use class="js-icon"></use></svg>
+<svg xmlns="http://www.w3.org/2000/svg" class="icon icon--search"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-search" class="js-icon"></use></svg>
I had hoped this could be run in nodejs and maybe it could with jsdom. Could be clearer about being only a browser implementation.
Textarea updates doesn't work after first input text.
<textarea></textarea>
<script>
document.querySelector('textarea').addEventListener('input', function(e) {
var textarea = document.createElement('textarea');
textarea.innerHTML = 'Hello World';
console.log(textarea, e.currentTarget);
morphdom(e.currentTarget, textarea);
}, false);
</script>
Look diffirence between shadow-dom and innerHTML
I hope it help you understand issue.
Sorry Duplicate of #51
We have a setup where we are running tests on marko widgets, and are seeing the issue below :
PhantomJS 1.9.8 (Mac OS X 0.0.0)
TypeError: 'null' is not an object (evaluating 'morphedNode.nodeType') (/path/to/project/.test/lasso/static/node_modules/marko-widgets/node_modules/morphdom/lib/index.js:373)
In addition to this we are also seeing:
ERROR: '(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.', 11
Causing all the tests the fail.
First of all... thanks so much for making this!!!!!
Since learning about virtual dom I though it was such an ingenious idea for solving the problems you mention with replacing innerHTML as your state changes. The issue is that all the stuff out there requires a paradigm shift in terms of how I currently approach things. I just like the idea of templates more JSX. Then I found this!
When building browser apps I like to just use bower and browser "globals" vs trying to pack everything into an isolated context. I tend to feel the window object is a straight forward context for keeping your 3rd party modules. Also makes working with jQuery stuff a lot more simple. I still keep the core app in it's own isolated context and pass an API to the window... Maybe I'm stuck in the old school.
I was wondering if you would be up for adding a bower file to this project and set it up to use the "UMD" trick to offer core methods as "globals" as well as module exports.
Thanks!!!
Hi i've just seen your project in the github trending projects page,
and it triggered my attention because i was in the middle of starting a very similar one.
While searching about how to implement my own in the last days it i've found this:
to read/cycle the source dom tree (in modern browsers) probably is faster to use this api than manually and recursively cycle the dom tree in js (fallback to this method required for old browsers):
https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
to apply changes in the destination dom tree,
lately seems google have developed a lib to do exactly that:
https://github.com/google/incremental-dom
seems your code does not use this things,
have you considered this options?
there is something wrong in this approach for you?
Current version makes use of document.createRange
and Element.prototype.hasAttribute
, which are unavailable on older browsers.
createRange
can be skipped because the fallback for creating a fragment works without it.
hasAttribute
on the other hand can't be easily replaced, but for the use case of the INPUT handler, I would suggest simply checking the getAttribute response for a truthy value.
As far as I've tested, everything else is working fine.
I will submit a pull request with those changes.
Currently using jsdom for testing which could be part of the issue, but the following diff detaches the document element and fails.
morphdom(document.documentElement, `
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>content</body>
</html>
`);
Am I doing something wrong? Even tried removing the doctype.
Edit:
Also tried doing this directly in Chrome Version 51.0.2680.0 canary (64-bit)
and received the following error.
VM414:479 Uncaught DOMException: Failed to execute 'replaceChild' on 'Node': Nodes of type '#text' may not be inserted inside nodes of type '#document'
From:
https://github.com/patrick-steele-idem/morphdom/blob/master/lib/index.js#L478
Edit2:
Looks like the issue stems from https://github.com/patrick-steele-idem/morphdom/blob/master/lib/index.js#L38 and https://github.com/patrick-steele-idem/morphdom/blob/master/lib/index.js#L41 in my case, but it looks like #toElement
just doesn't support anything outside of body.
You state that walking through the DOM isn't slow, but in reality it really is. Accessing things like firstNode or childNodes is vastly slower than storing a light-weight representation of it (aka virtual DOM).
Furthermore, handling of keyed nodes becomes problematic when using DOM nodes. There simply isn't any performant way of doing this when using the DOM as the source-of-truth.
Have you see this too? http://vdom-benchmark.github.io/vdom-benchmark/
Furthermore, you shouldn't really be comparing yourself to the virtual-dom
library and stating that library as the de-facto virtual DOM standard, it's one of the slowest implementations of virtual DOM out there in Safari (it's noticeably faster than morphdom in Chrome according to your own benchmark).
It is not currently possible to install this library using bower because
Would be great if it was possible to use bower for installation.
I noticed that morphdom was updating my DOM way more than I expected, and narrowed it down to the presence of comments. Here's a simple test I added that fails (pull request with naive fix to follow).
it('should not alter the DOM unnecessarily in the presence of comments', function() {
var el1 = document.createElement('div');
el1.innerHTML = '<!-- comment --><div class="div1">a</div>';
var el2 = el1.cloneNode(true);
var addedNodes = [];
var discardedNodes = [];
morphdom(el1, el2, {
onNodeAdded: function(el) { addedNodes.push(el) },
onNodeDiscarded: function(el) { discardedNodes.push(el) }
});
// This was a no-op update, and should have made no changes
expect(addedNodes).to.be.empty;
expect(discardedNodes).to.be.empty;
});
I noticed the following commented code:
// XXX optimization: if the nodes are equal, don't morph them
/*
if (fromNode.isEqualNode(toNode)) {
return fromNode;
}
*/
This seems entirely reasonable. If this is waiting on a polyfill for <IE9, I suggest just returning false
. It won't be any slower or faster in IE but it could speed up other browsers. If there's another reason, then by all means, explain :)
How do you handle events using morphdom?
https://facebook.github.io/react/docs/multiple-components.html#dynamic-children
Hi!
Sorry, translated with translate.google.ru ((
This update faster. In addition, if the nodes are attached to component instances will be destroyed is not correct instances.
For example here https://gist.github.com/Riim/e47127fc4a88cf1e0ff9 (rista.js is this file https://github.com/Riim/rista/blob/37974a40fc83a7127af96e513a67a1fae080694c/rista.js) second element of the list todos
is removed after three seconds, but dispose triggered on the third instance.
It would be nice if we could get of list of modified elements, so its possible to animate or post-process it.
getting a couple warnings on a fresh npm install:
npm WARN deprecated [email protected]: Package not maintained. Recent browserify uses https://github.com/feross/buffer
npm WARN engine [email protected]: wanted: {"node":"~0.10.0"} (current: {"node":"5.4.1","npm":"3.3.12"})
npm WARN deprecated [email protected]: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated [email protected]: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.
npm WARN deprecated [email protected]: this package has been reintegrated into npm and is now out of date with respect to npm
This works:
morphdom($("#out"),
`<div id="out">
Foo
</div>`
Howerever this doesn't:
morphdom($("#out"), `
<div id="out">
Foo
</div>`
(not the position of the opening Backtick-Quote)
This als won't work:
morphdom($("#out"), ` <div id="out">Foo</div>`
(Note the leading Space in the string)
With $ beeing
const $ = document.querySelector.bind(document);
In theory, the new target DOM could be a virtual DOM. As long as the virtual DOM exposes an interface that implements the required subset of the real DOM API (node.firstChild
, node.tagName
, node.nextSibling
, node.attributes
, etc.) then things will work for the most part. The only difference is that if a virtual DOM node is to be inserted into the real DOM then it will need to be upgraded into a real DOM node. This would add very little overhead to morphdom
while also making it more flexible.
If an application is able to efficiently produce a virtual DOM then that application will likely see better performance.
Pull Requests welcome.
Native node has more informations that a virtual node.
What do you think about using outerHTML and cssText String for a comparison between 2 nodes first of iterate attributes and childs for know if something is changed?
I was just wondering what was the initial use case, the one that made you create this library. I was thinking of marko
async fragments, but then again marko
only gives you missing pieces, not a complete "section" of DOM.
Thanks!
Hi all, at first great work!
I came across with something that seems to be a issue,
consider the following:
var el = document.createElement('div');
el.className = 'foo';
el.innerHTML = 'bar';
document.body.appendChild(el);
var updates = '<!-- some comment --> <div class="foo">bar</div>';
morphdom(el, updates);
the el
variable behaves exactly as it should be:
expect(el.className).to.equal('foo'); // true
but in the dom what I actually got is this:
I am not sure if this is a bug or an expected behavior,
any insights?
Hi,
i am playing with morphdom. in this example i see that the dom is redraw every time. ok can i preserve the dom and node attributes every refresh frame?
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.