2008-10-27 96 views
23

我正在研究一个大部分使用JavaScript构建的繁琐的Web界面。它基本上是一个非常大的形式,有很多部分。每个部分都是基于表单其他部分的选项构建的。每当这些选项发生变化时,新值将在“注册表”类型对象中记录下来,其他部分将相应地重新填充。是否有可能在JavaScript中侦听对象属性的更改?

让许多表单字段上的事件侦听器开始减慢速度,并且刷新整个表单对于每个更改对于用户来说太重/太慢。

我想知道是否有可能将侦听器添加到注册表对象的属性,而不是表单元素,以加快一点?如果是这样,你能提供/指向我一些示例代码吗?

更多信息:

  • 这是jQuery的一个插件,这样我就可以建立,从该库的任何功能将是有益的,但不是必需的。
  • 我们的用户使用IE6/7,Safari和FF2/3,所以如果有可能,但只适用于“现代”浏览器,我将不得不寻找不同的解决方案。

回答

6

感谢您的意见家伙。我已经走了下列要求:

var EntriesRegistry = (function(){ 

    var instance = null; 

    function __constructor() { 

     var 
      self = this, 
      observations = {}; 

     this.set = function(n,v) 
     { 
      self[n] = v; 

      if(observations[n]) 
       for(var i=0; i < observations[n].length; i++) 
        observations[n][i].apply(null, [v, n]); 

     } 

     this.get = function(n) 
     { 
      return self[n]; 
     } 

     this.observe = function(n,f) 
     { 

      if(observations[n] == undefined) 
       observations[n] = []; 

      observations[n].push(f); 
     } 

    } 

    return new function(){ 
     this.getInstance = function(){ 
      if (instance == null) 
      { 
       instance = new __constructor(); 
       instance.constructor = null; 
      } 
      return instance; 
     } 
    } 
})(); 

var entries = EntriesRegistry.getInstance(); 

var test = function(v){ alert(v); }; 

entries.set('bob', 'meh'); 

entries.get('bob'); 

entries.observe('seth', test); 

entries.set('seth', 'dave'); 

以板载您的意见,我将使用的表单对象事件代表团来更新注册表并触发登记的观察方法。

到目前为止,这对我来说效果不错......你们可以看到这个问题吗?

2

你可以侦听器附加到一个容器(主体或形式),然后使用事件参数来对变化起反应。你得到了所有听者的善良,但只需要为容器添加一个,而不是每个元素添加一个。

$('body').change(function(event){ 
    /* do whatever you want with event.target here */ 
    console.debug(event.target); /* assuming firebug */ 
}); 

event.target包含被点击的元素。

SitePoint有此事件代表团的一个很好的解释:

JavaScript事件代表团是由你为了避免将事件处理程序添加到多添加一个事件处理程序的父元素的简单方法子元素。

1

Mozilla引擎浏览器支持Object.watch,但我不知道跨浏览器兼容的等价物。

你是否用Firebug分析了该页面,以了解究竟是什么导致了缓慢,或者“很多事件处理程序”是猜测?

6

据我所知,没有事件触发对象属性的变化(编辑:除了,显然,Object.watch)。

为什么不尽可能使用事件代表团?也就是说,形式上的事件而不是单个形式的元素,捕捉事件的泡沫?

例如(我的jQuery是生疏了,请原谅我使用的原型,而不是,但我敢肯定,你就可以很容易地适应它):

$(form).observe('change', function(e) { 
    // To identify changed field, in Proto use e.element() 
    // but I think in jQuery it's e.target (as it should be) 
}); 

您还可以捕获inputkeyuppaste事件如果您希望它在文本字段失去焦点之前触发。我对这个解决方案通常是:

  1. 壁虎/基于Webkit的浏览器:form观察input
  2. 此外,在基于Webkit的浏览器:观察textarea小号keyuppaste事件(他们不因某些原因解雇inputtextarea S)。
  3. IE:form
  4. 观察keyuppaste(上select s此火灾)观察在formchange
  5. 对于keyuppaste事件,通过比较文本字段的valuedefaultValue

