Ưu và nhược điểm của Phản ứng của Facebook so với các thành phần Web (Polyme)


521

Những lợi ích chính của React của Facebook đối với thông số kỹ thuật Web sắp tới và ngược lại (hoặc có lẽ là so sánh táo hơn sẽ là với thư viện polymer của Google )?

Theo bài nói chuyện của JSConf EU và trang chủ React, những lợi ích chính của React là:

  • Phân tách và tăng sự gắn kết bằng mô hình thành phần
  • Trừu tượng, thành phần và biểu cảm
  • Các sự kiện DOM & tổng hợp ảo (về cơ bản có nghĩa là họ đã triển khai lại hoàn toàn DOM và hệ thống sự kiện của nó)
    • Bật công cụ sự kiện HTML5 hiện đại trên IE 8
    • Kết xuất phía máy chủ
    • Khả năng kiểm tra
    • Ràng buộc với SVG, VML và <canvas>

Hầu hết mọi thứ được đề cập đang được tích hợp vào các trình duyệt nguyên bản thông qua các Thành phần Web ngoại trừ khái niệm DOM ảo này (rõ ràng). Tôi có thể thấy làm thế nào các DOM ảo và các sự kiện tổng hợp có thể có ích ngày hôm nay để hỗ trợ các trình duyệt cũ, nhưng sẽ không vứt bỏ một khối lượng lớn mã trình duyệt bản địa giống như tự bắn vào chân mình trong dài hạn? Đối với các trình duyệt hiện đại có liên quan, không phải là có quá nhiều chi phí không cần thiết / phát minh lại bánh xe sao?

Dưới đây là một số điều tôi nghĩ React đang thiếu mà các Thành phần Web sẽ chăm sóc cho bạn. Sửa lỗi cho tôi nếu tôi sai.

  • Hỗ trợ trình duyệt riêng (đọc "đảm bảo sẽ nhanh hơn")
  • Viết kịch bản bằng ngôn ngữ kịch bản, viết kiểu bằng ngôn ngữ tạo kiểu, viết đánh dấu bằng ngôn ngữ đánh dấu.
  • Đóng gói kiểu bằng Shadow DOM
    • React thay vào đó có cái này , đòi hỏi phải viết CSS bằng JavaScript. Không đẹp.
  • Ràng buộc hai chiều

12
Wrt. ràng buộc hai chiều. Tính năng này có vấn đề ở quy mô. Trong các trường hợp tầm thường, nó hoạt động tốt, nhưng trong các trường hợp thực tế, bạn thường thấy rằng để giữ cho mã có thể quản lý được, bạn cần một khung nhìn để liên kết, thay vì ràng buộc với mô hình thực tế, điều này làm cho ràng buộc hai chiều ít hữu ích hơn nhiều so với nó ban đầu dường như. Tôi nghĩ rằng đó có thể là một lợi thế của React khi nó không cung cấp ràng buộc hai chiều vì nó buộc kiến ​​trúc luồng dữ liệu phù hợp.
Joeri Sebrechts

8
Tôi đã xem React, Angular và Knockout. Tôi thấy Knockout là 'sạch nhất' về mặt phân tách ui templating, dữ liệu và ràng buộc. Tôi muốn phản ứng, nhưng cố gắng tạo một Combobox đơn giản, tôi nhận ra rằng tôi đang viết nhiều mã hơn và trộn logic kết xuất với templating html..có nhiều hơn tôi sử dụng một cái gì đó như html / jina2. Dường như với tôi những thư viện / apis này đang đưa chúng ta lùi lại, không tiến lên. Điều tốt nhất về React là thao tác dom ảo, nhưng tôi có thể thấy rằng việc đến với các khung thành lập khác sớm hơn sau này.
mike01010

41
Tôi rất ngạc nhiên (và cũng hài lòng!) Rằng câu hỏi này đã không bị tắt vì "chủ yếu dựa trên quan điểm".
iconoclast

4
Không thể viết "tập lệnh bằng ngôn ngữ kịch bản" và "đánh dấu bằng ngôn ngữ đánh dấu" nếu bạn đang thực hiện việc tạo khuôn mẫu của bất kỳ loại nào. Angular, polymer, v.v ... sử dụng DSL mẫu được nhúng trong HTML. React sử dụng DSL mẫu được nhúng trong JS (JSX). Vấn đề với việc nhúng DSL trong HTML là cách thiết lập phạm vi để nhận các giá trị từ JS. Điều này dẫn đến hệ thống $ scope phức tạp của Angular. Mặt khác, trong JSX, phạm vi của các biến trong các mẫu chỉ là phạm vi JS - tôi thấy nó ít gây nhầm lẫn hơn.
Andy

3
Hiện tại, các thành phần React (trừ khi được viết xấu) sẽ nhanh hơn so với cùng trong bất kỳ khung ràng buộc DOM nào. Phép thuật v-dom và diff-ing là USP của phản ứng. Quan điểm của tôi là - Tại sao các trình duyệt sẽ không tạo ra sự khác biệt như thế trong bộ tính năng gốc của chúng. Điều gì ngăn họ lại, và nếu không có gì (ngăn họ lại) thì sự dẫn dắt của React có lẽ sẽ ngắn ngủi.
fasttrainof mặc dù

Câu trả lời:


664

Cập nhật:  câu trả lời này có vẻ khá phổ biến vì vậy tôi đã dành chút thời gian để dọn dẹp nó một chút, thêm một số thông tin mới và làm rõ một vài điều mà tôi nghĩ là không đủ rõ ràng. Hãy bình luận nếu bạn nghĩ bất cứ điều gì khác cần làm rõ hoặc cập nhật.

Hầu hết các mối quan tâm của bạn thực sự là vấn đề về quan điểm và sở thích cá nhân nhưng tôi sẽ cố gắng trả lời một cách khách quan nhất có thể:

Bản địa so với Biên dịch

Viết JavaScript bằng vanilla JavaScript, viết CSS bằng CSS, viết HTML bằng HTML.

Trước đây, có những cuộc tranh luận sôi nổi về việc liệu người ta nên viết  Hội bản gốc bằng tay hay sử dụng ngôn ngữ cấp cao hơn như C để làm cho trình biên dịch tạo mã hội cho bạn. Ngay cả trước đó, mọi người đã từ chối tin tưởng các nhà lắp ráp và thích viết mã máy bằng tay ( và tôi không nói đùa ).

