Sự khác biệt giữa khai báo và mệnh lệnh trong React.js?


97

Gần đây, tôi đã nghiên cứu rất nhiều về chức năng và cách sử dụng thư viện JavaScript của Facebook React.js. Khi nói về sự khác biệt của nó với phần còn lại của thế giới JavaScript, hai phong cách lập trình declarativeimperativeđược đề cập đến.

Sự khác biệt giữa cả hai là gì?


22
latentflip.com/imperative-vs-declarative Imperative programming: telling the "machine" how to do something, and as a result what you want to happen will happen. Declarative programming: telling the "machine"1 what you would like to happen, and let the computer figure out how to do it.
rickyduck

4
Tyler McGinnis đã viết một bài báo dài về vấn đề này với một số ví dụ điển hình.
Ian Dunn

Tại sao lại thêm câu trả lời dài dưới dạng nhận xét? ..
Alex

1
Liên kết trên là chính xác, nhưng dấu gạch chéo trong liên kết gây ra 404. latentflip.com/imperative-vs-decl Compare
James Yoo

Câu trả lời:


167

Một kiểu khai báo, giống như những gì react có, cho phép bạn kiểm soát luồng và trạng thái trong ứng dụng của mình bằng cách nói "Nó sẽ giống như thế này". Phong cách mệnh lệnh sẽ xoay chuyển tình thế và cho phép bạn kiểm soát ứng dụng của mình bằng cách nói "Đây là điều bạn nên làm".

Lợi ích của khai báo là bạn không bị sa lầy vào các chi tiết triển khai của việc đại diện cho tiểu bang. Bạn đang ủy quyền cho thành phần tổ chức giữ các chế độ xem ứng dụng của bạn nhất quán, vì vậy bạn chỉ cần lo lắng về trạng thái.

Hãy tưởng tượng bạn có một người quản gia, người này giống như một phép ẩn dụ cho một khuôn khổ. Và bạn muốn làm bữa tối. Trong một thế giới bắt buộc, bạn sẽ chỉ cho họ từng bước cách nấu bữa tối. Bạn phải cung cấp các hướng dẫn sau:

Go to the kitchen
Open fridge
Remove chicken from fridge
...
Bring food to the table

Trong thế giới khai báo, bạn chỉ cần mô tả những gì bạn muốn

I want dinner with chicken.

Nếu quản gia của bạn không biết cách làm gà, thì bạn không thể hoạt động theo kiểu khai báo. Giống như nếu Backbone không biết cách tự biến đổi để thực hiện một nhiệm vụ nhất định, bạn không thể chỉ bảo nó làm nhiệm vụ đó. Ví dụ: React có thể được khai báo vì nó "biết cách làm gà". So với Backbone, vốn chỉ biết giao tiếp với nhà bếp.

Có thể mô tả trạng thái làm giảm đáng kể diện tích bề mặt của bọ, đó là một lợi ích. Mặt khác, bạn có thể kém linh hoạt hơn trong cách mọi thứ diễn ra bởi vì bạn đang ủy quyền hoặc trừu tượng hóa cách bạn triển khai trạng thái.


78

Hãy tưởng tượng một thành phần giao diện người dùng đơn giản, chẳng hạn như nút "Thích". Khi bạn chạm vào nó, nó sẽ chuyển sang màu xanh lam nếu trước đó là màu xám và màu xám nếu trước đó là màu xanh lam.

Cách bắt buộc để làm điều này sẽ là:

if( user.likes() ) {
    if( hasBlue() ) {
        removeBlue();
        addGrey();
    } else {
        removeGrey();
        addBlue();
    }
}

Về cơ bản, bạn phải kiểm tra những gì hiện có trên màn hình và xử lý tất cả các thay đổi cần thiết để vẽ lại nó với trạng thái hiện tại, bao gồm cả việc hoàn tác các thay đổi so với trạng thái trước đó. Bạn có thể tưởng tượng điều này có thể phức tạp như thế nào trong một kịch bản thế giới thực.

Ngược lại, cách tiếp cận khai báo sẽ là:

if( this.state.liked ) {
    return <blueLike />;
} else {
    return <greyLike />;
}

