網上各種言論說 React 上手比 Vue 難,可能難就難不能深刻理解 JSX,或者對 ES6 的一些特性理解得不夠深刻,導致覺得有些點難以理解,然後說 React 比較難上手,還反人類啥的,所以我打算寫兩篇文章來講新手學習 React 的時候容易迷惑的點寫出來,如果你還以其他的對於學習 React ...
網上各種言論說 React 上手比 Vue 難,可能難就難不能深刻理解 JSX,或者對 ES6 的一些特性理解得不夠深刻,導致覺得有些點難以理解,然後說 React 比較難上手,還反人類啥的,所以我打算寫兩篇文章來講新手學習 React 的時候容易迷惑的點寫出來,如果你還以其他的對於學習 React 很迷惑的點,可以在留言區里給我留言。
為什麼要引入 React
在寫 React 的時候,你可能會寫類似這樣的代碼:
import React from 'react'
function A() {
// ...other code
return <h1>前端桃園</h1>
}
你肯定疑惑過,下麵的代碼都沒有用到 React,為什麼要引入 React 呢?
如果你把 import React from ‘react’
刪掉,還會報下麵這樣的錯誤:
那麼究竟是哪裡用到了這個 React,導致我們引入 React 會報錯呢,不懂這個原因,那麼就是 JSX 沒有搞得太明白。
你可以講上面的代碼(忽略導入語句)放到線上 babel 里進行轉化一下,發現 babel 會把上面的代碼轉化成:
function A() {
// ...other code
return React.createElement("h1", null, "前端桃園");
}
因為從本質上講,JSX 只是為 React.createElement(component, props, ...children)
函數提供的語法糖。
為什麼要用 className 而不用 class
React 一開始的理念是想與瀏覽器的 DOM API 保持一直而不是 HTML,因為 JSX 是 JS 的擴展,而不是用來代替 HTML 的,這樣會和元素的創建更為接近。在元素上設置
class
需要使用className
這個 API:const element = document.createElement("div") element.className = "hello"
瀏覽器問題,ES5 之前,在對象中不能使用保留字。以下代碼在 IE8 中將會拋出錯誤:
const element = { attributes: { class: "hello" } }
解構問題,當你在解構屬性的時候,如果分配一個
class
變數會出問題:const { class } = { class: 'foo' } // Uncaught SyntaxError: Unexpected token } const { className } = { className: 'foo' } const { class: className } = { class: 'foo' }
其他討論可見:有趣的話題,為什麼jsx用className而不是class
為什麼屬性要用小駝峰
因為 JSX 語法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase
(小駝峰命名)來定義屬性的名稱,而不使用 HTML 屬性名稱的命名約定。
來自 JSX 簡介
為什麼 constructor 里要調用 super 和傳遞 props
這是官網的一段代碼,具體見:狀態(State) 和 生命周期
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
而且有這麼一段話,不僅讓我們調用 super
還要把 props
傳遞進去,但是沒有告訴我們為什麼要這麼做。
不知道你有沒有疑惑過為什麼要調用 super
和傳遞 props
,接下來我們來解開謎題吧。
為什麼要調用 super
其實這不是 React 的限制,這是 JavaScript 的限制,在構造函數里如果要調用 this,那麼提前就要調用 super,在 React 里,我們常常會在構造函數里初始化 state,this.state = xxx
,所以需要調用 super。
為什麼要傳遞 props
你可能以為必須給 super
傳入 props
,否則 React.Component
就沒法初始化 this.props
:
class Component {
constructor(props) {
this.props = props;
// ...
}
}
不過,如果你不小心漏傳了 props
,直接調用了 super()
,你仍然可以在 render
和其他方法中訪問 this.props
(不信的話可以試試嘛)。
為啥這樣也行?因為React 會在構造函數被調用之後,會把 props 賦值給剛剛創建的實例對象:
const instance = new YourComponent(props);
instance.props = props;
props
不傳也能用,是有原因的。
但這意味著你在使用 React 時,可以用 super()
代替 super(props)
了麽?
那還是不行的,不然官網也不會建議你調用 props 了,雖然 React 會在構造函數運行之後,為 this.props
賦值,但在 super()
調用之後與構造函數結束之前, this.props
仍然是沒法用的。
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// Inside your code
class Button extends React.Component {
constructor(props) {
super(); //