Trong khi đó, hôm nay có rất nhiều người đã viết HTML trong Haml hoặc Jade , CSS trong Sass hoặc Less và JavaScript trong CoffeeScript hoặc đánh máy . Nó đây rồi. Nó hoạt động. Một số người thích nó, một số thì không.

Vấn đề là về cơ bản không có gì sai khi không viết JavaScript bằng vanilla JavaScript, CSS bằng CSS và HTML bằng HTML. Đó thực sự là một vấn đề ưu tiên.

DSL bên trong và bên ngoài

 Thay vào đó, đóng gói kiểu bằng Shadow DOM React có cái này, đòi hỏi phải viết CSS bằng JavaScript. Không đẹp.

Khá hay không, nó chắc chắn là biểu cảm. JavaScript là một ngôn ngữ rất mạnh, mạnh hơn nhiều so với CSS (thậm chí bao gồm bất kỳ bộ tiền xử lý CSS nào). Nó phụ thuộc vào việc bạn thích DSL bên trong hay bên ngoài cho những thứ đó. Một lần nữa, một vấn đề ưu tiên.

(Lưu ý: Tôi đã nói về các kiểu nội tuyến trong React được tham chiếu trong câu hỏi ban đầu.)

Các loại DSL - giải thích

Cập nhật: Đọc câu trả lời của tôi một thời gian sau khi viết nó tôi nghĩ rằng tôi cần phải giải thích những gì tôi muốn nói ở đây. DSL là ngôn ngữ dành riêng cho miền và nó có thể là nội bộ (sử dụng cú pháp của ngôn ngữ máy chủ như JavaScript - ví dụ như React without JSX hoặc như các kiểu nội tuyến trong React đã đề cập ở trên) hoặc có thể là bên ngoài (sử dụng một cú pháp khác hơn ngôn ngữ máy chủ - như trong ví dụ này sẽ nội tuyến CSS (DSL bên ngoài) bên trong JavaScript).

Nó có thể gây nhầm lẫn bởi vì một số tài liệu sử dụng các thuật ngữ khác với "bên trong" và "bên ngoài" để mô tả các loại DSL đó. Đôi khi "nhúng" được sử dụng thay vì "nội bộ" nhưng từ "được nhúng" có thể có nghĩa khác nhau - ví dụ Lua được mô tả là "Lua: một ngôn ngữ nhúng có thể mở rộng" trong đó nhúng không liên quan gì đến DSL (bên trong) được nhúng có nghĩa là nó hoàn toàn ngược lại - DSL bên ngoài) nhưng điều đó có nghĩa là nó được nhúng theo cùng nghĩa, giả sử, SQLite là một cơ sở dữ liệu nhúng. Thậm chí còn có eLua trong đó "e" là viết tắt của "nhúng" theo nghĩa thứ ba - rằng nó có nghĩa là cho các hệ thống nhúng! Đó là lý do tại sao tôi không thích sử dụng thuật ngữ "DSL nhúng" bởi vì những thứ như eLua có thể là "DSL" được "nhúng" theo hai nghĩa khác nhau trong khi hoàn toàn không phải là "DSL nhúng"!

Để làm cho mọi thứ tồi tệ hơn, một số dự án giới thiệu thêm sự nhầm lẫn cho hỗn hợp. Ví dụ. Các mẫu Flatiron được mô tả là "Không có DSL" trong khi thực tế nó chỉ là một ví dụ hoàn hảo về DSL bên trong với cú pháp như:map.where('href').is('/').insert('newurl');

Điều đó đã được nói, khi tôi viết "JavaScript là một ngôn ngữ rất mạnh, mạnh hơn nhiều so với CSS (thậm chí bao gồm bất kỳ bộ tiền xử lý CSS nào). Điều đó phụ thuộc vào việc bạn thích DSL bên trong hay bên ngoài cho những thứ đó. Một lần nữa, một vấn đề ưu tiên. " Tôi đã nói về hai kịch bản:

Một:

/** @jsx React.DOM */
var colored = {
  color: myColor
};
React.renderComponent(<div style={colored}>Hello World!</div>, mountNode);

Hai:

// SASS:
.colored {
  color: $my-color;
}
// HTML:
<div class="colored">Hello World!</div>

Ví dụ đầu tiên sử dụng những gì được mô tả trong câu hỏi là: "viết CSS bằng JavaScript. Không đẹp." Ví dụ thứ hai sử dụng Sass. Mặc dù tôi đồng ý rằng việc sử dụng JavaScript để viết CSS có thể không đẹp (đối với một số định nghĩa "đẹp") nhưng có một lợi thế khi thực hiện.

Tôi có thể có các biến và hàm trong Sass nhưng chúng có phạm vi từ vựng hoặc phạm vi động? Chúng được gõ tĩnh hay động? Mạnh hay yếu? Còn các loại số thì sao? Kiểu coersion? Những giá trị nào là trung thực và đó là giả? Tôi có thể có chức năng bậc cao hơn? Đệ quy? Đuôi gọi? Đóng cửa từ vựng? Họ được đánh giá theo thứ tự bình thường hoặc thứ tự áp dụng? Có đánh giá lười biếng hay háo hức? Là đối số cho các hàm được truyền theo giá trị hoặc bằng tham chiếu? Họ có thể đột biến? Bất biến? Kiên trì? Còn đối tượng thì sao? Các lớp học? Nguyên mẫu? Di sản?

Đó không phải là những câu hỏi tầm thường và tôi phải biết câu trả lời cho họ nếu tôi muốn hiểu mã Sass hoặc Ít hơn. Tôi đã biết những câu trả lời đó cho JavaScript, điều đó có nghĩa là tôi đã hiểu mọi DSL bên trong (như kiểu nội tuyến trong React) ở những cấp độ đó, vì vậy nếu tôi sử dụng React thì tôi chỉ phải biết một bộ câu trả lời cho những câu trả lời đó (và nhiều câu tương tự ) câu hỏi, trong khi khi tôi sử dụng ví dụ. Sass và Tay cầm sau đó tôi phải biết ba bộ câu trả lời đó và hiểu ý nghĩa của chúng.

