Giải thích xử lý sự kiện ExtJS 4


130

Gần đây tôi đã bắt đầu học ExtJS và gặp khó khăn trong việc hiểu cách xử lý Sự kiện. Tôi không có kinh nghiệm về bất kỳ phiên bản trước nào của ExtJS.

Từ việc đọc các hướng dẫn, hướng dẫn và trang tài liệu khác nhau, tôi đã tìm ra cách sử dụng nó, nhưng tôi không rõ về cách thức hoạt động của nó. Tôi đã tìm thấy một số hướng dẫn cho các phiên bản cũ hơn của ExtJS, nhưng tôi không chắc chúng có thể áp dụng như thế nào trong ExtJS 4.

Tôi đặc biệt tìm kiếm "từ cuối cùng" trên những thứ như

  • chức năng xử lý sự kiện nào được thông qua? Có một bộ lập luận chuẩn luôn được thông qua không?
  • Làm thế nào để xác định các sự kiện tùy chỉnh cho các thành phần tùy chỉnh chúng ta viết? Làm thế nào chúng ta có thể kích hoạt các sự kiện tùy chỉnh?
  • giá trị trả về (đúng / sai) có ảnh hưởng đến bong bóng sự kiện như thế nào không? Nếu không, làm thế nào chúng ta có thể kiểm soát sự kiện sủi bọt từ bên trong hoặc bên ngoài trình xử lý sự kiện?
  • Có một cách tiêu chuẩn để đăng ký người nghe sự kiện? (Bây giờ tôi đã bắt gặp hai cách khác nhau và tôi không chắc tại sao mỗi phương pháp được sử dụng).

Ví dụ, câu hỏi này khiến tôi tin rằng một người xử lý sự kiện có thể nhận được khá nhiều đối số. Tôi đã thấy các hướng dẫn khác trong đó chỉ có hai đối số cho trình xử lý. Các thay đổi?


2
Chỉ cần chú ý ... lạc đề?
jrharshath

12
88 câu trả lời cho câu hỏi, 155 câu trả lời cho câu trả lời đầu tiên và Andrew vĩ đại và hùng mạnh quyết định câu hỏi này không có chủ đề. Chuyến đi quyền lực nghiêm trọng đang diễn ra!
thuyền viên

3
Tôi đã bỏ phiếu để mở lại câu hỏi này vì câu trả lời ở đây là một mỏ vàng. Tôi đã chỉnh sửa câu hỏi để phù hợp hơn với phong cách Q và A.
dbrin

1
Vui lòng mở lại câu hỏi này vì nó thực sự hữu ích và là câu hỏi chính hãng. mù quáng đến mức chúng tôi không thể đóng nó.
Piyush Dholariya

2
Đây là một câu hỏi hay, và tôi thấy không có lý do gì để đóng nó. Gọi chủ đề này là vô lý. Bình chọn để mở lại.
Mike Fuchs

Câu trả lời:


222

Hãy bắt đầu bằng cách mô tả xử lý sự kiện của các phần tử DOM.

Xử lý sự kiện nút DOM

Trước hết bạn sẽ không muốn làm việc trực tiếp với nút DOM. Thay vào đó bạn có thể muốn sử dụng Ext.Elementgiao diện. Với mục đích gán các trình xử lý sự kiện Element.addListenerElement.on(chúng tương đương) đã được tạo. Vì vậy, ví dụ, nếu chúng ta có html:

<div id="test_node"></div>

và chúng tôi muốn thêm clickxử lý sự kiện.
Hãy lấy lại Element:

var el = Ext.get('test_node');

Bây giờ hãy kiểm tra tài liệu cho clicksự kiện. Trình xử lý của nó có thể có ba tham số:

nhấp (Ext.EventObject e, HTMLEuity t, Object eOpts)

Biết tất cả những thứ này, chúng ta có thể gán xử lý:

//       event name      event handler
el.on(    'click'        , function(e, t, eOpts){
  // handling event here
});

Xử lý sự kiện Widgets

