Using jQuery's datastore vs. expando properties

后端 未结 4 1734
我在风中等你
我在风中等你 2021-01-31 20:22

I\'m developing code using jQuery and need to store data associated with certain DOM elements. There are a bunch of other questions about how to store arbitrary data w

4条回答
  •  生来不讨喜
    2021-01-31 21:07

    Let me rephrase the question: What are the practical differences between the two data binding options available?

    Actually there are three options:

    $(e).prop('myKey', myValue);
    $(e).data('myKey', myValue);
    $(e).attr('data-myKey', myValue);
    

    Note: OP’s e.myKey = myValue is practically the same as the .prop() line.

    • if you need more than strings, use .prop(), i.e. expando properties
    • if you need DOM/CSS transparency and/or HTML serialization use .attr('data-*')
    • if you need both you are out of luck
    • if you only use strings, but need no DOM, read on to weigh pros and cons yourself
    • what is with .data() → read the last two paragraphs

    If you ever want to pass the data around with serialized HTML you need the .attr() solution. I.e. whenever you use things like .innerHTML or .html() or want to construct snippets from strings with data included. The same applies if you want to use CSS selectors like elem[data-myKey]. Disadvantage: you can only store strings.

    If you don’t need your data to be visible in the DOM or available to CSS interaction .data() and .prop() might work. Their biggest advantage is: they can hold any Javascript value.

    .prop() biggest disadvantage is the possibility of name collision. Only pick names you can be sure will not be used as native property ever. E.g. scope as key is a bad idea, because it exists on some HTML elements...

    Now comes .data(). The other answers seem to swear on it, I avoid it. The memory leaks related to .prop() and expando properties in general belong to the past, so that is no advantage any more. But you will be secured against name collisions with HTML properties. That is an advantage. But you get a bunch of disadvantages:

    $(e).data('myKey') draws its uninitialized value from the data-myKey attribute if available, runs JSON.parse() on those and sometimes returns that or falls back to the string value of the attribute. Once you set $(e).data('myKey', myValue) you lose the relationship with the data-myKey attribute, which nevertheless lives on with its “old” value, shown in DOM and in CSS interactions. On top, the key name you use is subject to possible name mangling. I.e. if you ever decide to read all key-value via $(e).data() the keys in that object might be different.

    Because of this erratic behavior (mixing expando property technology with data-* attributes) and inconsistent get/set design I always avoid .data().—Fortunately that is easy to do with .prop() and .attr() (with data-* keys for compliance).

    If you really want to use .data() to avoid name clashes with native properties, my advice: do not mix with data-* attributes, consider them a different thing, and avoid name clashes with those.—Does that make sense? For automatic clash avoidance you have to avoid clashes elsewhere manually. Great design.

提交回复
热议问题