7

这总是让我着迷。初始化网页上所有可爱的 UI 元素后,我加载了一些内容(例如,模式或选项卡),新加载的内容没有初始化 UI 元素。例如:

$('a.button').button(); // jquery ui button as an example
$('select').chosen(); // chosen ui as another example
$('#content').load('/uri'); // content is not styled :(

我目前的方法是创建需要绑定的元素注册表:

var uiRegistry = {
  registry: [],
  push: function (func) { this.registry.push(func) },
  apply: function (scope) {
    $.each(uiRegistry.registry, function (i, func) {
      func(scope);
    });
  }
};

uiRegistry.push(function (scope) {
  $('a.button', scope).button();
  $('select', scope).chosen();
});

uiRegistry.apply('body'); // content gets styled as per usual

$('#content').load('/uri', function () {
  uiRegistry.apply($(this)); // content gets styled :)
});

我不能是唯一有这个问题的人,那么有没有更好的模式来做到这一点?

4

2 回答 2

1

我的回答与你概述的基本相同,但我使用 jquery 事件来触发设置代码。我称之为“moddom”事件。

当我加载新内容时,我会在父级上触发我的事件:

parent.append(newcode).trigger('moddom');

在小部件中,我查找该事件:

$.on('moddom', function(ev) {
  $(ev.target).find('.myselector')
})

为了说明事件方法,这过于简单化了。

实际上,我将它包装在一个函数 domInit 中,该函数接受一个选择器和一个回调参数。每当找到与选择器匹配的新元素时,它都会调用回调 - 使用 jquery 元素作为第一个参数。

所以在我的小部件代码中,我可以这样做:

domInit('.myselector', function(myelement) {
  myelement.css('color', 'blue');
})

domInit 在有问题的元素“domInit”上设置数据,该元素是已应用函数的注册表。

我的完整 domInit 函数:

window.domInit = function(select, once, callback) {
  var apply, done;
  done = false;
  apply = function() {
    var applied, el;
    el = $(this);
    if (once && !done) {
      done = true;
    }
    applied = el.data('domInit') || {};
    if (applied[callback]) {
      return;
    }
    applied[callback] = true;
    el.data('domInit', applied);
    callback(el);
  };
  $(select).each(apply);
  $(document).on('moddom', function(ev) {
    if (done) {
      return;
    }
    $(ev.target).find(select).each(apply);
  });
};

现在我们只需要记住在进行 dom 更改时触发 'moddom' 事件。

如果您不需要“一次”功能,您可以简化这一点,这是一种非常罕见的边缘情况。它只调用一次回调。例如,如果您要在找到任何匹配的元素时执行全局操作 - 但它只需要发生一次。没有 done 参数的简化:

window.domInit = function(select, callback) {
  var apply;
  apply = function() {
    var applied, el;
    el = $(this);
    applied = el.data('domInit') || {};
    if (applied[callback]) {
      return;
    }
    applied[callback] = true;
    el.data('domInit', applied);
    callback(el);
  };
  $(select).each(apply);
  $(document).on('moddom', function(ev) {
    $(ev.target).find(select).each(apply);
  });
};

在我看来,浏览器应该有办法在 dom 更改时接收回调,但我从未听说过这样的事情。

于 2013-02-25T19:25:10.203 回答
0

最好的方法是将所有 ui 代码包装在一个函数中 - 甚至更好的是一个单独的文件 - 在 ajax 加载时只需将该函数指定为回调.. 这是一个小例子

假设您有将带有类的文本字段绑定someclass-for-date到日期选择器的代码,那么您的代码将如下所示..

$('.someclass-for-date').datepicker();

这是我认为最好的

function datepickerUi(){
    $('.someclass-for-date').datepicker();
}

这就是负载的样子

$('#content').load('/uri', function(){

    datepickerUi();

})

或者您可以在脚本标签中的 html 末尾加载它..(但我不喜欢那样,因为它更难调试)

这里有一些提示

保持你的代码和css样式尽可能的干净..这意味着对于应该是日期选择器的文本字段,在你的网站上给他们一个类..按照这个速度,你的所有代码都将是干净且易于维护的..

阅读有关 OOCss 的更多信息,这将清楚我的意思。

主要是使用jquery,这完全是关于组织......考虑一下,你会用一行代码完成你想要完成的事情......

编辑

这是一个与您类似的js小提琴,但我想它更干净点击这里

于 2013-02-25T19:04:28.683 回答