Bởi vì cách tiếp cận khai báo tách biệt các mối quan tâm, phần này của nó chỉ cần xử lý giao diện người dùng trông như thế nào ở trạng thái cụ thể và do đó dễ hiểu hơn nhiều.


21

Đây là sự tương tự tuyệt vời:

* Đáp án bắt buộc : Đi ra khỏi lối ra phía bắc của bãi đậu xe và rẽ trái. Đi về phía nam I-15 cho đến khi bạn đến lối ra Bangerter Highway. Rẽ phải ra khỏi lối ra giống như bạn đang đến Ikea. Đi thẳng và rẽ phải ở ánh sáng đầu tiên. Tiếp tục đi qua ánh sáng tiếp theo rồi rẽ trái tiếp theo của bạn. Nhà tôi là # 298.

Một phản hồi mang tính khai báo : Địa chỉ của tôi là 298 West Immutable Alley, Draper Utah 84020 *

https://tylermcginnis.com/imperative-vs-decl Compare-programming/


18

Tốt nhất là so sánh React (khai báo) và JQuery (bắt buộc) để cho bạn thấy sự khác biệt.

Trong React, bạn chỉ cần mô tả trạng thái cuối cùng của giao diện người dùng của mình trong render()phương thức mà không cần lo lắng về cách chuyển từ trạng thái giao diện người dùng trước đó sang trạng thái giao diện người dùng mới. Ví dụ,

render() {
  const { price, volume } = this.state;
  const totalPrice = price * volume;

  return (
    <div>
      <Label value={price} className={price > 100 ? 'expensive' : 'cheap'} ... />
      <Label value={volume} className={volume > 1000 ? 'high' : 'low'} ... />
      <Label value={totalPrice} ... />
      ...
    </div>
  )
}

Mặt khác, JQuery yêu cầu bạn chuyển đổi trạng thái giao diện người dùng của mình theo thứ bậc, ví dụ: chọn các phần tử nhãn và cập nhật văn bản và CSS của chúng:

updatePrice(price) {
  $("#price-label").val(price);
  $("#price-label").toggleClass('expansive', price > 100);
  $("#price-label").toggleClass('cheap', price < 100);

  // also remember to update UI depending on price 
  updateTotalPrice();
  ... 
}

updateVolume(volume) {
  $("#volume-label").val(volume);
  $("#volume-label").toggleClass('high', volume > 1000);
  $("#volume-label").toggleClass('low', volume < 1000);
  
  // also remember to update UI depending on volume
  updateTotalPrice();
  ... 
}

updateTotalPrice() {
  const totalPrice = price * volume;
  $("#total-price-label").val(totalPrice);
  ...
}

Trong kịch bản thế giới thực, sẽ có nhiều phần tử giao diện người dùng được cập nhật, cộng với các thuộc tính của chúng (ví dụ: kiểu CSS và trình xử lý sự kiện), v.v. Nếu bạn thực hiện điều này một cách chủ quan bằng JQuery, nó sẽ trở nên phức tạp và tẻ nhạt; rất dễ quên cập nhật một số phần của giao diện người dùng hoặc quên xóa trình xử lý sự kiện cũ (gây rò rỉ bộ nhớ hoặc kích hoạt trình xử lý nhiều lần), v.v. Đây là nơi lỗi xảy ra, tức là trạng thái giao diện người dùng và trạng thái mô hình đã hết đồng bộ hóa.

Các trạng thái không đồng bộ sẽ không bao giờ xảy ra với cách tiếp cận khai báo của React, bởi vì chúng ta chỉ cần cập nhật trạng thái mô hình và React có trách nhiệm giữ cho giao diện người dùng và trạng thái mô hình được đồng bộ.

  • Dưới móc, React sẽ cập nhật tất cả các phần tử DOM đã thay đổi bằng cách sử dụng mã mệnh lệnh.

Bạn cũng có thể đọc câu trả lời của tôi cho Sự khác biệt giữa lập trình khai báo và lập trình mệnh lệnh là gì?.

