问题
So the problem is that I have an html element which has an object in a "data-" attribute (set via jQuery ofc) and I want to listen to changes in that attribute.
I have already tried a lot of things, like setting almost all possible combination values in the MutationObserverInit object, but none of this help.
Does anybody know if it is possible?
$('#some-id').click( function() {
//$('#some-id').attr('title', 'some-title'); //this works
$('#some-id').data('foo', 'bar1'); //this don't
});
var functionCallBack = function(mutations) {
alert('something changed')
}
// select the target node
var target = document.getElementById("some-id");
// create an observer instance
var observer = new MutationObserver(functionCallBack);
// configuration of the observer:
var config = { subtree: true, childList: true , attributes: true};
// pass in the target node, as well as the observer options
observer.observe(target, config);
$('#some-id').data('foo', 'bar');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>
回答1:
New Answer (Based on Oriol's Answer):
I think Oriol provided a better approach but it could be optimized further.
var object = {
'key': 'value'
};
$('.addObj').click(function() {
$('#some-id').observeData('foo', object, function() {
console.log("Object Added");
});
});
$('.removeObj').click(function() {
$('#some-id').observeData('foo', null, function() {
console.log("Object removed");
});
});
jQuery.fn.observeData = function(name, object, callback) {
// Get elemenet
var element = $(this[0]);
// Add data
element.data(name, object);
// Call the callback function
callback();
// Return this for a chainable function
return this;
};
span {
padding: 10px;
float: left;
margin: 5px;
cursor: pointer;
background-color: green;
border: 1px solid black;
border-radius: 5px;
transition: all 0.5s;
color: white;
font-size: 13px;
}
span:hover {
opacity: 0.8;
}
#some-id {
text-align: center;
width: 100%;
margin: 10px 0;
font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>
<span class='addObj'>Add Object</span>
<span class='removeObj'>Remove Object</span>
JSFiddle: https://jsfiddle.net/t012rb9j/1/
Old Answer:
As you stated in your code:
$('#some-id').click(function() {
// $('#some-id').attr('title', 'some-title'); //this works
$('#some-id').data('foo', 'bar1'); //this don't
});
.attr() works while .data() is not working. The reason is that .attr() adds an an attribute value to your HTML tag while data stores this data in memory.
From jQuery documentation:
.data(): Store arbitrary data associated with the specified element and/or return the value that was set.
.attr(): Get the value of an attribute for the first element in the set of matched elements or set one or more attributes for every matched element.
One way to detect data changes (if you want to store an object) is to combine both functions.
var object = {
'key': 'value'
};
$('.addObj').click(function() {
$('#some-id').data('foo', object).attr("data-attached", "true");
});
$('.removeObj').click(function() {
$('#some-id').data('foo', null).attr("data-attached", "false");
});
var functionCallBack = function(mutations) {
mutations.forEach(function(mutation) {
if (jQuery(mutation.target).attr("data-attached") == "true") {
// Your code here
console.log("Object Added");
} else {
console.log("Object removed");
}
});
}
// select the target node
var target = document.getElementById("some-id");
// create an observer instance
var observer = new MutationObserver(functionCallBack);
// configuration of the observer:
var config = {
subtree: true,
childList: true,
attributes: true
};
// pass in the target node, as well as the observer options
observer.observe(target, config);
.addObj, .removeObj {
padding: 10px;
float: left;
margin: 5px;
cursor: pointer;
background-color: green;
border: 1px solid black;
border-radius: 5px;
transition: all 0.5s;
color: white;
font-size: 13px;
}
.addObj:hover, .removeObj:hover {
opacity: 0.8;
}
#some-id {
text-align: center;
width: 100%;
margin: 10px 0;
font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>
<span class='addObj'>Add Object</span>
<span class='removeObj'>Remove Object</span>
JSFiddle: https://jsfiddle.net/9xkb6jv4/
回答2:
If you want to detect new data set with jQuery's data
, you can always hijack it.
var functionCallBack;
var $data = jQuery.fn.data;
jQuery.fn.data = function(key, value) {
var ret = $data.apply(this, arguments);
if(functionCallBack && this[0] && value !== undefined) {
functionCallBack(this, key, value);
}
return ret;
};
$('#some-id').click( function() {
$(this).data('foo', 'bar1');
}).data('foo', 'bar');
functionCallBack = function(elements, key, value) {
console.log('something changed')
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="some-id">HEY</div>
来源:https://stackoverflow.com/questions/41538686/can-mutation-observer-listen-for-changes-in-data-attributes