深入学习jquery源码之data()
jQuery.data(element,[key],[value])
概述:
在元素上存放数据,返回jQuery对象。
注意:这是一个底层方法。你应当使用.data()来代替。
此方法在jQuery 1.8中删除,但你仍然可以通过$._data(element, "events")调试事件数据。请注意,这是不支持的公共接口;实际的数据结构可能会改变从版本之间不兼容。
参数:
element,key,value String,String,Any
element:要关联数据的DOM对象
key:存储的数据名
value:将要存储的任意数据
element,key String,String
element:要查询数据的DOM对象
key:存储的数据名
element String
要查询数据的DOM对象
jQuery.data(document.body, 'foo', 52);
jQuery.data(document.body, 'bar', 'test');
data([key],[value])
概述:
在元素上存放数据,返回jQuery对象。
如果jQuery集合指向多个元素,那将在所有元素上设置对应数据。 这个函数不用建立一个新的expando,就能在一个元素上存放任何格式的数据,而不仅仅是字符串。
V1.4.3 新增用法NEW data(obj) 可传入key-value形式的数据。
参数:
key String
存储的数据名.
key,value String,Any
key:存储的数据名
value:将要存储的任意数据
obj object
一个用于设置数据的键/值对
data()
说明:
在一个div上存取数据
$("div").data("blah"); // undefined
$("div").data("blah", "hello"); // blah设置为hello
$("div").data("blah"); // hello
$("div").data("blah", 86); // 设置为86
$("div").data("blah"); // 86
$("div").removeData("blah"); //移除blah
$("div").data("blah"); // undefined
在一个div上存取名/值对数据
$("div").data("test", { first: 16, last: "pizza!" });
$("div").data("test").first //16;
$("div").data("test").last //pizza!;
removeData([name|list])
概述:
在元素上移除存放的数据与$(...).data(name, value)函数作用相反
参数:
[name] String
存储的数据名
[list] Array,String
移除数组或以空格分开的字符串
说明
从元素中删除之前添加的数据:
$("#btn2").click(function(){
$("div").removeData("greeting");
alert("Greeting is: " + $("div").data("greeting"));
});
测试:
data() 方法向被选元素附加数据,或者从被选元素获取数据。
$("#btn1").click(function(){
$("div").data("greeting", "Hello World");
});
$("#btn2").click(function(){
alert($("div").data("greeting"));
});
(function ($) {
function init(target) {
var t = $(target),
state = $.data(target, 'gridsub'),
key = state.options.key;
var editIndex = undefined;
function endEditing() {
if (editIndex == undefined) { return true }
if (t.datagrid('validateRow', editIndex)) {
var ed = t.datagrid('getEditor', { index: editIndex, field: key });
t.datagrid('endEdit', editIndex);
editIndex = undefined;
return true;
} else {
return false;
}
}
t.datagrid({
title: state.options.title,
width: state.options.width,
onClickRow: function (index) {
if (endEditing()) {
t.datagrid('selectRow', index)
.datagrid('beginEdit', index);
editIndex = index;
} else {
t.datagrid('selectRow', editIndex);
}
},
rownumbers: state.options.rownumbers,
singleSelect: state.options.singleSelect,
toolbar: state.options.toolbar,
pagination: state.options.pagination,
columns: state.options.columns,
data: state.options.data,
});
$(state.options.toolbar).find("a.add").on("click", function (e) {
if (endEditing()) {
t.datagrid('appendRow', {});
editIndex = t.datagrid('getRows').length - 1;
t.datagrid('selectRow', editIndex).datagrid('beginEdit', editIndex);
}
});
$(state.options.toolbar).find("a.save").on("click", function (e) {
if (t.datagrid('validateRow', editIndex)) {
var ed = t.datagrid('getEditor', { index: editIndex, field: key });
t.datagrid('endEdit', editIndex);
t.datagrid('acceptChanges');
var rows = t.datagrid('getSelected');
t.datagrid("updateRow", rows);
}
});
$(state.options.toolbar).find("a.del").on("click", function (e) {
var rows = t.datagrid('getSelected');
var editIndex = t.datagrid("getRowIndex", rows);
if (!rows) {
$Core.UI.message.warning("请选择一条数据"); return false;
}
t.datagrid('cancelEdit', editIndex).datagrid('deleteRow', editIndex);
editIndex = undefined;
});
$(state.options.toolbar).find("a.cancel").on("click", function (e) {
var row = t.datagrid('getSelected');
t.datagrid('endEdit', editIndex)
// if (!state.options.key) {
// t.datagrid('deleteRow', editIndex);
// }
editIndex = undefined;
});
}
// 插件的定义
$.fn.gridsub = function (options, param) {
if (typeof options == 'string') {
var method = $.fn.gridsub.methods[options];
if (method) {
return method(this, param);
}
}
return this.each(function () {
debugger;
var state = $.data(this, "gridsub");
if (state) {
$.extend(state.options, options);
} else {
$.data(this, "gridsub",
{
options: $.extend(true, {}, $.fn.gridsub.defaults, options)
});
}
init(this);
});
};
$.fn.gridsub.methods = {
getRows: function (jq) {
return $(jq[0]).datagrid("getRows");
},
load: function (jq, value) {
return $(jq[0]).datagrid({ data: value });
}
};
// 插件的defaults
$.fn.gridsub.defaults = {
title: '',
width: 300,
//onClickRow: state.onClickRow,
rownumbers: false,
singleSelect: false,
// toolbar: state.toolbar,
pagination: false,
columns: [],
data: [],
};
// 闭包结束
})(jQuery);
$("#dglist2").gridsub({
title: '设备',
width: 1200,
key: "id",
rownumbers: false,
singleSelect: true,
toolbar: ".btn_tool2",
pagination: false,
columns: [[ ]],
});
this中没有gridsub的属性,通过$.data向元素附加数据
.jquery target() event.target
target 属性规定哪个 DOM 元素触发了该事件。
$("p, button, h1, h2").click(function(event){
$("div").html("Triggered by a " + event.target.nodeName + " element.");
});
//当点击p标签的时候显示:点击事件由 P 元素触发
drawPoint.type["onClick"] = function(point, e){
Leak.showInfoWindow(point)
}
marker = new AMap.Marker(pointOpitons);
mPoint.marker = marker;
if(mPoint.type.onClick && $.isFunction(mPoint.type.onClick)) {
marker.on('click',function(e){
mPoint.type.onClick(e.target.getExtData(),null);
}); //点事件的获取
}
jquery源码
function dataAttr(elem, key, data) {
// If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute
if (data === undefined && elem.nodeType === 1) {
var name = "data-" + key.replace(rmultiDash, "-$1").toLowerCase();
data = elem.getAttribute(name);
if (typeof data === "string") {
try {
data = data === "true" ? true :
data === "false" ? false :
data === "null" ? null :
// Only convert to a number if it doesn't change the string
+data + "" === data ? +data :
rbrace.test(data) ? jQuery.parseJSON(data) :
data;
} catch (e) { }
// Make sure we set the data so it isn't changed later
jQuery.data(elem, key, data);
} else {
data = undefined;
}
}
return data;
}
function internalData(elem, name, data, pvt /* Internal Use Only */) {
if (!jQuery.acceptData(elem)) {
return;
}
var ret, thisCache,
internalKey = jQuery.expando,
// We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode = elem.nodeType,
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
cache = isNode ? jQuery.cache : elem,
// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id = isNode ? elem[internalKey] : elem[internalKey] && internalKey;
// Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
if ((!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string") {
return;
}
if (!id) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if (isNode) {
id = elem[internalKey] = deletedIds.pop() || jQuery.guid++;
} else {
id = internalKey;
}
}
if (!cache[id]) {
// Avoid exposing jQuery metadata on plain JS objects when the object
// is serialized using JSON.stringify
cache[id] = isNode ? {} : { toJSON: jQuery.noop };
}
// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
if (typeof name === "object" || typeof name === "function") {
if (pvt) {
cache[id] = jQuery.extend(cache[id], name);
} else {
cache[id].data = jQuery.extend(cache[id].data, name);
}
}
thisCache = cache[id];
// jQuery data() is stored in a separate object inside the object's internal data
// cache in order to avoid key collisions between internal data and user-defined
// data.
if (!pvt) {
if (!thisCache.data) {
thisCache.data = {};
}
thisCache = thisCache.data;
}
if (data !== undefined) {
thisCache[jQuery.camelCase(name)] = data;
}
// Check for both converted-to-camel and non-converted data property names
// If a data property was specified
if (typeof name === "string") {
// First Try to find as-is property data
ret = thisCache[name];
// Test for null|undefined property data
if (ret == null) {
// Try to find the camelCased property
ret = thisCache[jQuery.camelCase(name)];
}
} else {
ret = thisCache;
}
return ret;
}
function internalRemoveData(elem, name, pvt) {
if (!jQuery.acceptData(elem)) {
return;
}
var thisCache, i,
isNode = elem.nodeType,
// See jQuery.data for more information
cache = isNode ? jQuery.cache : elem,
id = isNode ? elem[jQuery.expando] : jQuery.expando;
// If there is already no cache entry for this object, there is no
// purpose in continuing
if (!cache[id]) {
return;
}
if (name) {
thisCache = pvt ? cache[id] : cache[id].data;
if (thisCache) {
// Support array or space separated string names for data keys
if (!jQuery.isArray(name)) {
// try the string as a key before any manipulation
if (name in thisCache) {
name = [name];
} else {
// split the camel cased version by spaces unless a key with the spaces exists
name = jQuery.camelCase(name);
if (name in thisCache) {
name = [name];
} else {
name = name.split(" ");
}
}
} else {
// If "name" is an array of keys...
// When data is initially created, via ("key", "val") signature,
// keys will be converted to camelCase.
// Since there is no way to tell _how_ a key was added, remove
// both plain key and camelCase key. #12786
// This will only penalize the array argument path.
name = name.concat(jQuery.map(name, jQuery.camelCase));
}
i = name.length;
while (i--) {
delete thisCache[name[i]];
}
// If there is no data left in the cache, we want to continue
// and let the cache object itself get destroyed
if (pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache)) {
return;
}
}
}
// See jQuery.data for more information
if (!pvt) {
delete cache[id].data;
// Don't destroy the parent cache unless the internal data object
// had been the only thing left in it
if (!isEmptyDataObject(cache[id])) {
return;
}
}
// Destroy the cache
if (isNode) {
jQuery.cleanData([elem], true);
// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
/* jshint eqeqeq: false */
} else if (support.deleteExpando || cache != cache.window) {
/* jshint eqeqeq: true */
delete cache[id];
// When all else fails, null
} else {
cache[id] = null;
}
}
jQuery.extend({
cache: {},
// The following elements (space-suffixed to avoid Object.prototype collisions)
// throw uncatchable exceptions if you attempt to set expando properties
noData: {
"applet ": true,
"embed ": true,
// ...but Flash objects (which have this classid) *can* handle expandos
"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
},
hasData: function (elem) {
elem = elem.nodeType ? jQuery.cache[elem[jQuery.expando]] : elem[jQuery.expando];
return !!elem && !isEmptyDataObject(elem);
},
data: function (elem, name, data) {
return internalData(elem, name, data);
},
removeData: function (elem, name) {
return internalRemoveData(elem, name);
},
// For internal use only.
_data: function (elem, name, data) {
return internalData(elem, name, data, true);
},
_removeData: function (elem, name) {
return internalRemoveData(elem, name, true);
}
});
jQuery.fn.extend({
data: function (key, value) {
var i, name, data,
elem = this[0],
attrs = elem && elem.attributes;
// Special expections of .data basically thwart jQuery.access,
// so implement the relevant behavior ourselves
// Gets all values
if (key === undefined) {
if (this.length) {
data = jQuery.data(elem);
if (elem.nodeType === 1 && !jQuery._data(elem, "parsedAttrs")) {
i = attrs.length;
while (i--) {
// Support: IE11+
// The attrs elements can be null (#14894)
if (attrs[i]) {
name = attrs[i].name;
if (name.indexOf("data-") === 0) {
name = jQuery.camelCase(name.slice(5));
dataAttr(elem, name, data[name]);
}
}
}
jQuery._data(elem, "parsedAttrs", true);
}
}
return data;
}
// Sets multiple values
if (typeof key === "object") {
return this.each(function () {
jQuery.data(this, key);
});
}
return arguments.length > 1 ?
// Sets one value
this.each(function () {
jQuery.data(this, key, value);
}) :
// Gets one value
// Try to fetch any internally stored data first
elem ? dataAttr(elem, key, jQuery.data(elem, key)) : undefined;
},
removeData: function (key) {
return this.each(function () {
jQuery.removeData(this, key);
});
}
});