Không phải nói rằng cách này hay cách khác luôn tốt hơn nhưng mỗi khi bạn giới thiệu một ngôn ngữ khác cho hỗn hợp thì bạn phải trả một số giá có thể không rõ ràng ngay từ cái nhìn đầu tiên và giá này rất phức tạp.

Tôi hy vọng tôi đã làm rõ những gì tôi có nghĩa ban đầu một chút.

Ràng buộc dữ liệu

Ràng buộc hai chiều

Đây là một chủ đề thực sự thú vị và trên thực tế cũng là một vấn đề ưu tiên. Hai chiều không phải lúc nào cũng tốt hơn một chiều. Đó là một câu hỏi về cách bạn muốn mô hình hóa trạng thái có thể thay đổi trong ứng dụng của bạn. Tôi luôn xem các ràng buộc hai chiều là một ý tưởng hơi trái với các nguyên tắc của lập trình chức năng nhưng lập trình chức năng không phải là mô hình duy nhất hoạt động, một số người thích loại hành vi này và cả hai cách tiếp cận dường như hoạt động khá tốt trong thực tế. Nếu bạn quan tâm đến các chi tiết của các quyết định thiết kế liên quan đến mô hình hóa trạng thái trong React thì hãy xem cuộc nói chuyện của Pete Hunt (liên kết với câu hỏi) và cuộc nói chuyện của Tom Occhino và Jordan Walke  , người giải thích rất rõ về nó quan điểm của tôi.

Cập nhật: Xem thêm một cuộc nói chuyện khác của Pete Hunt: Có thể dự đoán được, không chính xác: lập trình DOM chức năng .

Cập nhật 2: Nó đáng chú ý là nhiều nhà phát triển đang tranh cãi chống lại luồng dữ liệu hai chiều, hoặc ràng buộc hai chiều, một số thậm chí gọi nó là một chất chống mẫu. Hãy ví dụ như Flux kiến trúc ứng dụng mà tránh được một cách rõ ràng MVC model (được chứng minh là khó có thể mở rộng quy mô cho Facebook lớn và các ứng dụng Instagram) trong lợi của một luồng dữ liệu đúng theo một hướng (xem Way Hacker: Suy nghĩ lại Web Phát triển ứng dụng ở Facebook nói chuyện bằng Tom Occhino, Jing Chen và Pete Hunt cho một lời giới thiệu tốt). Ngoài ra, rất nhiều chỉ trích chống lại AngularJS (khung Web phổ biến nhất dựa trên mô hình MVC, được biết đến với ràng buộc dữ liệu hai chiều) bao gồm các đối số chống lại luồng dữ liệu hai chiều đó, xem:

Cập nhật 3: Một bài viết thú vị khác giải thích độc đáo một số vấn đề được giải thích ở trên là Giải cấu trúc Flux của ReactJS - Không sử dụng MVC với ReactJS của Mikael Brassman, tác giả của RefluxJS (một thư viện đơn giản cho kiến ​​trúc ứng dụng luồng dữ liệu đơn hướng được lấy cảm hứng từ Flux).

Cập nhật 4: Ember.js hiện đang rời khỏi ràng buộc dữ liệu hai chiều và trong các phiên bản trong tương lai, nó sẽ là một chiều theo mặc định. Xem: Cuộc nói chuyện về Tương lai của Ember của Stefan Penner từ Hội nghị chuyên đề Embergarten ở Toronto vào ngày 15 tháng 11 năm 2014.

Cập nhật 5: Xem thêm: Đường đến Ember 2.0 RFC - cuộc thảo luận thú vị trong yêu cầu kéo của Tom Dale :

"Khi chúng tôi thiết kế lớp tạo khuôn ban đầu, chúng tôi đã hình dung rằng việc tạo tất cả các ràng buộc dữ liệu hai chiều sẽ không có hại: nếu bạn không đặt ràng buộc hai chiều, thì đó là ràng buộc một chiều trên thực tế!

Kể từ đó, chúng tôi đã nhận ra (với một số trợ giúp từ bạn bè của chúng tôi tại React), rằng các thành phần muốn có thể cung cấp dữ liệu cho con cái của chúng mà không cần phải cảnh giác với các đột biến bướng bỉnh.

Ngoài ra, giao tiếp giữa các thành phần thường được thể hiện một cách tự nhiên nhất dưới dạng sự kiện hoặc cuộc gọi lại . Điều này có thể xảy ra ở Ember, nhưng sự thống trị của các ràng buộc dữ liệu hai chiều thường dẫn mọi người xuống một con đường sử dụng các ràng buộc hai chiều như một kênh liên lạc . Các nhà phát triển Ember có kinh nghiệm không (thường) mắc lỗi này, nhưng đó là một lỗi dễ mắc phải. " [Nhấn mạnh thêm]

Bản địa so với VM

Hỗ trợ trình duyệt riêng (đọc "đảm bảo sẽ nhanh hơn")

Bây giờ cuối cùng một cái gì đó không phải là một vấn đề quan điểm.

Trên thực tế ở đây nó chính xác là cách khác. Tất nhiên mã "gốc" có thể được viết bằng C ++ nhưng bạn nghĩ công cụ JavaScript được viết bằng gì?

Thực tế, các công cụ JavaScript thực sự tuyệt vời trong các tối ưu hóa mà chúng sử dụng ngày nay - và không chỉ V8 nữa, mà cả SpiderMonkey và thậm chí cả Chakra cũng tỏa sáng trong những ngày này. Và hãy nhớ rằng với trình biên dịch JIT, mã không chỉ có nguồn gốc như nó có thể có mà còn có các cơ hội tối ưu hóa thời gian chạy mà đơn giản là không thể thực hiện trong bất kỳ mã được biên dịch tĩnh nào.

Khi mọi người nghĩ rằng JavaScript chậm, họ thường có nghĩa là JavaScript truy cập DOM. DOM chậm. Nó là bản địa, được viết bằng C ++ và nó chậm như địa ngục vì sự phức tạp mà nó phải thực hiện.

Mở bàn điều khiển của bạn và viết:

console.dir(document.createElement('div'));

và xem có bao nhiêu thuộc tính mà một divphần tử trống thậm chí không được gắn vào DOM phải thực hiện. Đây chỉ là các  thuộc tính cấp đầu tiên là "thuộc tính riêng" tức là. không được kế thừa từ chuỗi nguyên mẫu:

