karlitos
karlitos

Reputation: 1656

Most efficient way co compare two DOMStrings if they represent the same DOM node in JavaScript

I use ReactJs function renderToStaticMarkup to create HTML Markup. The markup is on another place in the App set as the innerHTML property to other DOM node. Since I would like to prevent images and iframes from re-rednering, I would like to make comparison, if the current innerHTML is the different from the one it should be set to.

if (!domNode.innerHTML !== newMarkup);
    domNode.innerHTML = newMarkup;
}

For some reason, Reacts renderToStaticMarkup creates HTML Markup for images as:

<img src="https://placebeard.it/200x150" alt="" class="content-media-image-linked"/>

but the DOM innerHTML has a value of

<img src="https://placebeard.it/200x150" alt="" class="content-media-image-linked">

So basically the difference IS in the trailing / (but this does not need to be the rule of thumb)

I wonder what would be the most efficient/fast way to determine, whether those two DOMStrings represent the same DOM Node.

1. String Comparison

It would be probably enough to replace/remove all occurrences of />

2. Parsing/converting to DOMNodes

This is more safe method, but also much more expensive. I would have to use something like document.createRange().createContextualFragment (see this post) and than use the isEqualNode method.

Has aonyone some better sugeestion ?

Upvotes: 0

Views: 1060

Answers (2)

karlitos
karlitos

Reputation: 1656

A quick fix to my issue was performing sanitization of the HTML Markup produced by the _ renderToStaticMarkup_ call. In my case the markup is generated only occasionally, but the Dom-Node equality check very often, so I went with just plain string quality-check.

I tried multiple libraries to achieve that:

sanitize-html lokked promissing, but was not removing the trailing /

html-minifier worked, but I had issues using it with es6 imports

I ended up using dompurify

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074385

As I think you know, the / in /> at the end of a tag has no meaning whatsoever in HTML (it does in XHTML and JSX), so my temptation would be

  1. Change the /> to > and compare; if they match, they're the same.

  2. If they don't match, parse it and use isEqualNode

The first gives you the quick win in what I assume will be the majority case. The second works the slower but more robust way, allowing attributes to be in a different order without introducing a difference (unless it makes a difference), etc.

When replacing the /> with >, be sure of course to only do so in the right place, which may or may not be tricky depending on the strings you're dealing with (e.g., to they contain nested HTML, etc.). ("Tricky" as in "you can't just use a simple regular expression" if the HTML isn't of a single element like your img example.)

Upvotes: 1

Related Questions