本篇文章將簡述 React.js 特殊的語法 —— JSX 的基本概念
相信在學 React.js 的各位,一定都會看到諸如下列的 「JSX」 語法,一個看起來像 HTML 又潛藏在 JavaScript 中(然後還可以你中有我我中有你)的怪東西。
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
今天,我們就來好好剖析一下 JSX 的語法概念 ——
這篇文章先假定各位大致知道 HTML 和 JavaScript 的基本運作語法
不過稍後也會稍微提點一下這方面的概念
需要詳細介紹歡迎各位搜尋 iT 邦幫忙 或 MDN Web Docs
或者期待一下,反應若不錯的話日後將有機會較為詳細的講述 Web Programming 相關的各項技術內容~
回顧 HTML
HTML,全名 HyperText Markup Language,中文為「超文本標記語言」
主旨就是運用標籤(tag)鑲嵌在文字中,對文字內容進行特殊的標記,來呈現更彈性多元的網頁內容。
舉例如下
<p>
I <b>love</b> <a href="https://weikaiwei.com/">City Grandma</a>!
</p>
上面程式碼的 <p>
</p><b> </b>
<a ...> </a>
就是標籤(tag),一般有開始標籤(<p>
)和結束標籤(</p>
)兩種,開始到結束中間的這段文字表達網頁的內容,而標籤本身則用來標記這段文字內容要以什麼形式類別呈現,例如
中間的是一段段落(paragraph)、p
b
之間的文字要粗體(bold)等等,而像 a
則是表達一個超連結(hyperlink,英文取自 anchor,指可以被點選連到其他網站的內容)。
在這邊要注意的是,像 <a>
這種連結由於通常會對應到一串目的地的網址,因此 <a>
tag 通常不會只有 <a>一些文字</a>
這樣,而是會在開始標籤上加上 href="https://example.com"
這串目標網址,因此 HTML 的 tag 我們通常可以描述為
<標籤種類 標籤屬性1="屬性內容1..." 標籤屬性2>標籤內容文字</標籤種類>
這樣的形式。「標籤種類」是指示這段文字在網頁上的角色,而這段文字除了內容本身如果有其他資料,會用一串「屬性、內容」來呈現——這在 JSX 語法中扮演了很重要的角色,稍後各位會看到。
回顧 JavaScript
在這裡要提及的是 JavaScript 的函數和類別兩個概念。
Function
最一般的 JavaScript 函數一般寫作
function add(x, y) {
return x + y;
}
其中 add
是函數名,x
、y
是變數名,而大括號內部會寫明要對這些傳進來的變數做什麼一系列的操作,最後再由 return
後面寫的東西將結果回傳。同樣的寫法可以用「箭頭函數」寫成
const add = (x, y) => x + y;
Class
實際上 JavaScript 是弱型別語言,class 是 function 的語法糖,有關 class、function 和 this 的各種愛恨情仇留待日後詳述⋯⋯
一個 JavaScript class 的定義寫作
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greeting() {
console.log(`Hello, my name is ${this.name}.`);
}
}
class Student extends Person {
constructor(name, age, school) {
super(name, age);
this.school = school;
}
student_info() {
console.log(`Hello, I am from ${this.school}.`);
}
}
let jeff = new Student("Jeff", 25, "NTU");
jeff.greeting(); // print out "Hello, my name is Jeff."
jeff.student_info(); // print out "Hello, I am from NTU."
Wrap it up
總之,從上面我們可以看到,function 可以定義一個傳入一些原料/資料並製作出產品/結果的過程,而 class 可以定義一項「物件(object)」並將其視為一個劇本中的角色並指派一些屬性與動作。
好了,說了這麼多,回來看 JSX 吧~
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
看上面這段 Create React App 自動生成的預設程式碼,各位可以看到最外層是一個 JS function,但在 return 後面接的那個「要被回傳的結果」卻是一段 HTML。
換言之,這是一個會回傳 HTML 的 JS function——各位大致這樣想就行了。
一般 JS 作為程式語言,JS function 回傳的東西當然是 JS 的變數(資料、物件),但在傳統純 JS 的寫法中我們經常得
var hyperlink = document.createElement("a");
// display <a></a>
hyperlink.setAttribute("href", "https://weikaiwei.com/");
hyperlink.innerText = "Click me";
// display <a href="https://weikaiwei.com/">Click me</a>
這樣進行一番操作,用 JS 的語法去慢慢把 HTML 的 tag 給搭建出來。但有了 JSX 這樣「在 JS 中直接寫 HTML」的語法,我們可以很簡單的直接
let hyperlink = <a href="https://weikaiwei.com/">Click me</a>;
把這件事完成。我們可以把 tag 之間圍起來的部分當成某一個 object(實際上也是),這樣想之後其他外面的部分就只是普通的 JS 了。
至於這個 tag 內部也很有趣,如果我們希望 tag 內部的任何內容(包含標籤屬性的內容與文字內容)可以是某個 JS 的變數(variable)或表達式(expression,指可以被算成某個值、能被存成某個變數的程式碼),可以在內嵌的 HTML 中用大括號「 {
}
」將 JS 程式碼包起來,例如
let hyperlink = <a href="https://weikaiwei.com/" + {1 + 2}>Click me {add(3, 4)} times!</a>;
// You will get
// <a href="https://weikaiwei.com/3">Click me 7 times!</a>
簡單說就是
js js js ... js <html html html {js js js ... js} html html>html html</html> js js js ...
也就是「用 tag 在 JS 內寫 HTML」,再「用 {} 在 HTML 內寫 JS」,因此以下操作是被允許的
js js js ... js <html html html {js js
js js js <html html ... html>html {js js ... js}</html> js
js ... js} html html>html html</html> js js js ...
不過慣例上,HTML tag 如果比較長,通常外圍會用小括號(
)
包起來來讓程式碼比較好閱讀
回到最前面的例子
最後來看一下最一開始的例子
import logo from './logo.svg'; // 這邊是 JS,把 SVG 圖檔輸入進來
import './App.css'; // 這邊是 JS,把 CSS 樣式表輸入進來
function App() { // JS,定義了一個 function
return ( // 要回傳一個東西,是一個 HTML tag。因為比較長所以用 () 包起來
<div className="App">
<!-- 前一行第一個 “<” 出現了,程式從這邊開始變 HTML -->
<header className="App-header">
<!-- 這邊的 `logo` 是一個 JS 變數,代表圖片,
因此要用 {} 告訴編譯器這裡是 JS 而不是單純的 "logo" 文字
剩下的還是 HTML -->
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<!-- 進到最後一個 HTML tag 的 closed tag 了,之後回到 JS -->
</div>
); // 這邊後面都是 JS
}
export default App;
實際上 React 為了讓 HTML 可以跟 JS 「共同演出」因此有做了一些調整,例如 class
為了避免跟 JS 的 class
關鍵字衝突,因此會改寫成 className
,在轉換成 HTML 時會變回 class
來使瀏覽器能夠正常運作;最後,有了這個 App
函數,我們要怎麼讓網頁裡面出現這些 div 等等的東西呢?
注意了!不是 App()
,而是 <App></App>
(或通常寫成 <App />
)!
待續⋯⋯
今天先到這邊,讓各位大致看得懂 JSX 語法,至於 React 整套運作流程與用法(還有 functional / class component 、props、states 等等一堆)⋯⋯坑先挖了,希望有機會可以儘早回來填上,有什麼想討論的也歡迎各位留言,更期望大家可以多多分享,期待能幫助到各位。就先這樣囉~
這邊有個不錯的 reference
https://blog.bitsrc.io/demystifying-jsx-building-your-own-jsx-parser-from-scratch-caecf58d7cbd