Xử lý sự kiện Widgets khá giống với xử lý sự kiện các nút DOM.

Trước hết, xử lý sự kiện widget được thực hiện bằng cách sử dụng Ext.util.Observablemixin. Để xử lý các sự kiện đúng cách, tiện ích của bạn phải chống lại Ext.util.Observablenhư một mixin. Tất cả các tiện ích tích hợp (như Bảng điều khiển, Biểu mẫu, Cây, Lưới, ...) Ext.util.Observabletheo mặc định là một hỗn hợp.

Đối với các widget có hai cách gán trình xử lý. Cách thứ nhất - là sử dụng trên phương thức (hoặc addListener). Ví dụ, hãy tạo Buttonwidget và gán clicksự kiện cho nó. Trước hết, bạn nên kiểm tra tài liệu của sự kiện để biết các đối số của trình xử lý:

nhấp (Ext.button.Button this, Event e, Object eOpts)

Bây giờ hãy sử dụng on:

var myButton = Ext.create('Ext.button.Button', {
  text: 'Test button'
});
myButton.on('click', function(btn, e, eOpts) {
  // event handling here
  console.log(btn, e, eOpts);
});

Cách thứ hai là sử dụng cấu hình trình nghe của widget :

var myButton = Ext.create('Ext.button.Button', {
  text: 'Test button',
  listeners : {
    click: function(btn, e, eOpts) {
      // event handling here
      console.log(btn, e, eOpts);
    }
  }
});

Lưu ý rằng Buttonwidget là một loại vật dụng đặc biệt. Nhấp vào sự kiện có thể được chỉ định cho tiện ích này bằng cách sử dụng handlercấu hình:

var myButton = Ext.create('Ext.button.Button', {
  text: 'Test button',
  handler : function(btn, e, eOpts) {
    // event handling here
    console.log(btn, e, eOpts);
  }
});

Sự kiện tùy chỉnh bắn

Trước hết bạn cần đăng ký một sự kiện bằng phương thức addEvents :

myButton.addEvents('myspecialevent1', 'myspecialevent2', 'myspecialevent3', /* ... */);

Sử dụng addEventsphương pháp là tùy chọn. Như các bình luận cho phương pháp này nói rằng không cần sử dụng phương pháp này nhưng nó cung cấp chỗ cho tài liệu sự kiện.

Để khởi động sự kiện của bạn, hãy sử dụng phương thức fireEvent :

myButton.fireEvent('myspecialevent1', arg1, arg2, arg3, /* ... */);

arg1, arg2, arg3, /* ... */sẽ được chuyển vào xử lý. Bây giờ chúng tôi có thể xử lý sự kiện của bạn:

myButton.on('myspecialevent1', function(arg1, arg2, arg3, /* ... */) {
  // event handling here
  console.log(arg1, arg2, arg3, /* ... */);
});

Điều đáng nói là vị trí tốt nhất để chèn lệnh gọi phương thức addEventsinitComponentphương thức của widget khi bạn đang xác định widget mới:

Ext.define('MyCustomButton', {
  extend: 'Ext.button.Button',
  // ... other configs,
  initComponent: function(){
    this.addEvents('myspecialevent1', 'myspecialevent2', 'myspecialevent3', /* ... */);
    // ...
    this.callParent(arguments);
  }
});
var myButton = Ext.create('MyCustomButton', { /* configs */ });

Ngăn chặn sự kiện sủi bọt

Để ngăn chặn bong bóng, bạn có thể return falsehoặc sử dụng Ext.EventObject.preventDefault(). Để ngăn chặn hành động sử dụng mặc định của trình duyệt Ext.EventObject.stopPropagation().

Ví dụ: hãy gán trình xử lý sự kiện nhấp vào nút của chúng tôi. Và nếu không nhấp vào nút bên trái, ngăn hành động mặc định của trình duyệt:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});

3
Đây là lòng tham, nhưng có cách nào để thực hiện điều "addEvents" thông qua một số cấu hình không? :)
jrharshath

