2008-10-27 49 views
23

Tôi đang làm việc trên một giao diện web khó sử dụng được xây dựng bằng JavaScript. Về cơ bản một (rất) hình thức lớn với nhiều phần. Mỗi phần được xây dựng dựa trên các tùy chọn từ các phần khác của biểu mẫu. Bất cứ khi nào các tùy chọn này thay đổi các giá trị mới được ghi chú trong đối tượng kiểu "đăng ký" và các phần khác sẽ được điền lại tương ứng.Có thể nghe các thay đổi đối với thuộc tính của đối tượng trong JavaScript không?

Có trình xử lý sự kiện trên nhiều trường biểu mẫu bắt đầu làm chậm mọi thứ và làm mới toàn bộ biểu mẫu cho mỗi thay đổi sẽ quá nặng/chậm đối với người dùng.

Tôi tự hỏi liệu có thể thêm người nghe vào thuộc tính của đối tượng đăng ký thay vì các thành phần biểu mẫu để tăng tốc độ lên một chút không? Và, nếu có, bạn có thể cung cấp/chỉ cho tôi một số mã mẫu không?

Thông tin thêm:

  • Đây là một plug-in cho jQuery, vì vậy bất kỳ chức năng tôi có thể xây dựng-on từ thư viện mà sẽ là hữu ích nhưng không cần thiết.
  • Người dùng của chúng tôi đang sử dụng IE6/7, Safari và FF2/3, vì vậy nếu có thể nhưng chỉ cho các trình duyệt "hiện đại", tôi sẽ phải tìm một giải pháp khác.

Trả lời

6

Thanks for the guys ý kiến. Tôi đã thực hiện theo các bước sau:

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'); 

Tham gia nhận xét của bạn, tôi sẽ sử dụng ủy quyền sự kiện trên đối tượng biểu mẫu để cập nhật sổ đăng ký và kích hoạt các phương pháp quan sát đã đăng ký.

Tính năng này hiện đang hoạt động tốt cho tôi ... các bạn có thấy bất kỳ sự cố nào với vấn đề này không?

2

Bạn có thể đính kèm người nghe vào vùng chứa (phần thân hoặc biểu mẫu) và sau đó sử dụng tham số sự kiện để phản ứng với thay đổi. Bạn nhận được tất cả lòng tốt của người nghe nhưng chỉ phải đính kèm một cái cho vùng chứa thay vì một cho mỗi phần tử.

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

Event.target giữ phần tử được nhấp vào.

SitePoint có một lời giải thích tốt đẹp ở đây đoàn sự kiện:

Javascript đoàn sự kiện là một kỹ thuật đơn giản mà bạn có thêm một xử lý sự kiện duy nhất để một yếu tố phụ huynh để tránh phải thêm xử lý sự kiện cho nhiều yếu tố con.

1

Trình duyệt động cơ Mozilla hỗ trợ Object.watch, nhưng tôi không biết tương đương trình duyệt chéo tương thích.

Bạn đã lược tả trang bằng Firebug để có ý tưởng chính xác điều gì gây ra sự chậm chạp, hoặc là "rất nhiều trình xử lý sự kiện" có phải là phỏng đoán không?

6

Theo như tôi biết, không có sự kiện nào được kích hoạt khi thay đổi thuộc tính đối tượng (chỉnh sửa: ngoại trừ, hiển nhiên, đối với Object.watch).

Tại sao không sử dụng đoàn sự kiện bất cứ khi nào có thể? Đó là, các sự kiện trên biểu mẫu thay vì trên các phần tử biểu mẫu riêng lẻ, nắm bắt các sự kiện khi chúng bong bóng lên?

Ví dụ (jQuery của tôi là Rusty, tha thứ cho tôi sử dụng Prototype thay vào đó, nhưng tôi chắc chắn bạn sẽ có thể thích ứng với nó một cách dễ dàng):

$(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) 
}); 

Bạn cũng có thể chụp inputkeyuppaste sự kiện nếu bạn muốn nó kích hoạt trên các trường văn bản trước khi chúng bị mất tiêu điểm.Giải pháp của tôi cho điều này thường là:

  1. Gecko/Webkit dựa trên trình duyệt: quan sát input trên form.
  2. Cũng trong trình duyệt Webkit dựa trên: quan sát keyuppaste sự kiện trên textarea s (họ không bắn input trên textarea s đối với một số lý do).
  3. IE: quan sát keyuppaste trên form
  4. Quan sát change trên form (cháy này trên select s).
  5. Đối keyuppaste sự kiện, so sánh giá trị hiện tại của một lĩnh vực chống lại mặc định của nó (những gì giá trị của nó là khi trang đã được nạp) bằng cách so sánh một trường text value để nó defaultValue

Edit: Đây là mã ví dụ tôi phát triển để ngăn ngừa trình nguyên bản từ www.phpbb.com và những thứ tương tự:

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

+0

Object.observe() đã bị phản đối. Cố gắng tránh sử dụng nó càng nhiều càng tốt vì lợi ích của chính bạn. – andersfylling

0

jQuery chỉ là tuyệt vời. Mặc dù bạn có thể xem qua ASP.NET AJAX Preview.

Một số tính năng chỉ là tệp .js, không phụ thuộc với .NET. Có thể bạn có thể tìm thấy việc triển khai mẫu quan sát hữu ích.

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."); 

Ngoài ra, mẫu bên ứng dụng sẵn sàng sử dụng cho một số trường hợp thú vị.

Một lưu ý cuối cùng, đây là hoàn toàn tương thích với jQuery (không phải vấn đề với $)

Links: Home page, Version I currently use

0

tôi đang tìm kiếm điều tương tự và hitted câu hỏi của bạn ... không ai trong số các câu trả lời thỏa mãn nhu cầu của tôi vì vậy tôi đã đưa ra giải pháp này mà tôi muốn chia sẻ:

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...}) 

Đó là một đơn giản hóa API sự kiện DOM và hoạt động tốt! Đây là một hoàn chỉnh hơn example

1

Sửa đổi nhỏ cho câu trả lời trước đó: bằng cách di chuyển mã quan sát đến một đối tượng, người ta có thể tạo ra một trừu tượng và sử dụng nó để mở rộng các đối tượng khác với phương pháp mở rộng của 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; 
} 

Xem fiddle: https://jsfiddle.net/v2mcwpw7/3/

+0

Người ta có thể lập luận rằng chúng ta có thể ràng buộc đối tượng 'ObservableProperties' trực tiếp với đối tượng nghiệp vụ bằng cách thực hiện' $ .extend (true, this, ObservableProperties); ' Nó trông đẹp hơn. Tuy nhiên, hãy cẩn thận về phạm vi. Tôi sử dụng một 'self'variable khi tôi làm những điều phức tạp một chút với phạm vi (hoặc Singleton cho vấn đề đó), nếu không, nếu mọi thứ đều công khai, tôi sẽ đi với' this'. Xem [this fiddle] (https://jsfiddle.net/empx6z58/) –

Các vấn đề liên quan