编辑比较反对它的默认值的字段的当前值(什么它的价值是,当加载页面):这是我公司开发的示例代码为了防止未经修饰的形式提交和类似:

What is the best way to track changes in a form via javascript?

+0

Object.observe()已被弃用。尽量避免为了你自己的利益尽可能地使用它。 – andersfylling 2016-05-04 21:13:14

0

jQuery的仅仅是惊人的。尽管你可以看看ASP.NET AJAX Preview。

某些功能只是.js文件,不依赖于.NET。可能你会发现有用的观察者模式的实现。

var o = { foo: "Change this string" }; 

Sys.Observer.observe(o); 

o.add_propertyChanged(function(sender, args) { 
    var name = args.get_propertyName(); 
    alert("Property '" + name + "' was changed to '" + sender[name] + "'."); 
}); 

o.setValue("foo", "New string value."); 

此外,客户端模板已准备好用于一些有趣的场景。

最后需要说明,这是使用jQuery(不带$的问题)完全兼容

链接:Home pageVersion I currently use

0

我正在寻找同样的事情,hitted你的问题......没有答案的满足我的需求,所以我想出了这个解决方案,我想与大家分享:

var ObservedObject = function(){ 
    this.customAttribute = 0 
    this.events = {} 
    // your code... 
} 
ObservedObject.prototype.changeAttribute = function(v){ 
    this.customAttribute = v 
    // your code... 
    this.dispatchEvent('myEvent') 
} 
ObservedObject.prototype.addEventListener = function(type, f){ 
    if(!this.events[type]) this.events[type] = [] 
    this.events[type].push({ 
     action: f, 
     type: type, 
     target: this 
    }) 
} 
ObservedObject.prototype.dispatchEvent = function(type){ 
    for(var e = 0; e < this.events[type].length; ++e){ 
     this.events[type][e].action(this.events[type][e]) 
    } 
} 
ObservedObject.prototype.removeEventListener = function(type, f){ 
    if(this.events[type]) { 
     for(var e = 0; e < this.events[type].length; ++e){ 
      if(this.events[type][e].action == f) 
       this.events[type].splice(e, 1) 
     } 
    } 
} 

var myObj = new ObservedObject() 

myObj.addEventListener('myEvent', function(e){// your code...}) 

它的简化DOM Events API并且工作得很好! 这里是一个更完整的example

1

小修改以前的答案:由观察到的代码移动到一个对象,一个可以让一个抽象出来,并用它来与jQuery的扩展方法扩展其他对象。

ObservableProperties = { 
    events : {}, 
    on : function(type, f) 
    { 
     if(!this.events[type]) this.events[type] = []; 
     this.events[type].push({ 
      action: f, 
      type: type, 
      target: this 
     }); 
    }, 
    trigger : function(type) 
    { 
     if (this.events[type]!==undefined) 
     { 
      for(var e = 0, imax = this.events[type].length ; e < imax ; ++e) 
      { 
       this.events[type][e].action(this.events[type][e]); 
      } 
     } 
    }, 
    removeEventListener : function(type, f) 
    { 
     if(this.events[type]) 
     { 
      for(var e = 0, imax = this.events[type].length ; e < imax ; ++e) 
      { 
       if(this.events[type][e].action == f) 
        this.events[type].splice(e, 1); 
      } 
     } 
    } 
}; 
Object.freeze(ObservableProperties); 

var SomeBusinessObject = function(){ 
    self = $.extend(true,{},ObservableProperties); 
    self.someAttr = 1000 
    self.someMethod = function(){ 
     // some code 
    } 
    return self; 
} 

见琴:https://jsfiddle.net/v2mcwpw7/3/

+0

有人可能会争辩说,我们可以通过执行`$ .extend(true,this,ObservableProperties)'将'ObservableProperties`对象直接绑定到业务对象;` 它看起来更好。但是,请注意范围。当我做一些与范围有关的事情时(或者单身人士),我使用`self`变量,否则如果一切都是公开的,我会用`this`去。请参阅[this fiddle](https://jsfiddle.net/empx6z58/) – 2016-01-14 12:32:32

相关问题