@jrharshath, theo như tôi biết, thật không may, không có cách nào để làm điều đó thông qua cấu hình.
Người đàn ông phân tử

Làm thế nào để người ta tạo ra những cái này -'myspecialevent1 ', tôi thấy bạn đã đính kèm và xử lý nó nhưng làm thế nào để chúng ta tạo ra chúng?
hey,

1
Câu trả lời rực rỡ! Tôi mới sử dụng ExtJ và đang tìm cách tham chiếu bất kỳ yếu tố nào trong trang và sử dụng các trình xử lý sự kiện trên chúng, giống như jQuery. Bạn đã dạy tôi! Cảm ơn!
Rutwick Gangurde

1
một chút lỗi trong phần "Ngăn chặn sự kiện sủi bọt". stopPropagation được sử dụng để ngăn chặn sự kiện sủi bọt và ngăn chặn Default được sử dụng để ngăn chặn hành vi / hành động mặc định.
MatRt

44

Bắn các sự kiện rộng ứng dụng

Cách làm cho bộ điều khiển nói chuyện với nhau ...

Ngoài câu trả lời rất hay ở trên, tôi muốn đề cập đến các sự kiện toàn ứng dụng có thể rất hữu ích trong thiết lập MVC để cho phép giao tiếp giữa các bộ điều khiển. (extjs4.1)

Hãy nói rằng chúng ta có một trạm điều khiển (ví dụ Sencha MVC) với một hộp chọn:

Ext.define('Pandora.controller.Station', {
    extend: 'Ext.app.Controller',
    ...

    init: function() {
        this.control({
            'stationslist': {
                selectionchange: this.onStationSelect
            },
            ...
        });
    },

    ...

    onStationSelect: function(selModel, selection) {
        this.application.fireEvent('stationstart', selection[0]);
    },    
   ...
});

Khi hộp chọn kích hoạt một sự kiện thay đổi, chức năng onStationSelectsẽ được kích hoạt.

Trong chức năng đó, chúng ta thấy:

this.application.fireEvent('stationstart', selection[0]);

Điều này tạo và kích hoạt một sự kiện toàn ứng dụng mà chúng ta có thể nghe từ bất kỳ bộ điều khiển nào khác.

Do đó, trong một bộ điều khiển khác, bây giờ chúng ta có thể biết khi nào hộp chọn trạm đã được thay đổi. Điều này được thực hiện thông qua việc lắng nghe this.application.onnhư sau:

Ext.define('Pandora.controller.Song', {
    extend: 'Ext.app.Controller', 
    ...
    init: function() {
        this.control({
            'recentlyplayedscroller': {
                selectionchange: this.onSongSelect
            }
        });

        // Listen for an application wide event
        this.application.on({
            stationstart: this.onStationStart, 
                scope: this
        });
    },
    ....
    onStationStart: function(station) {
        console.info('I called to inform you that the Station controller select box just has been changed');
        console.info('Now what do you want to do next?');
    },
}

Nếu hộp chọn đã được thay đổi, bây giờ chúng ta cũng kích hoạt chức năng onStationStarttrong bộ điều khiển Song...

Từ các tài liệu Sencha:

Các sự kiện ứng dụng cực kỳ hữu ích cho các sự kiện có nhiều bộ điều khiển. Thay vì lắng nghe cùng một sự kiện xem trong mỗi bộ điều khiển này, chỉ một bộ điều khiển lắng nghe sự kiện xem và kích hoạt một sự kiện toàn ứng dụng mà những bộ điều khiển khác có thể nghe. Điều này cũng cho phép các bộ điều khiển giao tiếp với nhau mà không cần biết hoặc phụ thuộc vào sự tồn tại của nhau.

Trong trường hợp của tôi: Nhấp vào nút cây để cập nhật dữ liệu trong bảng điều khiển lưới.

Cập nhật 2016 nhờ @ gm2008 từ các bình luận bên dưới:

Về mặt bắn các sự kiện tùy chỉnh trên toàn ứng dụng, hiện tại có một phương thức mới sau khi ExtJS V5.1 được xuất bản, đang sử dụng Ext.GlobalEvents.

Khi bạn bắn các sự kiện, bạn có thể gọi: Ext.GlobalEvents.fireEvent('custom_event');

Khi bạn đăng ký xử lý sự kiện, bạn gọi: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

Phương pháp này không giới hạn ở bộ điều khiển. Bất kỳ thành phần nào cũng có thể xử lý một sự kiện tùy chỉnh thông qua việc đặt đối tượng thành phần làm phạm vi tham số đầu vào.

Tìm thấy trong Sencha Docs: MVC Phần 2


1
Về mặt bắn các sự kiện tùy chỉnh trên toàn ứng dụng, hiện tại có một phương thức mới sau khi ExtJS V5.1 được xuất bản, đó là sử dụng Ext.GlobalEvents. Khi bạn kích hoạt sự kiện, bạn gọi Ext.GlobalEvents.fireEvent('custom_event');Khi bạn đăng ký xử lý sự kiện, bạn gọi Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope};Đây là một câu đố . Phương pháp này không giới hạn ở bộ điều khiển. Bất kỳ thành phần nào cũng có thể xử lý một sự kiện tùy chỉnh thông qua việc đặt đối tượng thành phần làm tham số đầu vào scope. Câu hỏi nên được mở lại.
gm2008

