最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - I know its bad to store data in the DOM, but why? - Stack Overflow

programmeradmin2浏览0评论

I've heard over and over again that it is bad practice to "use the DOM as a database."

While I mostly agree with that sentiment, this question is more about the less black and white cases. Keeping in mind the latest revisions to jQuery's .data() methods and the HTML5 data-attribute spec, is it really so bad to stick some data in the DOM for the sake of convenience?

For example, I recently implemented a "live" calculation feature on a table full of inputs by doing something like this:

<table>
  <tr>
    <td><input type="text"></td>
  </tr>
  <tr>
    <td><input type="text"></td>
  </tr>
</table>

jQuery:

$('table').bind('calculate',function(){
  var total = 0;
  $(this).find('tr').each(function(){
    total += $(this).data('value');
  });
  // display total
});

$('table input').bind('change keyup',function(){
  $(this).closest('tr').data('value',$(this).val());
  $(this).closest('table').trigger('calculate');
});

This is an over-simplified example because I could skip the calls to .data() and go straight to the input values, but let's imagine a slightly more complex scenario where elements other than inputs are affecting the row values.

Is it wrong to use the DOM to store simple data in this kind of situation?

I've heard over and over again that it is bad practice to "use the DOM as a database."

While I mostly agree with that sentiment, this question is more about the less black and white cases. Keeping in mind the latest revisions to jQuery's .data() methods and the HTML5 data-attribute spec, is it really so bad to stick some data in the DOM for the sake of convenience?

For example, I recently implemented a "live" calculation feature on a table full of inputs by doing something like this:

<table>
  <tr>
    <td><input type="text"></td>
  </tr>
  <tr>
    <td><input type="text"></td>
  </tr>
</table>

jQuery:

$('table').bind('calculate',function(){
  var total = 0;
  $(this).find('tr').each(function(){
    total += $(this).data('value');
  });
  // display total
});

$('table input').bind('change keyup',function(){
  $(this).closest('tr').data('value',$(this).val());
  $(this).closest('table').trigger('calculate');
});

This is an over-simplified example because I could skip the calls to .data() and go straight to the input values, but let's imagine a slightly more complex scenario where elements other than inputs are affecting the row values.

Is it wrong to use the DOM to store simple data in this kind of situation?

Share Improve this question asked May 6, 2011 at 1:42 Jordan SitkinJordan Sitkin 2,3433 gold badges26 silver badges35 bronze badges 5
  • The nodes in your DOM tree are data. – Lightness Races in Orbit Commented May 6, 2011 at 1:47
  • touché. but you know what i mean... people have advised me to always create some kind of model in memory here. would that save me form trouble or is this really ok? – Jordan Sitkin Commented May 6, 2011 at 1:48
  • I'm either misunderstanding the question or I'm misunderstanding how jQuery's data() method works. I thought jQuery stored those values in its cache rather than literally attaching data to the DOM. – Kevin Ennis Commented May 6, 2011 at 2:24
  • 1 @kennis, neither! I just didn't know that jQuery's data() method stored values in a cache. I was confused by this: As of jQuery 1.4.3 HTML 5 data- attributes will be automatically pulled in to jQuery's data object. The treatment of attributes with embedded dashes was changed in jQuery 1.6 to conform to the W3C HTML5 specification. I had just assumed that since data-attributes and .data() seemed to be coupled that jQuery was using the DOM. But clearly there is some other magic happening. I should just check out the source... – Jordan Sitkin Commented May 6, 2011 at 4:47
  • 1 jQuery claims not to store it in the DOM: "The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery)." – Carl G Commented Jun 15, 2013 at 6:58
Add a comment  | 

4 Answers 4

Reset to default 44

It's fine to store data in DOM objects. And since your question is specific to jQuery's data API, it's important to understand how the data API works. I wrote an answer explaining its inner workings a while back. The data API only keeps a reference to the DOM objects along with the data, and doesn't store anything inside the DOM objects themselves. All data is stored in plain old JavaScript objects.

The issue of whether that is a good or a bad approach is a matter of personal taste. John Resig, the creator of jQuery, gave a talk at Tech4Africa in 2010 where he talks about this exact issue, and proposes to do away with a separate storage area and link everything with the DOM using the data API. You can see the talk on YouTube (thanks to @tine2k for providing the link). If you listen to the entire talk, you'll find some good examples of why this approach makes sense and keeps things simple.

I believe similar arguments can be made for the other end of the spectrum - to have your data in neatly tucked away objects, and classes, and be separate from the view itself. That sort of thinking comes from traditional architectures such as MVC.

I say it's fine to go with either approach - using the DOM to store data, or using a classical approach. Just don't mix the two, cause then you application model is sprinkled everywhere.

There are some fundamental arguments against using the DOM to store data:

  1. The DOM is supposed to be a view of data. The properties of DOM elements should be metadata for the elements themselves, not data from the model.

  2. You should not add random properties to host objects as you have no idea what they might do with them.

  3. You have the same issue as global variables - if it becomes common practice, you will have to adopt a scheme to avoid name collisions.

There is also the argument that the DOM is a pretty ordinary data store and that object structure with indexes will be much more efficient for anything other than trivial data needs.

If you only have small amounts of data and have full control over your pages, then go ahead and put data in data- attributes and properties. But do not store large chunks or complex structures.

Oh, and I don't think there are any performance issues - accessing an element and its properties in the DOM is likely no faster or slower than accessing some part of an object structure, though I'm sure there are faster and slower ways of doing both.

I don't think there is anything wrong with storing data in the DOM, but I think the issue lies with storing a lot of data in the DOM. The browser does have to muddle through the DOM to output the pages we see, and the more data that is in there the more crap it has to sort out.

I'm sure there are also other reasons as well, this is just my deduction.

Having developed a few single page apps for CE devices that have limited browser power, I have adopted a few extra personal standards about these things. The main thing is that just because JQuery supports scanning through the DOM, that does not suggest it as a performant approach. If I need to know which LI has focus, I could use .index() or .find() or even .each(), but keeping that value in a separate model object is better for the following reasons:

  1. MVC is a real thing, despite the rampant abuse through doing things like using the DOM as a state holder. Keeping state in the model as a rule makes MVC make sense.
  2. Scanning through the LI tags is more expensive than using listItems.focussed in code.
  3. The DOM is busy being manipulated and your queries on it may be delayed or cause delays.
According to Matt @ https://github.com/Matt-Esch/virtual-dom, "Reading some DOM node properties even causes side effects." I tend to agree with that point, but i will admit I am in search for more evidence on that point, as the guy appointed to chase down our biggest apps performance issues that I am personally convinced are tied mostly to DOM dependent code.

发布评论

评论列表(0)

  1. 暂无评论