1

我为我正在处理的项目编写了以下代码:

var clicky_tracking = [
  ['related-searches', 'Related Searches'],
  ['related-stories', 'Related Stories'],
  ['more-videos', 'More Videos'],
  ['web-headlines', 'Publication']
];

for (var x = 0, length_x = clicky_tracking.length; x < length_x; x++) {
  links = document.getElementById(clicky_tracking[x][0])
                  .getElementsByTagName('a');
  for (var y = 0, length_y = links.length; y < length_y; y++) {
    links[y].onclick = (function(name, url) {
      return function() {
        clicky.log(url, name, 'outbound');
      };
    }(clicky_tracking[x][1], links[y].href));
  }
}

我想做的是:

  • 定义一个二维数组,每个实例的内部数组包含两个元素:一个id属性值(例如,“相关搜索”)和相应的描述(例如,“相关搜索”);
  • 对于每个内部数组,找到document具有相应id属性的元素,然后收集其中所有<a>元素(超链接)的集合;
  • 循环遍历该集合并将onclick处理程序附加到每个应该调用的超链接,clicky.log作为参数传入与“相关搜索”对应的描述id(例如,“相关搜索”的id“相关搜索”)和元素的href属性值<a>被点击了。

希望这不是完全混乱!代码可能比这更不言自明。

我相信我在这里实现的是一个闭包,但是 JSLint 抱怨:

http://img.skitch.com/20100526-k1trfr6tpj64iamm8r4jf5rbru.png

所以,我的问题是:

  • 我怎样才能重构这段代码以使 JSLint 符合要求?或者,更好的是,无论 JSLint 怎么想,是否有一种我错过的最佳实践方法?
  • 我应该改用事件委托吗?也就是说,将onclick事件处理程序附加到具有我数组document中的属性的元素id,然后查看event.target? 我以前做过一次并且理解了这个理论,但是我对细节很模糊,并且希望得到一些关于它是什么样子的指导——假设这是一种可行的方法。

非常感谢您的帮助!

4

3 回答 3

1

这段代码不是很容易维护!我讨厌把 jQuery 塞进你的喉咙,但这看起来像是对你非常有用的情况,比如:

$('a.trackable').click(function(e) {

  clicky.log(url, name, 'outbound');
};

您可以通过向每个链接添加类'trackable' 来启用跟踪,并使用例如$(this).attr('rel') 将链接映射到查找表。

希望这是有道理的。

于 2010-05-26T05:55:49.530 回答
1

您可以创建一个函数来构建事件处理程序,例如:

function createClickHandler(url, name) {
  return function () {
    clicky.log(url, name, 'outbound');
  };
}

for (var x = 0, length_x = clicky_tracking.length; x < length_x; x++) {
  links = document.getElementById(clicky_tracking[x][0]) // NOTE:links should be 
                  .getElementsByTagName('a');            // declared at the top
  for (var y = 0, length_y = links.length; y < length_y; y++) {
    links[y].onclick = createClickHandler(clicky_tracking[x][1], links[y].href);
  }
}

我也认为事件委托也是一个很好的选择,你可以很容易地实现它:

var clicky_tracking = [
  ['related-searches', 'Related Searches']
  //...
], elem;

function createClickHandler(name) { // capture only the 'name' variable
  return function (e) {
    e = e || window.event; // cross-browser way to get the event object
    var target = e.target || e.srcElement; // and the event target

    if (target.nodeName == "A") { // make sure that the target is an anchor
      clicky.log(target.href, name, 'outbound');
    }
  };
}

for (var x = 0, len = clicky_tracking.length; x < len; x++) {
  elem = document.getElementById(clicky_tracking[x][0]); // find parent element
  elem.onclick = createClickHandler(clicky_tracking[x][1]); // bind the event
}
​
于 2010-05-26T05:58:22.793 回答
1

委派是一种更好的方法。JSLint 抱怨是因为您每次都在循环中创建一个新函数。但是,与其在文档上设置一个事件来监听所有点击事件,我宁愿在所有分配了 id 的单个根元素上设置一个处理程序。可以为所有这些元素重用一个处理程序。

function logClick(event) {
    event = event || window.event;
    var link = event.target || event.srcElement;

    if(link.nodeName.toLowerCase() !== "a") {
        return;
    }

    var name = clicky_tracking[this.id];
    clicky.log(link.href, name, 'outbound');
}

向每个根元素注册上述处理程序。

for(var id in clicky_tracking) {
    var root = document.getElementById(id);
    root.onclick = logClick;
}

另外为了避免在数组中搜索,我clicky_tracking已从数组更改为对象,以便更轻松地进行键控访问。

var clicky_tracking = {
  'related-searches': 'Related Searches',
  'related-stories': 'Related Stories',
  'more-videos': 'More Videos',
  'web-headlines': 'Publication'
};
于 2010-05-26T06:06:10.760 回答