align, onwaiting, onvolumechange, ontimeupdate, onuspend onmouseenter, onmousedown, onloadouse, onloadedart oncontextmenu, onclose, onclick, onchange, oncanplay phiên bản, oncanplay, oncattery, onblur, onabort, kiểm tra chính tả, isContentEditable, contentEditable, outsText, InternalText, accessKey, hidden, webkitdropzone, draggable, tabFirstEuityChild, trẻ em clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTopent, offsetLeight, offsetWidth, offsetTop, offsetLeft, localName, tiền tố, tên không gian, chữ cái, thuộc tính, tên miền, tiền tố, tên miền ParentNode, nodeType, nodeValue, nodeNameoncopy, onb Beforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, tập dữ liệu, classList, className, outsHTML, trong namepaceURI, id, style, thuộc tính, tagName, ParentEuity, textContent, baseURI, ownDocument, nextSibling, trướcSibling, lastChild, FirstChild, childNodes, ParentNode, nodeType, nodeValue, nodeNameoncopy, onb Beforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, tập dữ liệu, classList, className, outsHTML, trong namepaceURI, id, style, thuộc tính, tagName, ParentEuity, textContent, baseURI, ownDocument, nextSibling, trướcSibling, lastChild, FirstChild, childNodes, ParentNode, nodeType, nodeValue, nodeNameParentEuity, textContent, baseURI, ownDocument, nextSibling, trướcSibling, lastChild, firstChild, childNodes, ParentNode, nodeType, nodeValue, nodeNameParentEuity, textContent, baseURI, ownDocument, nextSibling, trướcSibling, lastChild, firstChild, childNodes, ParentNode, nodeType, nodeValue, nodeName

Nhiều trong số chúng thực sự là các đối tượng lồng nhau - để xem các thuộc tính cấp hai (sở hữu) của một nguồn gốc trống divtrong trình duyệt của bạn, hãy xem câu đố này .

Ý tôi là nghiêm túc, thuộc tính onvolumechange trên mỗi nút div duy nhất? Có phải là một sai lầm? Không, đây chỉ là phiên bản mô hình sự kiện truyền thống DOM Cấp 0 của một trong những trình xử lý sự kiện " phải được hỗ trợ bởi tất cả các yếu tố HTML , vì cả thuộc tính nội dung và thuộc tính IDL" [nhấn mạnh thêm] trong Phần 6.1.6.2 của thông số HTML bởi W3C - không có cách nào xung quanh nó.

Trong khi đó, đây là các thuộc tính cấp đầu tiên của DOM giả divtrong React:

đạo cụ, _owner, _lifeCyclState, _pendingProps, _pendingCallbacks, _pendingOwner

Hoàn toàn khác biệt phải không? Trên thực tế, đây là toàn bộ đối tượng được tuần tự hóa thành JSON ( LIVE DEMO ), bởi vì bạn thực sự có thể  tuần tự hóa nó thành JSON vì nó không chứa bất kỳ tham chiếu vòng tròn nào - một điều không thể tưởng tượng được trong thế giới của DOM gốc ( nơi nó sẽ ném ngoại lệ ):

{
  "props": {},
  "_owner": null,
  "_lifeCycleState": "UNMOUNTED",
  "_pendingProps": null,
  "_pendingCallbacks": null,
  "_pendingOwner": null
}

Đây là lý do chính khiến React có thể nhanh hơn DOM trình duyệt gốc - bởi vì nó không phải thực hiện mớ hỗn độn này .

Xem bản trình bày này của Steven Luscher để xem cái gì nhanh hơn: DOM gốc được viết bằng C ++ hoặc DOM giả được viết hoàn toàn bằng JavaScript. Đó là một bài thuyết trình rất công bằng và thú vị.

Cập nhật: Ember.js trong các phiên bản trong tương lai sẽ sử dụng một DOM ảo được lấy cảm hứng rất nhiều từ React để cải thiện độ hoàn hảo. Xem: Cuộc nói chuyện về Tương lai của Ember của Stefan Penner từ Hội nghị chuyên đề Embergarten ở Toronto vào ngày 15 tháng 11 năm 2014.

Tóm lại: các tính năng từ Thành phần Web như mẫu, ràng buộc dữ liệu hoặc các yếu tố tùy chỉnh sẽ có rất nhiều lợi thế so với React nhưng cho đến khi chính mô hình đối tượng tài liệu được đơn giản hóa đáng kể thì hiệu suất sẽ không phải là một trong số chúng.

Cập nhật

Hai tháng sau khi tôi đăng câu trả lời này, có một số tin tức có liên quan ở đây. Như tôi vừa viết trên Twitter , phiên bản mới nhất của trình soạn thảo văn bản Atom do GitHub viết bằng JavaScript sử dụng React của Facebook để có hiệu suất tốt hơn mặc dù theo Wikipedia "Atom dựa trên Chromium và được viết bằng C ++" nên nó có toàn quyền kiểm soát việc triển khai C ++ DOM gốc (xem Hạt nhân nguyên tử )  được đảm bảo có hỗ trợ cho các Thành phần Web vì nó có trình duyệt web riêng. Đây chỉ là một ví dụ gần đây về một dự án trong thế giới thực, có thể sử dụng bất kỳ loại tối ưu hóa nào khác thường không có sẵn cho các ứng dụng Web và nó đã chọn sử dụng React được viết bằng JavaScript, để đạt được hiệu suất tốt nhất, ngay cả khi Atom đã không được xây dựng với React để bắt đầu, vì vậy thực hiện nó không phải là một thay đổi nhỏ.

Cập nhật 2

một so sánh thú vị của Todd Parker khi sử dụng WebPagetest để so sánh hiệu suất của các ví dụ TodoMVC được viết bằng Angular, Backbone, Ember, Polymer, CanJS, YUI, Knockout, React và Shoestring. Đây là so sánh khách quan nhất mà tôi đã thấy cho đến nay. Điều quan trọng ở đây là tất cả các ví dụ tương ứng được viết bởi các chuyên gia trong tất cả các khung đó, chúng đều có sẵn trên GitHub và có thể được cải thiện bởi bất kỳ ai nghĩ rằng một số mã có thể được tối ưu hóa để chạy nhanh hơn.

