React 是一個聲明式,高效且靈活的用於構建用戶界面的 JavaScript 庫。使用 React 能夠將一些簡短、獨立的代碼片斷組合成複雜的 UI 界面,這些代碼片斷被稱做「組件」。html
npm install -g create-react-app
下載官方的腳手架工具create-react-app。create-react-app react01
建立一個新的名爲react01的項目。 React和ReactDOM是開發React項目必不可少的兩個包。React負責邏輯控制,它用JSX來描述虛擬DOM以及用它的Component類來建立一個組件;而ReactDOM主要負責渲染,將構建好的虛擬DOM渲染成真實DOM到頁面上。
來自官方的示例:這裏面還涉及到另外一個問題,JSX是什麼?vue
class HelloMessage extends React.Component {
render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
}
ReactDOM.render(React.createElement(HelloMessage, { name: "Taylor" }), document.getElementById('hello-example'));
複製代碼
至關於react
class HelloMessage extends React.Component {
render() {
return (
<div> Hello {this.props.name} </div>
)
}
}
ReactDOM.render(
<HelloMessage name="Taylor" />, document.getElementById('hello-example') ) 複製代碼
JSX形如js和html的混合體,它在react代替常規的js語法。它的優勢:1)執行更快,提升執行效率。2)使用咱們更熟悉的html來描述UI,JSX在react轉換爲js的寫法形如:React.createElement("div",null,"Hello ",this.props.name);
,寫起來很繁瑣。3)它是類型安全的,在編譯過程當中就能發現錯誤。
JSX就是html加上表達式,下面介紹一下一些表達式的寫法:npm
import src from './static/img'
sayHi(){
return 'hello, react'
}
render(){
const name = 'zhunny'
const jsx = '<p>jsx</p>'
return(
<div>
{/*註釋語法*/}
{/*表達式*/}
<h1>{name}</h1>
<h1>{this.seyHi()}</h1>
{/*屬性的寫法*/}
<img src={src} style={{width:"200px"}}>
{/*jsx也能夠直接當成是表達式*/}
{jsx}
{/*只要是js表達式均可以放在{}裏面*/}
<div>
)
}
複製代碼
一種是函數類型組件,一種是基於類的組件。數組
//rfc 比較簡潔,直接至關於render函數,但hooks的出現使得它們之間沒有太大區別
import React from 'react'
export default function CompType() {
return (
<div> </div>
)
}
//rcc 能夠在類中使用各類生命週期鉤子,在constructor構造函數中初始化state和props
import React, { Component } from 'react'
export default class CompType extends Component {
render() {
return (
<div> </div>
)
}
}
複製代碼
使用組件時,可能會出現一些特別的狀態,它們可能會改變所以影響視圖的變化,所以咱們須要去維護這些狀態。凡是數據與視圖有交互的時候,就須要將這些數據維護到狀態state中去。state通常在構造函數constructor中初始化。安全
constructor(props) {
super(props)
this.state = {
count:1
}
}
複製代碼
而setState是官方提供給咱們用來修改state值的方法,千萬不能直接修改state,會報錯。使用setState修改state有兩種方法,直接修改state對象setState(obj,cb)
,或者傳入一個修改函數setState(fn,cb)
。由於state和setState是批量執行的,這樣能夠提高更新的性能,可是同時它會認爲連續相同的操做形如setState(obj,cb)
是同樣的,只會執行最後一次。這個時候就須要使用第二種修改state的方法。app
componentDidMount () {
this.setState({
count: this.state.count + 1
})
}
複製代碼
componentDidMount () {
this.setState(preState => ({
count:preState.count + 1
}))
this.setState(preState => ({
count:preState.count + 1
}))
}
複製代碼
這是一種父組件向子組件傳遞屬性的一種方式,父->子通訊的方法。兩種不一樣類型的組件在調用props時有差異。函數
//在父組件中
import { Welcome1, Welcome2 } from './components/CompType'
export default class App extends Component {
render () {
return (
<Welcome1 name="zhunnyWang" />
<Welcome2 name="zhunnyWang" />
)
}
}
複製代碼
//在子組件中
//props傳值,兩種方式有區別,props是隻讀的
//單向綁定,嚴格的單向數據流
export function Welcome1 (props) {
return (
<div> Welcome1,{props.name} </div>
)
}
export class Welcome2 extends React.Component {
constructor(props){
super(props)
}
render () {
return (
<div>Welcome2,{this.props.name}</div>
)
}
}
複製代碼
這是在react使用最頻繁的兩種表達式寫法。條件渲染有兩種實現方式,一種是使用三元表達式,一種是使用短路邏輯。父組件向子組件傳遞了一個props爲title='goodlist'
。列表渲染就是循環的將一個數組中的元素顯示在視圖上。工具
export class GoodsList extends React.Component {
constructor(props){
super(props)
this.state = {
goods:[
{id:1,name:'《你不知道的Javascript》'}
{id:2,name:'《CSS世界》'}
]
}
}
render () {
const title = this.props.title ? <h1>{this.props.title}</h1> : null
return (
<div> {/*條件渲染的第一種方式,三元表達式*/} {title} {/*條件渲染的第二種方式,短路邏輯*/} {this.props.title && <h1>this.props.title</h1>} {/*列表渲染*/} <ul> {this.state.goods.map(good => (<li key={good.id}>{good.name}</li>))} </ul> </div>
)
}
}
複製代碼
react的事件處理與原生js形似,形如onClick={this.fn}
。事件處理函數的聲明有兩種方式,一種是經過箭頭函數,一種是普通函數可是須要在構造函數中綁定this。性能
export class GoodsList extends React.Component {
constructor(props){
super(props)
this.state = {
goods:[
{id:1,name:'《你不知道的Javascript》'}
{id:2,name:'《CSS世界》'}
],
text: ''
}
//不用箭頭函數就得綁定this
this.addGood = this.addGood.bind(this)
}
textChange = (e) => {
this.setState({
text: e.target.value
})
}
addGood () {
/** * react官方但願這是一個純函數 * 更新的數據不是以前的數據,而是一個全新的數據 */
this.setState(prevState => {
return {
goods: [
...prevState.goods,
{
id: prevState.goods.length + 1,
name: prevState.text
}
]
}
})
}
render () {
return (
<div> {/*react嚴格遵循單向數據流,沒有數據的雙向綁定,所以須要本身來實現*/} <input type="text" text={this.state.text} onChange={this.textChange} /> <button onClick={this.addGood}>添加商品</button> {/*須要在聲明的事件處理函數中傳入參數時,也須要借用箭頭函數來傳參*/} <button onClick={() => {this.addToCart(good)}}>添加商品</button> </div> ) } } 複製代碼
父傳子可使用props來傳遞,上述章節已經給出示例。子傳父也須要藉助props傳遞一個回調函數,經過回調函數來觸發父組件中的方法,用父組件中的函數來修改子組件中的值。這與vue有很大的差別,react但願子組件是一個很是單純的組件,它只有展現功能,全部的操做在父組件中完成。
//父組件
export class Counter extends React.Component {
constructor(props){
super(props)
this.state = {
count:1
}
}
add = (value) => {
this.setState(prevState => {
count: preState.count + value
})
}
render () {
return (
<div> <Add count={this.state.count} add={this.add}></Add> </div>
)
}
}
//子組件
export function Add ({ count, add }) {
return(
<div> {count} <button onClick={add(10)}></button> </div>
)
}
複製代碼
摘自官方文檔的一段話,當你遇到須要同時獲取多個子組件數據,或者兩個組件之間須要相互通信的狀況時,須要把子組件的 state 數據提高至其共同的父組件當中保存。以後父組件能夠經過 props 將狀態數據傳遞到子組件當中。這樣應用當中全部組件的狀態數據就可以更方便地同步共享了。
這就是上述所說的子組件是很是單純的,父組件操做,只將結果傳遞給子組件,子組件將結果最終展現到視圖上。
通常來講,有兩種修改數據的方式,第一種是直接修改變量的值,第二種是將新的數據直接替換舊的數據。在React中,官方推薦咱們在修改狀態值時使用全新的數據替換舊數據,維持不變性。
第一種:直接修改變量的值:
const name = { firstName:'wang', secondName:'zhunny' }
name.firstName = 'zhou'
複製代碼
第二種:全新的數據替換舊的數據:
const name = { firstName:'wang', secondName:'zhunny' }
const newName = {...name, firstName:'zhou'}
複製代碼
在React中維持不變性有如下幾點好處: