React
是一個聲明式,高效且靈活的用於構建用戶界面的JavaScript
庫。能夠將一些簡短、獨立的代碼片斷組合成複雜的UI界面,這些片斷被稱爲「組件」。javascript
React 大致包含下面這些概念:前端
能夠將UI 拆分爲獨立且複用的代碼片斷,每部分均可獨立維護。
組件,從概念上相似於JavaScript
函數。它接受任意的參數(即 「props」),並返回用於描述頁面展現內容的React 元素
。
自定義組件命名:必須以大寫字母開頭,React 會將以小寫字母開頭的組件視爲原生DOM標籤。vue
import React from 'react'; // React 的核心庫 import ReactDOM from 'react-dom'; // 提供與 DOM 相關的功能 class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } ReactDOM.render( <ShoppingList name="Mark" />, document.getElementById('root') );
React 應用都是構建在組件之上。ShoppingList
就是一個React 組件類型,ReactDOM.render
函數會將組件方到頁面上的某個節點元素中。(render
返回了一個 React 元素
,這是一種對渲染內容的輕量級描述。)
大多數 React
應用只會調用一次 ReactDOM.render()
。java
其中props
(是 properties 的簡寫) 是組件包含的兩個核心概念之一,另外一個是state
。react
props
接收一些其餘組件的參數(好比上方的 name ),來配置組件,全部 React
組件都必須像純函數同樣保護它們的 props
不被更改。git
state
來實現所謂「記憶」的功能。能夠經過 React
組件的構造函數中設置 this.state
;this.state
應該被視爲一個組件的私有屬性。
修改this.state
值須要經過this.setState
方法賦值,有些 props
值或 state
值多是異步更新的,使用對象賦值的方式更改 state
可能無效,可以使用回調傳參方式更新github
this.setState( (state,props)=> ({count:state.count + props.count}) );
經過
class
語法來定義組件,必須包含render()
方法,而且繼承於React.Component
。
類組件必須包含render()
,而且return 只能返回一個父元素(相似vue中的template中必需要有一個父元素)。數組
class Square extends React.Component { /** * @name constructor * @param {*} props * 每次定義子類的構造函數時,都必須調用 super 方法。 * 所以,在全部含有構造函數的React組件中,構造函數必須以super(props)開頭 * state 保存着組件中的數據 相似 vue 中的 data 屬性 */ constructor(props) { super(props); this.state = { value:null }; } render() { return ( <button className="square" onClick = {()=>{this.setState({value:'X'})} }> {this.state.value} </button> ); } }
render方法中的onClick
事件監聽函數中調用this.setState
方法,能夠設置this.state
中的屬性
推薦使用箭頭函數,避免this 形成困擾。dom
簡單組件是一個函數,不須要使用class
關鍵字,固然就沒有constructor和state
異步
const Square = (props) => { return (<button className= "square" onClick= { props.onClick} >{ props.value } </button>) }
input
、<select>
、<textarea>
等表單的狀態發生改變,都得同時經過onChange
事件改變組件中的state
值,不然表單不會發生變化。經過這種方式控制取值的表單叫作受控組件
。
class Input extends Component { constructor(props){ super(props) this.state = { value:'3s' } } render (){ return <input type="text" value = {this.state.value} /> // 用戶在表單中輸入任何信息都是無效的 } } // 使用事件來改變 render (){ return ( <input type="text" value = {this.state.value} onChange = {({target}) =>{ this.setState({ value:target.value }) }} /> ) }
React受控組件更新state的流程:
onChange
事件state
將組件變成數組集合放入花括號中便可渲染多個組件,一般使用數組的map()
方法
const Lis = (props) => { const lis = props.list.map((val,key)=> <li key={key}>{key+1}</li>); return <ul>{lis}</ul> } const list = Array(7).fill(null); ReactDOM.render( <Lis list = {list} />, document.getElementById('root') );
當多個組件發生數據聯動時,建議將共享狀態提高到最近的共同父組件中去。
/* * @Author: Owen * @Date: 2019-07-23 23:55:17 * @Last Modified by: Owen * @Last Modified time: 2019-07-29 16:06:22 */ import React,{Component} from 'react'; import {render} from 'react-dom'; // 溫度轉化器 let toConvert = (temperature,callback) => { let num = parseInt(temperature); if(Number.isNaN(num)) return '' num = callback(num) return Math.round(num*1000)/1000; } const BoilingVerdict = (props) =>{ let text = props.temperature > 100?'':' not'; return (<p> The water would{text} boil. </p>) } // 公共input組件只接收行爲和狀態 const TemperatureInput = (props) =>{ return ( <input value ={props.temperature} onChange = {props.valueChange} /> ) } // 父組件設置行爲和狀態 class Calculator extends Component { constructor(props){ super(props) this.state = { temperature:'', scale:'C' } } toFahrenheit({target}) { this.setState({ temperature:target.value, scale:'F' }) } toCelsius({target}) { this.setState({ temperature:target.value, scale:'C' }) } render() { let {temperature,scale} = this.state; let celsius = scale === 'F'?toConvert(temperature,(val)=>(val - 32)*5/9):temperature; let fahrenheit = scale === 'C'?toConvert(temperature,(val)=>val*9/5+32):temperature; return ( <div> <div> Celsius: <TemperatureInput scale ='C' temperature = {celsius} valueChange = {this.toCelsius.bind(this)} /> </div> <div> Fahrenheit: <TemperatureInput scale ='F' temperature = {fahrenheit} valueChange = {this.toFahrenheit.bind(this)} /> </div> <div><BoilingVerdict temperature = {this.state.temperature} /></div> </div> ); } } render(<Calculator />,document.querySelector('#root'))
在就React
應用中,任何科比數據應當只有一個相對應的數據源,一般,多個組件須要相同數據,能夠將數據提高到這些組件的共同父組件中。依靠自上而下的數據流,去控制組件,而不是嘗試在不一樣組件同步 state
。這樣會減小未來排查和隔離BUG所須要的工做量
有些組件沒法提早知曉它們子組件的具體內容,須要留坑,那麼也能夠經過 props
來佔位。
props.children
件起始標籤和結束標籤之間的內容都會被將{props.children}
替換。
function FancyBorder(props) { return ( <div className={'FancyBorder FancyBorder-' + props.color}> {props.children} </div> ); } function WelcomeDialog() { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> Welcome </h1> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder> ); }
由於 React元素
本質就是對象,因此能夠將它當中參數像其餘數據同樣傳遞。
function SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); } function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); }
每一個 JSX 元素都是調用 React.createElement() 的語法糖。通常來講,若是你使用了 JSX,就再也不須要調用
createElement()
或createFactory()
方法。
React 提出的一種叫 JSX 的語法,這應該是最開始接觸 React 最不能接受的設定之一,由於前端被「表現和邏輯層分離」這種思想「洗腦」過久了。實際上組件的 HTML 是組成一個組件不可分割的一部分,可以將 HTML 封裝起來纔是組件的徹底體.
JSX是一個JavaScript語法擴展。它相似於模板語言,但它具備JavaScript 的所有能力。它最終會被編譯爲
React.createElement()
函數調用,返回稱爲React元素
的普通JavaScript`對象。
推薦使用箭頭函數,避免this 形成困擾
function Square(props) { return ( < button className = "square" onClick = { props.onClick } > { props.value } </button> ); } class Board extends React.Component { constructor(props){ super(props) this.state = { squares: Array(9).fill(null), xIsNext:true, // 先落子,並確認該哪位玩家落子 } } /** * 只接受一個squares副本,而不直接修改自己數據 * 1. 這樣能夠簡化複雜的功能,不可變性使得複雜的特性更容易實現。 * 2. 能夠跟蹤數據的改變,若是直接修改源數據就很難跟蹤變化的數據。 * 3. 能夠幫助咱們在 React 中建立 purecomponents。能夠輕鬆的肯定不可變數據是否發生了改變, * 從而肯定什麼時候對組件進行從新渲染。 * @param {*} i * @memberof Board */ handleClick(i) { const squares = this.state.squares.slice(); squares[i] = this.state.xIsNext? "X":"O"; this.setState({ squares,xIsNext:!this.state.xIsNext }) } renderSquare(i) { // 返回一個 Square 組件 return ( < Square value = { this.state.squares[i] }// 給子組件傳遞 value數據 onClick = {()=> this.handleClick(i)} // 給子組件傳遞 onClick事件 />); } render() { let {state} = this; const status = `Next player: ${state.xIsNext?'X':'O'}`; return ( <div> <div className="status">{status}</div> <div className="board-row"> {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> </div> ); } }
在 JSX 中你能夠任意使用JavaScript表達式,只須要用一個大括號({})括起來;
事實上每一個 React 元素都是一個JavaScript
對象,能夠把它保存在變量中或者做爲參數傳遞。
爲避免遇到自動插入分號陷阱,最好將內容包裹在小括號中,若是隻有一行代碼則不須要括號。
// 加括號 class App extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // 不用加括號 class App extends React.Component { render() { return <li>Instagram</li>; } }
JSX 語法更接近於 JavaScript,因此 ReactDom 使用cameCase(小駝峯命名)來定義屬性名稱,而且不要使用引號將大括號包裹,二者是不能並存的。對於字符串值使用引號,對於表達式使用大括號
React
中沒法經過 return false
的方式阻止默認行爲,必須使用e.preventDefault()
阻止默認事件。可是不用擔憂event事件
的兼容問題
JSX 自己就能防止XSS攻擊
// 原生DOM <a href="#" onclick="console.log('The link was clicked.'); return false"> Click me </a> // JSX class App extends React.Component { render() { return ( <a href="#" onclick={(e)=>this.handleClick(e)}> //每次渲染時都會建立不一樣的回調函數。該回調函數做爲 prop 傳入子組件時,這些組件可能會進行額外的從新渲染。 Click me </a>; <a href="#" onclick={(e)=>this.handleClick(id,e)}> // 向事件處理程序傳遞參數 Click me </a>; ) } }
JavaScript
中,class
的方法默認不會綁定 this
。若是你忘記綁定 this.handleClick
並把它傳入了 onClick
,當你調用這個函數的時候 this
的值爲 undefined
。class App extends React.Component { // 此語法確保 `handleClick` 內的 `this` 已被綁定。 // 注意: 這是 **實驗性** 語法。 使用 Create React App 默認會啓用此語法 handleClick = (e)=> { e.preventDefault(); console.log(e) } render() { return ( <a href="#" onclick={this.handleClick}> Click me </a>; <a href="#" onclick={this.handleClick。bind(this,id)}> // 向事件處理程序傳遞參數, 事件對象會被隱式傳遞 Click me </a>; ) } }
參考資料
react 官網
React 入門教程