Cập nhật 3

Ember.js trong các phiên bản trong tương lai sẽ bao gồm một số tính năng của React được thảo luận ở đây (bao gồm cả DOM ảo và ràng buộc dữ liệu một chiều, chỉ đặt tên cho một số), có nghĩa là các ý tưởng bắt nguồn từ React đã được chuyển sang các khung khác. Xem: Đường đến Ember 2.0 RFC - cuộc thảo luận thú vị trong yêu cầu kéo của Tom Dale (Ngày bắt đầu: 2014-12-03): "Trong Ember 2.0, chúng tôi sẽ áp dụng mô hình" DOM ​​ảo "và mô hình luồng dữ liệu bao trùm ý tưởng tốt nhất từ ​​React và đơn giản hóa giao tiếp giữa các thành phần. "

Đồng thời, Angular.js 2.0 đang triển khai rất nhiều khái niệm được thảo luận ở đây.

Cập nhật 4

Tôi phải giải thích một vài vấn đề để trả lời nhận xét này của Igwe Kalu:

"Không thể so sánh React (JSX hoặc đầu ra biên dịch) với JavaScript đơn giản, khi React cuối cùng giảm xuống JavaScript đơn giản. [...] Dù sử dụng chiến lược nào thì React sử dụng để chèn DOM mà không cần sử dụng React. không thêm bất kỳ lợi ích đặc biệt nào khi xem xét tính năng được đề cập ngoài sự tiện lợi. " (bình luận đầy đủ ở đây )

Trong trường hợp chưa đủ rõ ràng, một phần trong câu trả lời của tôi, tôi đang so sánh hiệu suất hoạt động trực tiếp trên DOM gốc (được triển khai dưới dạng đối tượng máy chủ trong trình duyệt) so với DOM giả / ảo của React (được triển khai bằng JavaScript). Điểm tôi đang cố gắng đưa ra là DOM ảo được triển khai trong JavaScript có thể vượt trội hơn DOM thực được triển khai trong C ++ và không phải React có thể vượt trội hơn JavaScript (điều này rõ ràng sẽ không có ý nghĩa gì vì nó được viết bằng JavaScript). Quan điểm của tôi là mã C ++ "bản địa" không phải lúc nào cũng được đảm bảo nhanh hơn JavaScript "không bản địa". Sử dụng React để minh họa điểm đó chỉ là một ví dụ.

Nhưng bình luận này đã chạm vào một vấn đề thú vị. Theo một nghĩa nào đó, đúng là bạn không cần bất kỳ khung nào (React, Angular hoặc jQuery) vì bất kỳ lý do gì (như hiệu suất, tính di động, tính năng) bởi vì bạn luôn có thể tạo lại những gì khung làm cho bạn và phát minh lại bánh xe - nếu bạn có thể biện minh cho chi phí, đó là.

Nhưng - như Dave Smith độc đáo đặt nó trong Làm thế nào để bỏ lỡ thời điểm khi so sánh hiệu suất khuôn khổ web : "Khi so sánh hai khuôn khổ web, vấn đề không phải là có thể ứng dụng của tôi được nhanh chóng với khuôn khổ X. Câu hỏi đặt ra là sẽ ứng dụng của tôi được nhanh chóng với khuôn khổ X. "

Trong câu trả lời năm 2011 của tôi về: một số lý do kỹ thuật thực nghiệm không sử dụng jQuery Tôi giải thích một vấn đề tương tự, đó là không thể viết mã thao tác DOM di động mà không có thư viện như jQuery, nhưng mọi người hiếm khi làm như vậy.

Khi sử dụng ngôn ngữ lập trình, thư viện hoặc khung, mọi người có xu hướng sử dụng các cách làm việc thuận tiện hoặc thành ngữ nhất, không phải là cách hoàn hảo nhưng bất tiện. Giá trị thực sự của các khung công tác tốt là làm cho dễ dàng những gì sẽ khó thực hiện - và bí mật là làm cho mọi thứ trở nên thuận tiện. Kết quả vẫn có sức mạnh chính xác theo ý của bạn như dạng tính toán lambda đơn giản nhất hoặc máy Turing nguyên thủy nhất, nhưng tính biểu cảm tương đối của các khái niệm nhất định có nghĩa là những khái niệm đó có xu hướng được thể hiện dễ dàng hơn hoặc hoàn toàn, và rằng các giải pháp đúng đắn không chỉ có thể mà còn thực sự được triển khai rộng rãi.

Cập nhật 5

Phản ứng + Hiệu suất =? bài viết của Paul Lewis từ tháng 7 năm 2015 cho thấy một ví dụ trong đó React chậm hơn vanilla JavaScript được viết bằng tay cho một danh sách vô hạn các hình ảnh Flickr, đặc biệt quan trọng trên thiết bị di động. Ví dụ này cho thấy mọi người phải luôn kiểm tra hiệu năng cho trường hợp sử dụng cụ thể và các nền tảng và thiết bị đích cụ thể.

Nhờ Kevin Lozandier cho đưa nó đến sự chú ý của tôi .


75
đó là những gì tôi gọi là một câu trả lời toàn diện, cảm ơn!
Demwunz

14
Có vẻ như Atom đang rời khỏi React. Xem github.com/atom/atom/issues/3677 .
Juho Vepsäläinen

6
@ash: Nếu bạn đọc sâu hơn về chủ đề, họ sẽ nói về cách cuối cùng họ muốn di chuyển hoàn toàn khỏi React và các khung công tác khác, và chỉ sử dụng các phần tử tùy chỉnh và DOM bóng tối.
Musicfreak

3
Chỉ cần làm rõ từ ngữ ở trên, trong danh sách của @ErikAllik, FRP (Lập trình phản ứng chức năng) không phải là một ngôn ngữ mới mà là một cách tiếp cận đang trở nên phổ biến. Trên thực tế, "Elm dựa trên ý tưởng về lập trình phản ứng chức năng" (từ elm-lang.org), và như ông đã đề cập, có các khung FRP cho Haskell, v.v.
Jon Coombs

5
tl; đọc dù sao - câu trả lời xuất sắc, chi tiết!
Mark K Cowan

16

Polyme là tuyệt vời. Phản ứng là tuyệt vời. Chúng không giống nhau.

