Giới thiệu cú pháp JSX khi lập trình webapp với React
Ngay từ đầu bài viết, chúng tôi phải nhấn mạnh điều này để các bạn đừng bao giờ quên:
Không trình duyệt nào hiểu được mã nguồn JSX.
JSX là gì?
JSX là cú pháp (syntax) kết hợp giữa JavaScript và XML chứ không phải là một ngôn ngữ hoàn chỉnh. Nó cho phép lập trình viên có thể viết mã XML bên trong file mã nguồn JavaScript.
Kết hợp với kỹ thuật “CSS Module” hoặc kỹ thuật “Styled Component”, người ta có thể lập trình HTML và CSS bằng JavaScript, tận dụng được thế mạnh của JS để biến kiến trúc web app theo component thành hiện thực, cụ thể là khả năng chỉ tải mã nguồn khi cần thiết (lazy-loading) và giới hạn phạm vi (scope) của CSS mà không cần đặt tên CSS Class dài dòng theo chuẩn BEM.
Trình duyệt không hiểu được JSX
JSX là viên thuốc bọc đường được sinh ra dành cho lập trình viên. Mã nguồn JSX phải thông qua một bước chuyển mã (transpile) bằng công cụ Babel để biến thành mã JS thuần túy, nhờ vậy trình duyệt mới chạy được.
Ví dụ code JSX dưới đây:
<Form> <MaskInput type="date" value={val} /> </Form>
Sau khi được transpile thành code JS sẽ nom như sau:
React.createElement(Form, null, React.createElement(MaskInput, { type: "date", value: val, } );
Những điều cần nhớ khi làm việc với JSX
1. Có thể được gán vào biến của JavaScript
Như các bạn đã thấy ở trên, bản chất của JSX khi chạy thực tế là một object được trả về từ hàm React.createElement
, cho nên nó chẳng qua là một kiểu dữ liệu của JS thuần tùy, dĩ nhiên nó có thể được gán vào biến, truyền vào hàm dưới dạng tham số…
Khi code:
const myForm = ( <Form> <MaskInput value={val} /> </Form> );
Thực tế:
const myForm = React.createElement(...);
2. Thẻ đơn phải tự đóng
Đây là luật của XML. Hãy xem những ví dụ sau:
<div><strong>Đăng ký</strong></div> <img src="photo.jpg" /> <MaskInput value={val} /> <div id="dataHolder" />
Dòng 1 có thẻ mở và thẻ đóng. Dòng 2-3 là thẻ tự đóng (self-closed tag). Lưu ý dòng 4: Mặc dù trong HTML <div>
là thẻ có cặp mở và đóng, nhưng trong JSX nếu nó không chứa gì bên trong thì nó là thẻ tự đóng.
3. Chỉ có một node gốc
Một luật khác thừa hưởng từ XML. Một đoạn mã JSX (JSX fragment) bắt buộc phải có một và chỉ một node gốc.
Đoạn mã sau là SAI cú pháp JSX:
<h3>Đăng ký</h3> <form> <img src="photo.jpg"> </form>
Sửa lại như thế này thì đúng, NHƯNG….
<div> <h3>Đăng ký</h3> <form> <img src="photo.jpg"> </form> </div>
… cách này thêm thẻ <div
sẽ phá layout có sẵn của trang web, cho nên giải pháp là dùng thẻ “giả” <React.Fragment>...</React.Fragment>
, hoặc viết ngắn gọn là <>...</>
.
<React.Fragment> <h3>Đăng ký</h3> <form> <img src="photo.jpg" /> </form> </React.Fragment>
cũng tương đương với
<> <h3>Đăng ký</h3> <form> <img src="photo.jpg"> /form> </>
4. Thực thi code JS hoặc truyền biến trong cặp ngoặc móc { }
JSX có thể được viết ở giữa một đoạn code JS, nhưng nếu muốn viết code JS ở giữa một đoạn code JSX thì phải nằm giữa cặp ngoặc móc { }
.
const price = 123; const fruits = ['pearl', 'berry' ,'melon']; const myForm = ( <Form> <MaskInput value={'$' + price} /> { fruits.map(f => ( <input type="radio" value={f} /> )} </Form> );
Ở dòng 5, chúng ta thực hiện phép cộng chuỗi bằng JS rồi truyền kết quả vào prop “value” của component “MaskInput”.
Dòng 6-8, dùng hàm map()
của JS để tạo ra nhiều radio button.
5. Tự hiểu mảng của JSX
Đoạn mã với hàm map()
ở trên có tác dụng giống hệt với đoạn mã sau:
... const fruits = ['pearl', 'berry' ,'melon']; const radios = []; for (let f in fruits) { radios.push(<input type="radio" value={f} />); } const myForm = ( <Form> { radios } </Form> );
Chỉ cần truyền một array chứa các JSX Fragment, thì array đó sẽ tự động được duyệt qua để render những JSX Fragment bên trong.
Những câu hỏi thường gặp
1. JSX có phải là ngôn ngữ Front-end mới không?
Không. Ngôn ngữ lập trình phía Front-end hiện nay chỉ có JavaScript và WebAssembly, nhưng WebAssembly quá mới và không dùng để code trực tiếp, nên JavaScript vẫn được coi là độc tôn.
2. Trình duyệt nào hỗ trợ JSX?
Không trình duyệt nào hiểu được JSX. JSX phải được transpile thành mã JS để chạy trên trình duyệt.
3. JSX chỉ dùng được cho React thôi phải không?
Không chỉ có React. Mặc định Bable sẽ transpile mã JSX thành lời gọi hàm React.createElement
, nhưng vẫn có thể cấu hình để Babel dùng hàm khác, ví dụ như thư việc Preact thì gọi hàm Preact.createElement
, ngoài ra còn có thư viện Inferno v.v. và v.v.
(Còn nữa, sẽ liên tục bổ sung)
Facebook Comments