前情提要:
昨天把工作室(環境)都打造好了。
大家還記得昨天的環境建置的許下的兩個願望嗎?
把JSX轉成瀏覽器看得懂的語法
就是它!把JSX轉成瀏覽器看得懂的語法
到底什麼是JSX?
我們看看react的解釋
const element = <h1>Hello, world!</h1>;
This funny tag syntax is neither a string nor HTML.
It is called JSX, and it is asyntax extension
to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript.
好,React説JSX只是javascript的擴展語法
,我們透過JSX來描繪UI
的形貌,但看起來他就是個html啊,來證明給我看吧。
這時候我們就要請出Babel好朋友幫我們把JSX打回原形
你誰啊???!!!
我還是左轉去寫Vue好了
React說等等,其實沒這麼難懂,Babel轉換過的JSX透過React.createElement
產出React element,我們來看看裡面的參數需要什麼:(reference)
React.createElement(
type,
[props],
[...children]
)
tag name string
(如:'div'或'span'), React component
(class或function)或React fragment
什麼什麼什麼,你在說什麼我什麼都不懂
好的,我們對照babel處理前的JSX和babel處理後的javascript
// JSX
(<h1>Hello, world!</h1>)
// Babel轉換
React.createElement("h1", null, "Hello, world!");
翻譯蒟蒻:我要用React.createElmet這個方法建立一個h1元素,裡面沒有屬性值,但內容文字是Hello, world!
好像有點感覺了,那屬性值是什麼?可以加html的attribute嗎?
如果我想在我的h1元素加上class的話要怎麼處理呢?
// JSX
(<h1 className="title">Hello, world!</h1>)
// Babel轉換
React.createElement("h1", { className: "title" }, "Hello, world!");
翻譯蒟蒻:我要用React.createElmet這個方法建立一個h1元素,className為"title",內容文字是Hello, world!
加上id後,原本第二個參數是null,已經轉成{ className: "title" }
。
好像有點懂了!那如果我的html是巢狀元素(nesting element)呢?
// JSX
(<p id="motto">The struggle is <strong>real</strong>.</p>)
// Babel轉換
React.createElement(
"p",
{ id: "motto" },
"The struggle is ",
React.createElement("strong", null, "real"),
"."
);
大家可以看到我在content (The struggle is real.) 裡面加了strong元素想強調real這個詞,所以建立一個新元素。往後每增加一個element就要用一次React.createElement,有多少用多少,免費不用錢,長得醜就是了。
我想這也是官方推薦使用JSX的原因。
注意事項
不曉得大家有沒有注意到上面的className
,其實它代表的就是html的class
,因為class是ES6的保留字,為了避免混淆所以區分。
面對相同狀況的苦主之二還有label的for
,for在javascript也是有特殊功能的,所以在JSX上用到的label for需替換成htmlFor
另外,React DOM使用camelCase作為屬性命名規範,所以像是tabindex="0"
,在JSX裡會變成tabIndex="0"
,寫JSX時請大家留意這點。但...凡事都有例外XD
The exception is
aria-*
anddata-*
attributes, which should be lowercased. For example, you can keep aria-label as aria-label.
來源:React-DOM Elements
以上就是另外需要注意的地方
延續前天我們建立的開發環境,測試的時候我有將最基本的React雛形貼上index.js內,來回顧一下:
import React from 'react'; //匯入react library
import ReactDOM from 'react-dom'; //匯入react-dom library
const App = () => {
//小括號包起來的就是用JSX建立的React element
return (
<div>
Hello World!
</div>
);
};
ReactDOM.render(<App/>, document.getElementById('app'));
昨天能夠順利把Hello World!印到頁面上多虧ReactDOM.render
的幫忙。
react-dom提供了幾款與DOM相關的特定方法供開發者使用,render應該是最常見的一種。Reference
ReactDOM.render(element, container[, callback])
第一個參數是element,第二個參數是container,第三個callback。
<App/>是誰? (⊙o⊙)
<App/>是React的component
,這個component會回傳React element
(也就是<div>Hello World!</div>
),element完成了總要有個container(容器)放,我們就指定DOM上id名為app的element擔此大任。
那如果我今天不想用JSX呢?我們來改寫一次
import React from 'react';
import ReactDOM from 'react-dom';
const App = () => {
return (
React.createElement('div', null, 'Hello World!')
);
};
ReactDOM.render(React.createElement(App, null), document.getElementById('app'));
等等!第一個React.createElement我懂,是來建立div element的,但第二個React.createElement(App, null, null)
是什麼,我們剛剛有見過他嗎?上一段我們提到<App/>
是React的component,然後現在是???
時間拉回一開始我們在說明React.createElement時......
React.createElement(
type,
[props],
[...children]
)
React component
(class或function)或React fragment第一個參數type
其實也可以放入React component
,所以基本上下面兩句語法是可以理解是相同功能的,差異只在JSX是否介入。
// JSX
<App/>
// Babel轉換
React.createElement(App, null, null)
反過來想,使用React component是因為透過JSX處理才變成簡潔乾淨的吧!
至於component是什麼?怎麼用?這又是明天的故事了...
回顧今日
結語
再回顧一次JSX,覺得很多知識就跟拔絲地瓜一樣拔不完,只能慢慢累積了XD
如果有誤人子弟的地方還請大家指正,謝謝大家收看。
相關參考資料