Polyme là một thư viện để xây dựng các thành phần web tương thích ngược.

Phản ứng là V trong MVC. Đó là Chế độ xem và không có gì khác. Không phải tự nó ít nhất.

Phản ứng không phải là một khuôn khổ.

React + Flux + Node + (Gulp hoặc Grunt) tương đương với một khung công tác, nhưng 3 trong số đó không phải là một phần của phản ứng.

Có nhiều công nghệ, mô hình và phong cách kiến ​​trúc phản ứng các nhà phát triển tuân theo, nhưng phản ứng tự nó không phải là một khung.

Thật đáng buồn khi không ai dành thời gian để nói điều đơn giản nhất có thể, rằng họ không nên so sánh. Chúng có một số chồng chéo, nhưng chúng khác nhau nhiều hơn giống nhau.

Cả hai đều cho phép bạn xác định các thành phần web, nhưng theo những cách khác nhau. Ngoài ra chúng là những công cụ rất rất khác nhau.


Không phản ứng cả M và V, không chỉ V, vì nó giữ và cập nhật trạng thái dữ liệu và hiển thị các đoạn html thông qua các thành phần?
abelito

1
Có các thư viện quản lý nhà nước phản ứng như thông lượng hoặc redux, nhưng chúng không được đóng gói với phản ứng.
Robotsushi

Ồ tôi hiểu rồi, chúng tôi không coi dữ liệu Xem là dữ liệu mô hình .. cho đến khi nó được gửi đến phía máy chủ. Mặc dù React giữ trạng thái thành phần (xem dữ liệu), nhưng vẫn xem dữ liệu cho đến khi gửi. Điều đó có ý nghĩa.
abelito

15

Các anh chàng React có một lời giải thích khá hay về việc so sánh giữa React và các Thành phần Web:

Cố gắng so sánh và đối chiếu Phản ứng với WebComponents chắc chắn dẫn đến kết luận cụ thể, bởi vì hai thư viện được xây dựng để giải quyết các vấn đề khác nhau. WebComponents cung cấp đóng gói mạnh mẽ cho các thành phần có thể sử dụng lại, trong khi React cung cấp một thư viện khai báo giữ DOM đồng bộ với dữ liệu của bạn. Hai mục tiêu là bổ sung; các kỹ sư có thể trộn và kết hợp các công nghệ. Là nhà phát triển, bạn có thể tự do sử dụng React trong WebComponents của mình hoặc sử dụng WebComponents trong React hoặc cả hai.


14

Một câu trả lời khác ở một điểm cụ thể:

Viết JavaScript bằng vanilla JavaScript, viết CSS bằng CSS, viết HTML bằng HTML.

Không có gì ngăn cản bạn viết Javascript, nói, CoffeeScript, TypeScript, ClojureScript hoặc bất cứ thứ gì khác. Đó hoàn toàn là vấn đề ưu tiên.

HTML là DSL tốt nhất cho các tài liệu HTML tĩnh . Nhưng nó không cung cấp gì cho HTML động. Và trong trình duyệt, ngôn ngữ tốt nhất để tạo HTML động là Javascript, không phải là HTML thuần túy với thao tác DOM DOM quảng cáo hoặc ngôn ngữ mẫu như Tay cầm không phải là một nửa ngôn ngữ.

Đối với CSS, nếu CSS của bạn là tĩnh, bạn viết nó như bình thường. Nếu nó cần phải động dựa trên một số giá trị thời gian chạy, thì đó là câu chuyện tương tự như HTML: Javascript là cách tốt nhất để làm cho nó động.


1
Tôi đánh giá cao câu trả lời, nhưng đó không thực sự là quan điểm của tôi. Hy vọng rằng các chỉnh sửa của tôi làm cho câu hỏi rõ ràng hơn một chút?
CletusW

1
Xin lỗi nó không. Bạn vẫn có thể viết kiểu của mình bằng bất kỳ ngôn ngữ kiểu nào trong một tệp riêng. Và JSX của React làm cho nó giống như bạn đang sử dụng ngôn ngữ đánh dấu.
DjebbZ

3
"Javascript là cách tốt nhất để làm cho [CSS] động" - nói đơn giản là nó không thực sự giải thích lý do tại sao.
pilau

1
Chà, nếu các kiểu / lớp cần thay đổi theo quy tắc đầu vào của người dùng hoặc doanh nghiệp, chỉ cần sử dụng javascript để thay đổi chúng. Trong vanilla js, bạn sẽ thao tác các thuộc tính classList hoặc style của một nút DOM. Với React, bạn có thể đạt được cùng một mục tiêu thao túng DOM ảo. Có rõ ràng hơn không?
DjebbZ

2
Vjeux, người đóng góp cốt lõi cho React, gần đây đã có một cuộc nói chuyện trong đó nó thúc đẩy khái niệm "CSS trong JS" bằng React. Tôi nghĩ điều đó thật thú vị, bạn có thể sẵn sàng xem nội dung của nó: blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html
DjebbZ

6

Tôi chưa sử dụng các Thành phần Web, nhưng có vẻ như chúng yêu cầu bạn thêm logic đột biến được mã hóa thủ công vào các trình xử lý sự kiện.

