(jQuery)使用extend()访问自定义属性时出现问题

时间:2019-05-19 22:38:49

标签: javascript jquery

我已经为jquery div元素分配了一个名为name的自定义属性。我可以使用div1.name手动访问该属性,但无法通过使用$(this)的鼠标事件来访问它。

  var div1 = $('<div></div>');
  div1.css("width", "100px");
  div1.css("height", "100px");
  div1.css("background-color", "red");
  div1.mouseover(sayName);
  $('body').append(div1);

  var div2 = $('<div></div>');
  div2.css("width", "100px");
  div2.css("height", "100px");
  div2.css("background-color", "green");
  div2.mouseover(sayName);
  $('body').append(div2);

  div1.extend({"name":"Red"});
  div2.extend({"name":"Green"});

  function sayName() {
    console.log(div1.name); // prints Red
    console.log(div2.name); // prints Green
    console.log($(this).name); // prints undefined
  }

我需要一种使用$(this)访问名称的方法

1 个答案:

答案 0 :(得分:1)

您无法尝试执行的操作,因为您将name属性设置为特定的jQuery实例,而每次调用$(this)都会创建一个新实例,尽管它包含相同的HTML元素。

相反,您可以做的是使用getter / setter组合获取/设置data-*属性:

/* Expand jQuery.fn to have the 'name' property. */
Object.defineProperty($.fn, "name", {
  get: function () {
    /* Return the value of the first element's 'data-name' attribute. */
    return this[0].dataset.name;
  },
  set: function (value) {
    /* Iterate over every element in the context. */
    for (var i = 0; i < this.length; i++) {
      /* Set the value as the value of the element's 'data-name' attribute. */
      this[i].dataset.name = value;
    };
  }
});

$(function () {
  /* Set the 'name' property of the element (sets 'data-name'). */
  $("#element").name = "Fancy Div";
  
  /* Get the value of the 'name' property (gets 'data-name'). */
  console.log($("#element").name);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "element"></div>


通常,由于您通常希望以这种方式添加多个属性,因此以下是一个封装了此功能的快速插件:

/* Create a method that can set properties as described. */
$.fn.set = function (property, value) {
  /* Create the object that will contain the given property/ies. */
  var obj = (typeof property == "object") ? {...property || {}} : {[property]: value};
  
  /* Iterate over every property in the given object. */
  for (let property in obj) {
    /* Check whether the property doesn't already exist. */
    if (!(property in $.fn)) {
      /* Expand jQuery.fn to have the 'name' property. */
      Object.defineProperty($.fn, property, {
        get: function () {
          /* Return the value of the first element's data-* attribute. */
          return this[0].dataset[property];
        },
        set: function (value) {
          /* Set the value of every element's data-* attribute. */
          this.each(index => this[index].dataset[property] = value);
        }
      });
    }

    /* Update the property with the new value. */
    this[property] = obj[property];
  }
  
  /* Return the context. */
  return this;
};


$(function () {
  /* Set some properties of the element. */
  $("#element")
    .set("name", "Fancy Div")
    .set({type: "container", value: 0});
  
  /* Get some properties of the element. */
  console.log("name: " + $("#element").name);
  console.log("type: " + $("#element").type);
  console.log("value: " + $("#element").value);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "element"></div>