Tái bút: từ ví dụ jQuery ở trên, bạn có thể nghĩ điều gì sẽ xảy ra nếu chúng ta đặt tất cả các thao tác DOM trong một updateAll()phương thức và gọi nó mỗi khi có bất kỳ trạng thái mô hình nào của chúng ta thay đổi và giao diện người dùng sẽ không bao giờ bị mất đồng bộ. Bạn nói đúng, và đây là những gì React làm hiệu quả, sự khác biệt duy nhất là jQuery updateAll()sẽ gây ra nhiều thao tác DOM không cần thiết, nhưng React sẽ chỉ cập nhật các phần tử DOM đã thay đổi bằng cách sử dụng Thuật toán khác biệt DOM ảo của nó .


6

Mã bắt buộc hướng dẫn JavaScript về cách nó sẽ thực hiện từng bước. Với mã khai báo, chúng tôi cho JavaScript biết chúng tôi muốn làm gì và để JavaScript đảm nhận việc thực hiện các bước.

React mang tính khai báo vì chúng tôi viết mã mà chúng tôi muốn và React chịu trách nhiệm lấy mã đã khai báo của chúng tôi và thực hiện tất cả các bước JavaScript / DOM để đưa chúng tôi đến kết quả mong muốn.


5

Một cuộc sống thực song song trong thế giới mệnh lệnh sẽ là bước vào một quán bar để uống bia và đưa ra các hướng dẫn sau cho người pha chế:

- Lấy ly từ kệ

--Đặt ly trước bản nháp

- Kéo tay cầm xuống cho đến khi đầy ly

- Đưa ly cho tôi.

Thay vào đó, trong thế giới khai báo, bạn chỉ cần nói: "Làm ơn hãy uống bia."

Cách tiếp cận khai báo khi yêu cầu một loại bia giả định rằng người pha chế biết cách phục vụ một loại bia và đó là một khía cạnh quan trọng của cách thức hoạt động của chương trình khai báo.

Trong lập trình khai báo, các nhà phát triển chỉ mô tả những gì họ muốn đạt được và không cần phải liệt kê tất cả các bước để làm cho nó hoạt động.

Thực tế là React cung cấp một cách tiếp cận khai báo giúp nó dễ sử dụng và do đó, mã kết quả rất đơn giản, điều này thường dẫn đến ít lỗi hơn và khả năng bảo trì cao hơn.

Vì React tuân theo một mô hình khai báo và không cần phải nói cho nó biết cách tương tác với DOM; bạn chỉ cần KHAI BÁO những gì bạn muốn thấy trên màn hình và React sẽ thực hiện công việc đó cho bạn.



0

Tôi sẽ bắt đầu với một phép tương tự: Tôi có hai chiếc ô tô, trong hai chiếc ô tô của tôi, tôi muốn nhiệt độ bên trong ô tô của mình là nhiệt độ phòng bình thường ~ 72 ° F. Ở chiếc xe đầu tiên (cũ hơn), có hai nút điều khiển nhiệt độ (1 núm để điều khiển nhiệt độ và 1 núm để điều khiển luồng gió). Khi trời quá nóng, tôi phải điều chỉnh núm đầu tiên để giảm nhiệt độ và có thể thay đổi luồng gió) và giảm tốc độ nếu quá lạnh. Đây là công việc bắt buộc! Tôi phải tự quản lý các nút bấm. Trong chiếc xe thứ hai (mới hơn), tôi có thể cài đặt / khai báo nhiệt độ. Có nghĩa là tôi không phải loay hoay với các nút điều chỉnh nhiệt độ mà xe của tôi biết rằng tôi đã khai báo / đặt nó ở 72 ° F và xe của tôi sẽ thực hiện công việc bắt buộc để đạt được trạng thái đó.

React cũng vậy, bạn khai báo markup / template và stat thì React sẽ thực hiện công việc bắt buộc để giữ cho DOM đồng bộ với ứng dụng của bạn.

<button onClick={activateTeleporter}>Activate Teleporter</button>

Thay vì sử dụng .addEventListener()để thiết lập xử lý sự kiện, chúng ta khai báo những gì chúng ta muốn. Khi nhấp vào nút, nó sẽ chạy activateTeleporterchức năng.


-1
  • Khai báo cho phép bạn kiểm soát tất cả các chế độ xem. (như quản lý nhà nước)
  • Mệnh lệnh được phép bạn kiểm soát xung quanh chế độ xem. (như $ (this))
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.