Cách tốt nhất để liên kết các trình xử lý sự kiện trong React

Hình: Flickr bởi liz west

Trình xử lý sự kiện ràng buộc trong React có thể khó khăn (bạn có JavaScript để cảm ơn vì điều đó). Đối với những người biết lịch sử của Perl và Python, TMTOWTDI (Có nhiều hơn một cách để làm điều đó) và TUYỆT VỜI (Chỉ có một cách để làm điều đó) nên là những từ quen thuộc. Thật không may, ít nhất là để liên kết sự kiện, JavaScript là ngôn ngữ TMTOWTDI, luôn khiến các nhà phát triển bối rối.

Trong bài đăng này, chúng tôi sẽ khám phá những cách phổ biến để tạo các ràng buộc sự kiện trong React và tôi sẽ cho bạn thấy những ưu và nhược điểm của chúng. Và quan trọng nhất, tôi sẽ giúp bạn tìm thấy Chỉ có một cách duy nhất - hoặc ít nhất, yêu thích của tôi.

Bài đăng này giả định rằng bạn hiểu sự cần thiết của ràng buộc, chẳng hạn như tại sao chúng ta cần phải làm điều này.handler.bind (này) hoặc sự khác biệt giữa hàm () {console.log (this); } và () => {console.log (này); }. Nếu bạn bối rối về những câu hỏi này, Saurabh Misra đã có một bài viết tuyệt vời giải thích chúng.

Liên kết động trong render ()

Trường hợp đầu tiên thường được sử dụng là gọi .bind (this) trong hàm render (). Ví dụ:

lớp HelloWorld mở rộng Thành phần {
  xử lýClick (sự kiện) {}
  kết xuất () {
    trở về (
      

Xin chào, {this.state.name}!       

Tất nhiên điều này sẽ làm việc. Nhưng hãy nghĩ về một điều: Điều gì xảy ra nếu this.state.namechanges?

Bạn có thể nói rằng việc thay đổi this.state.name sẽ khiến thành phần kết xuất lại (). Tốt Thành phần sẽ kết xuất để cập nhật phần tên. Nhưng nút sẽ được kết xuất?

Hãy xem xét thực tế rằng React sử dụng Virtual DOM. Khi kết xuất xảy ra, nó sẽ so sánh DOM ảo được cập nhật với DOM ảo trước đó và sau đó chỉ cập nhật các phần tử đã thay đổi thành cây DOM thực tế.

Trong trường hợp của chúng tôi, khi render () được gọi, this.handleClick.bind (this) cũng sẽ được gọi để ràng buộc trình xử lý. Cuộc gọi này sẽ tạo ra một trình xử lý hoàn toàn mới, khác hoàn toàn so với trình xử lý được sử dụng khi kết xuất () được gọi lần đầu tiên!

DOM ảo cho liên kết động. Các yếu tố trong màu xanh sẽ được kết xuất lại.

Như trong sơ đồ trên, khi render () được gọi trước đó, this.handleClick.bind (this) đã trả về funcA để React biết onChange là funcA.

Sau đó, khi render () được gọi lại, this.handleClick.bind (this) đã trả về funcB (lưu ý rằng nó sẽ trả về một hàm mới mỗi lần được gọi). Bằng cách này, React biết rằng onChange không còn là funcA, điều đó có nghĩa là nút đó cần được kết xuất lại.

Một nút có thể không phải là một vấn đề. Nhưng nếu bạn có 100 nút được hiển thị trong danh sách thì sao?

kết xuất () {
  trở về (
    {this.state.buttons.map (btn => (
      
        {btn.label}
      
    ))}
  );
}

Trong ví dụ trên, bất kỳ thay đổi nhãn nút nào cũng sẽ khiến tất cả các nút được hiển thị lại, vì tất cả các nút sẽ tạo trình xử lý onChange mới.

Ràng buộc trong hàm tạo ()

Một cách học cũ là thực hiện các ràng buộc trong hàm tạo. Không có gì lạ mắt:

lớp HelloWorld mở rộng Thành phần {
  constructor() {
    this .handleClick = this.handleClickFunc.bind (this);
  }
  kết xuất () {
    return ();
  }
}

Cách này tốt hơn nhiều so với trước đây. Gọi render () sẽ không tạo trình xử lý mới cho onClick, do đó, nút DOM ảo để liên kết trong hàm tạo. Các yếu tố trong màu xanh sẽ được kết xuất lại.

Ràng buộc với chức năng mũi tên

Với các thuộc tính lớp ES7 (hiện được hỗ trợ với Babel), chúng ta có thể thực hiện các ràng buộc theo định nghĩa phương thức:

lớp HelloWorld mở rộng Thành phần {
  xử lýClick = (sự kiện) => {
    console.log (this.state.name);
  }
  kết xuất () {
    return ()
  }
}

Trong đoạn mã trên, handleClick là một phép gán tương đương với:

constructor() {
  this .handleClick = (sự kiện) => {...}
}

Vì vậy, một khi thành phần được khởi tạo, this.handleClick sẽ không bao giờ thay đổi nữa. Bằng cách này, nó đảm bảo rằng