15

Thêm một mẹo cho người nghe sự kiện điều khiển.

Bạn có thể sử dụng ký tự đại diện để theo dõi sự kiện từ bất kỳ thành phần nào:

this.control({
   '*':{ 
       myCustomEvent: this.doSomething
   }
});

12

Chỉ muốn thêm một vài xu vào các câu trả lời xuất sắc ở trên: Nếu bạn đang làm việc trên Extjs 4.1 và không có các sự kiện rộng ứng dụng nhưng cần chúng, tôi đã sử dụng một kỹ thuật rất đơn giản có thể giúp: Tạo một đối tượng đơn giản mở rộng Có thể quan sát và xác định bất kỳ sự kiện rộng ứng dụng nào bạn có thể cần trong đó. Sau đó, bạn có thể kích hoạt các sự kiện đó từ bất kỳ đâu trong ứng dụng của mình, bao gồm cả phần tử dom html thực tế và lắng nghe chúng từ bất kỳ thành phần nào bằng cách chuyển tiếp các phần tử cần thiết từ thành phần đó.

Ext.define('Lib.MessageBus', {
    extend: 'Ext.util.Observable',

    constructor: function() {
        this.addEvents(
            /*
             * describe the event
             */
                  "eventname"

            );
        this.callParent(arguments);
    }
});

Sau đó, bạn có thể, từ bất kỳ thành phần nào khác:

 this.relayEvents(MesageBus, ['event1', 'event2'])

Và bắn chúng từ bất kỳ thành phần hoặc yếu tố dom:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">

Chỉ cần thông tin, this.addEvents đã bị từ chối bắt đầu từ EXT JS 5.0. Vì vậy, không cần thêm các sự kiện ngay bây giờ
Ajay Sharma

11

Chỉ hai điều nữa tôi thấy hữu ích để biết, ngay cả khi chúng không phải là một phần của câu hỏi, thực sự.

Bạn có thể sử dụng relayEventsphương thức để báo cho một thành phần lắng nghe một số sự kiện của thành phần khác và sau đó kích hoạt lại chúng như thể chúng bắt nguồn từ thành phần đầu tiên. Các tài liệu API đưa ra ví dụ về lưới chuyển tiếp loadsự kiện cửa hàng . Nó khá thuận tiện khi viết các thành phần tùy chỉnh đóng gói một số thành phần phụ.

Một cách khác, tức là truyền các sự kiện được nhận bởi một thành phần đóng gói mycmpđến một trong các thành phần phụ của nó subcmp, có thể được thực hiện như thế này

mycmp.on('show' function (mycmp, eOpts)
{
   mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts);
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.