đoạn trích từ ví dụ về polymer:

 <script>
   Polymer({
     counterChanged: function() {
       this.$.counterVal.classList.add('highlight');
     },
 ...

Toàn bộ quan điểm của React là giảm độ phức tạp bằng cách loại bỏ logic đột biến. Thay vào đó, bạn hoàn toàn tái tạo một DOM ảo và để thuật toán diff của React tìm ra những gì cần thay đổi trong DOM thực.


5
Không chắc chắn nơi bạn có ví dụ đó, nhưng Polymer cũng không khuyến khích đột biến DOM thủ công có lợi cho liên kết dữ liệu, bao gồm cả tên lớp .
CletusW

Đó là ví dụ từ tab "tạo phần tử" trên trang nhất của polymer-project.org .
hạn

4
Ồ, bạn nói đúng! Tôi đoán họ chỉ muốn một ví dụ về tìm kiếm nút tự động. Đó có lẽ không phải là thứ tốt nhất để cho đi.
CletusW

6

Tôi nghĩ rằng nhược điểm lớn nhất của React theo ý kiến ​​của tôi là nó không dựa trên các tiêu chuẩn web. React là một công cụ rất mạnh ngay bây giờ, nhưng vì nó phá vỡ rất nhiều những gì trình duyệt cung cấp bất cứ khi nào có thể, các quyết định dường như có ý nghĩa bây giờ có thể sẽ không có ý nghĩa trong một vài năm nữa khi các cơ sở tích hợp của trình duyệt tiếp tục cải tiến. Vì vậy, tôi muốn nói về điều đó và cách nó tác động đến một vài khía cạnh khác nhau của các ứng dụng web.

Hiệu suất

Mọi người muốn tranh luận rằng lợi thế của React là nó hoàn toàn phát minh lại toàn bộ mô hình DOM và sự kiện, và DOM tiêu chuẩn hiện tại rất nặng nề và đắt đỏ, nhưng cuối cùng tôi vẫn không tìm thấy hiệu suất của Phản ứng để trở nên tốt hơn những gì tôi có thể nhận được từ một ứng dụng Backbone hoặc polymer được viết tốt. Trên thực tế, trong hầu hết kinh nghiệm chuyên môn của tôi, hiệu suất của React thực sự kém hơn một chút. Điều đó không có nghĩa là React chậm ... Đó không phải là sự lựa chọn hiệu năng vượt trội mà tất cả chúng ta đều nghĩ đó là trước khi chúng ta chạm tay vào nó.

Trong câu trả lời RSP, ông chỉ ra rằng mô hình DOM Phản ứng đối với một div là nhiều trọng lượng nhẹ hơn so với div DOM bản địa, và đó là hoàn toàn đúng. Tuy nhiên, để React trở nên hữu ích, div 'ảo' đó cuối cùng phải trở thành một div thực sự. Vì vậy, trong thế giới quan của tôi, đó không phải là vấn đề của div React vs div bản địa. Đó là div React + div gốc so với div gốc. Chi phí hoạt động của phiên bản DOM của React là không tầm thường và nếu các tiêu chuẩn bỏ đi một số thuộc tính không cần thiết đó và cho phép các nút DOM gốc nhẹ hơn nhiều, thì đột nhiên chi phí đó sẽ rất đắt.

Ở một trong những nơi làm việc trước đây của tôi, chúng tôi đã có một số ứng dụng trong Polyme và một số ứng dụng trong React. Một trong những ứng dụng Polyme đầu tiên cuối cùng đã được viết lại trong React vì đó là những gì công ty đã đạt được, và dựa trên các phép đo, tôi đã lấy phiên bản React của cùng ứng dụng này sử dụng bộ nhớ nhiều hơn khoảng 30% so với phiên bản Polyme và mặc dù sự khác biệt là không đáng kể, phiên bản Polyme cũng được hiển thị trong thời gian ngắn hơn. Một điều cần xem xét ở đây là chúng ta đang nói về các ứng dụng được viết bởi mọi người và mọi người không hoàn hảo, vì vậy có thể việc triển khai React của ứng dụng này không tận dụng mọi thứ mà React có khả năng. Nhưng tôi nghĩ rằng ít nhất một số trong số đó phải làm với React phải chịu khi có phiên bản DOM riêng.

React phát minh lại toàn bộ DOM bằng mô hình của chính nó và sau đó sử dụng mô hình đó để tối ưu hóa hiệu suất chính. Một khung nhìn được kết xuất vào một DOM ảo và được chiếu vào DOM thực. Khi có thay đổi và chế độ xem phải được cập nhật, chế độ xem sẽ được kết xuất lại vào DOM ảo một lần nữa và cây đó khác với cây trước đó để xác định nút nào phải được thay đổi trong DOM thực để phản ánh thay đổi này Theo quan điểm. Mặc dù đây là một cách tiếp cận rất thông minh để thực hiện cập nhật DOM hiệu quả, nhưng vẫn có quá nhiều việc trong việc duy trì tất cả các cây DOM ảo này và phân biệt chúng để xác định những gì cần thay đổi trong DOM thực. Ngay bây giờ, chi phí này được bù đắp rất nhiều bởi các lợi ích hiệu suất, nhưng khi DOM gốc được cải thiện theo thời gian, quy mô sẽ thay đổi theo hướng khác. Tôi lo lắng về việc ứng dụng React có thể già đi như thế nào, và nếu trong 3 năm nữa, chúng sẽ chậm hơn nhiều so với những thứ liên quan đến DOM trực tiếp hơn. Cách tiếp cận DOM ảo này là một chút của búa tạ và các thư viện khác như Polymer đã có thể thực hiện các cách tiếp cận rất hiệu quả để xử lý DOM theo cách tinh tế hơn nhiều.

Cập nhật cho hiệu suất: Một trong những thư viện mà tôi tình cờ gặp lại trong thời gian trước, điều tôi nghĩ là công việc tốt hơn trong việc quản lý các bản cập nhật cho DOM. Đó là thư viện Dom Incremental Dom của Google và tôi nghĩ rằng thực tế là nó hoạt động với dom tại chỗ và không phải tạo ra một "bản sao ảo" là một cách tiếp cận gọn gàng hơn, với chi phí bộ nhớ ít hơn nhiều. Xem thêm tại đây: http://google.github.io/incremental-dom/#about

Thành phần khai báo và mệnh lệnh

Một trong những điều bạn luôn nghe thấy khi bạn nói về việc thành phần hóa ứng dụng của bạn là tất cả những lợi ích của các thành phần của bạn là khai báo. Bên trong thế giới quan của React, mọi thứ đều tốt đẹp và mang tính khai báo. Bạn viết JavaScript trả về đánh dấu và React sẽ dán tất cả lại cho bạn. Và thật tuyệt nếu bạn đang làm việc với một ứng dụng hoàn toàn mới chỉ sử dụng React và không có gì khác. Bạn có thể viết một số thành phần và miễn là bạn đang ở trong một mảnh DOM thuộc sở hữu của React, đơn giản như việc đặt thẻ đó trên trang để sử dụng thành phần của bạn.

Nhưng ngay khi bạn đi lấy những thành phần đó và sử dụng chúng bên ngoài React, mọi thứ trở nên rắc rối hơn rất nhiều. Bởi vì cách các thành phần React được tạo thành các thẻ hoàn toàn nằm ngoài những gì các tiêu chuẩn web cung cấp, không có gì khác ngoài React biết cách cung cấp cho bạn một cách khai báo để tiêu thụ các thành phần này. Nếu tôi muốn đặt các thành phần React vào chế độ xem Xương sống hiện có bằng cách sử dụng các mẫu của Handbars, bạn phải kết xuất một div giả trong mẫu của mình bằng một lớp hoặc ID mà bạn có thể sử dụng làm tay cầm, sau đó viết JavaScript bắt buộc để tìm div giả đó và gắn kết thành phần của bạn vào nó. Có ứng dụng Express.js đang sử dụng các mẫu phía máy chủ? Vâng, đó là cùng một bài hát và điệu nhảy. Một trang JSP? Bạn cười, nhưng có rất nhiều ứng dụng vẫn đang sử dụng chúng. Trừ khi bạn là một loại khởi động không có mã hiện có, bạn ' sẽ phải viết một số hệ thống ống nước để sử dụng lại các thành phần React của bạn trên nhiều ứng dụng. Trong khi đó, Polymer đạt được các thành phần thông qua tiêu chuẩn Thành phần Web và bằng cách sử dụng thông số Phần tử tùy chỉnh, Polymer có thể tạo ra các thành phần mà trình duyệt chỉ cần biết cách tiêu thụ. Tôi có thể đặt một thành phần Polyme vào trang JSP, mẫu Express.js, chế độ xem ASP.NET, khung nhìn Backbone ... bên trong thành phần React. Nghĩa đen là bất cứ nơi nào bạn có thể sử dụng HTML, bạn có thể sử dụng một thành phần Polyme. Những người đang thiết kế để tái sử dụng đang tìm kiếm các tiêu chuẩn web, bởi vì các tiêu chuẩn là hợp đồng giúp dễ dàng làm cho mọi thứ tương thích với nhau. YouTube tiếp tục tạo ra nhiều nội dung hơn trong Polyme (nguồn: Polyme đạt được các thành phần thông qua tiêu chuẩn Thành phần Web và bằng cách sử dụng thông số Phần tử tùy chỉnh, Polyme có thể tạo ra các thành phần mà trình duyệt chỉ cần biết cách tiêu thụ. Tôi có thể đặt một thành phần Polyme vào trang JSP, mẫu Express.js, chế độ xem ASP.NET, khung nhìn Backbone ... bên trong thành phần React. Nghĩa đen là bất cứ nơi nào bạn có thể sử dụng HTML, bạn có thể sử dụng một thành phần Polyme. Những người đang thiết kế để tái sử dụng đang tìm kiếm các tiêu chuẩn web, bởi vì các tiêu chuẩn là hợp đồng giúp dễ dàng làm cho mọi thứ tương thích với nhau. YouTube tiếp tục tạo ra nhiều nội dung hơn trong Polyme (nguồn: Polyme đạt được các thành phần thông qua tiêu chuẩn Thành phần Web và bằng cách sử dụng thông số Phần tử tùy chỉnh, Polyme có thể tạo ra các thành phần mà trình duyệt chỉ cần biết cách tiêu thụ. Tôi có thể đặt một thành phần Polyme vào trang JSP, mẫu Express.js, chế độ xem ASP.NET, khung nhìn Backbone ... bên trong thành phần React. Nghĩa đen là bất cứ nơi nào bạn có thể sử dụng HTML, bạn có thể sử dụng một thành phần Polyme. Những người đang thiết kế để tái sử dụng đang tìm kiếm các tiêu chuẩn web, bởi vì các tiêu chuẩn là hợp đồng giúp dễ dàng làm cho mọi thứ tương thích với nhau. YouTube tiếp tục tạo ra nhiều nội dung hơn trong Polyme (nguồn: Tôi có thể đặt một thành phần Polyme vào trang JSP, mẫu Express.js, chế độ xem ASP.NET, khung nhìn Backbone ... bên trong thành phần React. Nghĩa đen là bất cứ nơi nào bạn có thể sử dụng HTML, bạn có thể sử dụng một thành phần Polyme. Những người đang thiết kế để tái sử dụng đang tìm kiếm các tiêu chuẩn web, bởi vì các tiêu chuẩn là hợp đồng giúp dễ dàng làm cho mọi thứ tương thích với nhau. YouTube tiếp tục tạo ra nhiều nội dung hơn trong Polyme (nguồn: Tôi có thể đặt một thành phần Polyme vào trang JSP, mẫu Express.js, chế độ xem ASP.NET, khung nhìn Backbone ... bên trong thành phần React. Nghĩa đen là bất cứ nơi nào bạn có thể sử dụng HTML, bạn có thể sử dụng một thành phần Polyme. Những người đang thiết kế để tái sử dụng đang tìm kiếm các tiêu chuẩn web, bởi vì các tiêu chuẩn là hợp đồng giúp dễ dàng làm cho mọi thứ tương thích với nhau. YouTube tiếp tục tạo ra nhiều nội dung hơn trong Polyme (nguồn:http://react-etc.net/entry/youtube-is-being-rebuilt-on-web-components-and-polymer ), và tôi chỉ có thể tưởng tượng khía cạnh dựa trên tiêu chuẩn của Polyme là lý do tại sao. Trình phát YouTube ở giữa trang YouTube có thể được biến thành một thành phần lấy nguồn nội dung làm tài sản và đột nhiên bất kỳ ai muốn nhúng trình phát YouTube vào trang của họ đều có thể sử dụng chính xác mã trình phát YouTube mà họ đang sử dụng và họ có thể làm như vậy đơn giản bằng cách dán thẻ vào trang của họ.

Tóm lược

Tôi có thể thấy chắc chắn có một số khía cạnh hấp dẫn của React ngay bây giờ. Nếu tất cả những gì bạn đang sử dụng là React, bạn có thể xây dựng một số vật dụng và một số thành phần và khai báo lại chúng ở mọi nơi. Nhưng tôi nghĩ React sẽ tốt hơn rất nhiều nếu nó sử dụng một số tiêu chuẩn Thành phần Web để đạt được những gì nó làm, thay vì tắt và xây dựng trình duyệt trong trình duyệt và một cơ chế phức tạp để giữ mọi thứ đồng bộ.

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.