1. 元件定義
元件是React的核心概念,元件將應用的UI拆分成獨立的、可複用的模組。
定義元件的兩種方式:
(1)類元件:使用ES6 class
(2)函式元件:使用函式
使用class定義元件的兩個條件:
(1)class繼承自React.Component
(2)class內部必須定義render(),render()返回代表該元件UI的React元素。
1.1 基本元件
HelloWorld.js:
import React, { Component } from "react" class HelloWorld extends Component { render() { return ( <h1>Hello World!</h1> ); } } export default HelloWorld;
Index.js:
import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './components/HelloWorld' ReactDOM.render(<HelloWorld />, document.getElementById('root'));
說明:ReactDOM.render()需要先匯入react-dom庫,這個庫會完成元件所代表的虛擬DOM節點到瀏覽器的DOM節點的轉換。
使用export default預設匯出元件。
default表示可以在別的檔案中使用import HelloWorld from './components/HelloWorld'匯入這個模組;
如果沒有default,則需要使用import { HelloWorld } from './components/HelloWorld'來匯入模組。
1.2 元件的props
元件props用於把父元件中的資料或方法傳遞給子元件。
props是一個簡單結構的物件,它包含的屬性是由元件作為JSX標籤所使用的屬性組成。
示例(1):
import React, { Component } from "react" class HelloWorld extends Component { render() { return ( <h1>Hello { this.props.name }!</h1> ); } } export default HelloWorld;
import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './components/HelloWorld' ReactDOM.render(<HelloWorld name={ 'Libing' } />, document.getElementById('root'));
示例(2):
TodoItem.js
import React, { Component } from 'react'; class TodoItem extends React.Component { render() { const { id, title } = this.props; return ( <li>{ id }-{ title }</li> ); } } export default TodoItem;
TodoList.js
import React, { Component } from 'react'; import TodoItem from './TodoItem'; const data = [ { id: 1, title: 'ToDo' }, { id: 2, title: 'In Progress' }, { id: 3, title: 'Done' } ] class TodoList extends Component { render() { return ( <ul> { data.map((item) => <TodoItem id={ item.id } title={ item.title } /> ) } </ul> ); } } export default TodoList;
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import TodoList from './components/TodoList' ReactDOM.render(<TodoList />, document.getElementById('root'));
1.3 元件的state
元件的state是元件內部的姿態,state的變化最終將反映在元件UI的變化。
在元件的構造方法constructor中通過this.state定義元件的初始狀態,並通過呼叫this.setState()改變元件狀態,進而元件UI會隨之重新渲染。
修改TodoItem.js
import React, { Component } from 'react'; class TodoItem extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } handleClick() { let count = this.state.count; count++; this.setState({ count: count }); } render() { const { id, title } = this.props; return ( <li> { id }-{ title }-{ this.state.count } <button onClick={() => { this.handleClick(); }} >+1</button> </li> ); } } export default TodoItem;
1.4 有狀態元件和無狀態元件
state用來反映元件內部狀態的變化。
無狀態元件:如果一個元件的內部狀態是不變的,則用不到state。
有狀態元件:如果一個元件的內部狀態會發生變化,就需要使用state來儲存變化。
示例:
HelloWorld.js
import React from 'react'; function HelloWorld(props) { return <h1>Hello { props.name }!</h1>; } export default HelloWorld;
注:由於使用了JSX,需要匯入React。
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './components/HelloWorld' ReactDOM.render(<HelloWorld name={ 'World' } />, document.getElementById('root'));
在使用無狀態元件時,儘量定義函式元件。
在開發React應用時,要先思考哪些元件應該設計成有狀態元件,哪些元件應該設計成無狀態元件。並且,儘可能多的使用無狀態元件,無狀態元件不用關心狀態變化,只聚焦於UI的展示,更容易複用。
React應用元件設計的一般思路:通過定義少數的有狀態元件管理整個應用的狀態變化,並且將狀態通過props傳遞給其餘的無狀態元件,由無狀態元件完成頁面絕大部分UI的渲染。
有狀態元件主要關注處理狀態變化的業務邏輯,無狀態元件主要關注元件的UI渲染。
1.5 屬性校驗和預設屬性
1.5.1 屬性校驗
React提供PropTypes用於校驗元件屬性的型別。
import React from 'react'; import PropTypes from 'prop-types' class HelloWorld extends React.Component { render(){ return (<h1>Hello { this.props.name }!</h1>); } } HelloWorld.propTypes = { name: PropTypes.string } export default HelloWorld;
import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './components/HelloWorld' ReactDOM.render(<HelloWorld name={'World'} />, document.getElementById('root'));
若屬性型別設定number,則報錯提示。
import React from 'react'; import PropTypes from 'prop-types' class HelloWorld extends React.Component { render(){ return (<h1>Hello { this.props.name }!</h1>); } } HelloWorld.propTypes = { name: PropTypes.number } export default HelloWorld;
import React from 'react'; import PropTypes from 'prop-types' class HelloWorld extends React.Component { render(){ return (<h1 style={ this.props.style }>Hello { this.props.name }!</h1>); } } HelloWorld.propTypes = { name: PropTypes.string, style: PropTypes.shape ({ color: PropTypes.string, fontSize: PropTypes.number }).isRequired } export default HelloWorld;
import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './components/HelloWorld' ReactDOM.render(<HelloWorld style={{ color: 'red', fontSize: 14 }} name={'World'} />, document.getElementById('root'));
示例中,style是一個物件,包含兩個屬性color和fontSize,color是字串型別,fontSize是數字型別。
如果屬性是元件的必須屬性,在PropTypes的型別屬性上呼叫isRequired。
1.5.2 預設屬性
React提供為元件屬性指定預設值,元件defaultProps。當元件屬性未被賦值時,元件會使用defaultProps定義的預設屬性。
import React from 'react'; class HelloWorld extends React.Component { render(){ return (<h1 style={ this.props.style }>Hello { this.props.name }!</h1>); } } HelloWorld.defaultProps = { name: 'Libing' } export default HelloWorld;
import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './components/HelloWorld' ReactDOM.render(<HelloWorld />, document.getElementById('root'));
1.6 元件樣式
為元件新增樣式的方法主要有兩種:外部樣式表和內聯樣式。
1.6.1 外部CSS樣式表
樣式表引入的兩種方式:
(1)在使用元件的HTML頁面中通過標籤引入
<link rel="stylesheet" type="text/css" href="style.css" >
(2)把樣式表當作一個模組,在使用該樣式表的元件中,匯入樣式表檔案
import './style.css'; // 相對路徑
React元素要使用className代替class作為選擇器。
/src/components/HelloWorld.css
.hello-world { color: red; font-size: 14px; }
/src/components/HelloWorld.js
import React from 'react'; import './HelloWorld.css'; class HelloWorld extends React.Component { render(){ return (<h1 className='hello-world'>Hello World!</h1>); } } export default HelloWorld;
第一種引入樣式表的方式常用於該樣式表作為整個應用的所有元件(基礎樣式表),第二種引入樣式表的方式常用於該樣式表作用於某個元件(元件的私有樣式)。
全域性基礎樣式表要可以使用第二種方式引入,一般在應用的入口js檔案中引入,如index.js。
1.6.2 內聯樣式
內聯樣式是一種CSS in JS的寫法:將CSS寫到JS檔案中,用JS物件表示CSS,通過DOM型別節點的style屬性引用樣式物件。
import React from 'react'; class HelloWorld extends React.Component { render(){ return (<h1 style={{ color: 'red', fontSize: '14px' }}>Hello World!</h1>); } } export default HelloWorld;
style使用了兩個大括號{{}},第一個大括號表示style的值是一個JavaScript表示式,第二個大括號表示這個JavaScript表示式是一個物件。
import React from 'react'; class HelloWorld extends React.Component { render(){ const style = { color: 'red', fontSize: '14px' }; return (<h1 style={ style }>Hello World!</h1>); } } export default HelloWorld;