當可以說這麼一句話 你纔算是掌握了:
切 已經Out了html
Facebook臉書-> Instagram照片牆 。 於2013年5月開源java
幫助開發者簡潔、直觀地構建高性能的UI界面react
官方網站: https://reactjs.org/android
中文網站: https://doc.react-china.org/webpack
執行初始化命令:ios
#保證Node版本>=6 npm install -g create-react-app create-react-app my-app cd my-app npm start ## 若是npm版本5.2.0+,可使用npx進行初始化 npx create-react-app my-app cd my-app npm start
npm和yarn命令對比git
步驟文檔github
查看當前鏡像配置:web
npm config list
npm config get registry
設置當前鏡像地址
npm config set registry https://registry.npm.taobao.org/
npm config set disturl https://npm.taobao.org/dist
元素是構成React應用的最小單位
import React from 'react'; import ReactDOM from 'react-dom'; const element = ( <div> <h1>HaHa!</h1> <h2>Hello Itheima element</h2> </div> ); // ReactDOM進行元素渲染 ReactDOM.render( element, document.getElementById('root') );
React對JSX語法轉換
const element = ( <div className="eleClass"> HaHa! </div> );
轉換js後
const element = React.createElement( "div", { className: "eleClass" }, "HaHa!" );
組件能夠將界面分割成獨立的、可複用的組成部分。只須要專一於構建每一個單獨的部分。好比按鈕,對話框,列表,輸入框都是組件。
無狀態組件:通常用於簡單的頁面展現
// 用函數定義了名爲Hello組件 function Hello(props) { return <h1>Hello {props.name} !</h1>; } // react進行元素渲染 ReactDOM.render( <Hello name="itheima props"/>, document.getElementById('root') );
有狀態組件:能夠維護本身的狀態State信息,完成更加複雜的顯示邏輯
// 用類定義 名爲Hello組件 class Hello extends React.Component { render(){ return <h1>Hello {this.props.name} !</h1>; } } // react進行元素渲染 ReactDOM.render( <Hello name="itheima class"/>, document.getElementById('root') );
類定義組件名稱必須是大寫
建議在return元素時,用小括號()包裹
組件之間能夠相互引用,一般把App做爲根組件
// 用類定義 名爲Hello組件 class Hello extends React.Component { render() { return <h1>Hello {this.props.name} !</h1>; } } // 根組件 function App(props) { return ( <div> <div> <h2>團隊名稱: {props.team}</h2> <p>成員個數: {props.count}</p> <p>成立時間: {props.date.toLocaleString()}</p> </div> <Hello name="悟空" /> <Hello name="八戒" /> <Hello name="沙僧" /> <Hello name="三藏" /> </div> ); } // react進行元素渲染 ReactDOM.render( <App team="西天取經團" count={4} date={new Date()}/>, document.getElementById('root') );
注意:組件的返回值只能有一個根元素,因此用一個div包裹全部Hello元素
在google插件市場搜索安裝React查看DOM結構
自動更新的時鐘
class Clock extends Component { render(){ return ( <div> <h1>當前時間:</h1> <h3>current: {new Date().toLocaleString()}</h3> </div> ); } } setInterval(() => { ReactDOM.render( <Clock />, document.getElementById('root') ); }, 1000);
應用通常執行一次ReactDOM.reader() 渲染
在組件內部進行更新, 每一個時鐘內部都維護一個獨立的date信息
在組件內部使用局部state狀態屬性
class Clock extends Component { constructor(props) { super(props); // state定義:在constructor構造函數進行state狀態的初始化 this.state = { title: "時鐘標題", date: new Date() }; setInterval(() => { this.tick(); }, 1000); } tick(){ // 更新date, 數據驅動, 必須經過setState函數修改數據並更新ui this.setState({ date: new Date() }) } render(){ return ( <div> <h1>{this.state.title}</h1> <h3>current: {this.state.date.toLocaleString()}</h3> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
state特性:
this.state={...}
this.setState({...})
更新並渲染組件生命週期經常使用的函數
componentDidMount:組件已掛載, 進行一些初始化操做
componentWillUnmount: 組件將要卸載,進行回收操做,清理任務
class App extends Component { handleClick(e){ console.log("handleClick!") console.log(this); } render(){ return ( <div> <button onClick={() => this.handleClick()}> 按鈕:{'{() => this.handleClick()}'} </button> </div> ); } }
// 屬性初始化器語法 (Property initializer syntax) handleClick = () => { console.log("handleClick!") console.log(this); }
class App extends Component { handleClick(e, str, date){ // 參數要和調用者傳入的一一對應 console.log(this) console.log(e) console.log(str, date) } render(){ return ( <button onClick={(e)=>this.handleClick(e, "參數" , new Date())}> 按鈕1:{'箭頭函數'} </button> ); } }
參數要和調用者傳入的一一對應
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; // 類定義組件的寫法 class App extends Component { constructor(props) { super(props); // 綁定this到事件函數 this.countPlus = this.countPlus.bind(this); this.state = { count: 0, timeSurplus: 10 }; } // 組件已掛載, 開啓週期任務 componentDidMount() { this.timerId = setInterval(() => { this.setState((preState) => ({ timeSurplus: preState.timeSurplus - 1 })) // 在合適的時候, 結束周期函數 if(this.state.timeSurplus <= 0){ clearInterval(this.timerId) } }, 1000); } countPlus(){ // 更新當前count數字. console.log(this) // 若是時間到了, 返回 if (this.state.timeSurplus <= 0){ return; } // 更新數據會自動觸發UI的從新render // this.setState({ // count: this.state.count + 1 // }) // 經過以前state狀態更新如今的狀態 this.setState((preState) => ({ count: preState.count + 1 })) } render() { return ( <div> <h1>{this.props.title}</h1> <h2> { this.state.timeSurplus <= 0 ? ("時間到, 總數" + this.state.count) : ("剩餘時間:" + this.state.timeSurplus) } </h2> <button onClick={this.countPlus}> 計數: {this.state.count} </button> </div> ); } } ReactDOM.render( <App title="計數器, 試試你的手速!"/>, document.getElementById('root') );
直接寫在style屬性中
<button style={{width: 200, height: 200}}>我是按鈕</button>
通關變量聲明樣式並引用
const btnStyle = { width: 200, height: 200 }; ... <button style={btnStyle} onClick={this.handleClick}>我是按鈕</button>
#腳手架安裝和樣式處理
npm i -g yarn npm uninstall -g create-react-app yarn global add create-react-app create-react-app my-app
應用ID 36408f4c57bebc38 應用密鑰 VIB9yiN5LQZZVkaXOpnKD7DpYMw9VeNl
直接寫在style屬性中
<button style={{width: 200, height: 200}}>我是按鈕</button>
通關變量聲明樣式並引用
const btnStyle = { width: 200, height: 200 }; ... <button style={btnStyle} onClick={this.handleClick}>我是按鈕</button>
經過css樣式文件設置
.btn { width: 300px; height: 200px; background-color: coral; }
? 2. 引入
import './css/counter.css';
? 3. 使用className
<button className="btn">我是按鈕</button>
[TOC]
function BuySomething(props){ if(props.money >= 10){ return <p>恭喜, 購買成功! {props.money} >= 10</p>; } return <p> 購買失敗,金額不足! {props.money}</p> }
if (list.length % 2 === 0){ subTitle = <p>好記性不如爛筆頭! </p>; } else { subTitle = <p>明日復明日, 明日何其多! </p>; }
{this.props.showTitle && (<h2>GTD 記事本</h2>)}
{/* 三目運算符/三元運算符 */} { list.length === 0 ? <p>這裏空空如也, 恭喜咯!</p> : <ul>{list}</ul> }
// 某種不但願渲染的條件發生了, 經過返回null阻止render渲染 if(true){ return null; } return (...);
在html中, input, select, textarea這些表單元素都會默認維護本身的狀態,React經過受控組件
將用戶輸入的內容保存到state中,經過渲染表單組件,控制用戶輸入以後發生的變化。
//1. 在構造函數初始化狀態 constructor(props) { super(props); this.state = { money:'' }; } // 2.監聽input的變化 <input type="text" value={this.state.money} onChange={this.handleChange} /> // 3.處理變化,更新state handleChange = (e)=>{ // console.log(e.target.value); this.setState({ money: e.target.value }) }
若是有多個組件須要共享狀態數據,把要MoneyInput共享的數據state={money, unit}提高到他們最近的共同父組件App中。
數據源要保證只有一個,並保持自上而下的數據流結構。
money={rmb}
屬性設置給MoneyInput組件,this.props.money
GTD軟件: Getting things done
在package.json的scripts下配置
"start": "SET PORT=3456 & react-scripts start",
.map
能夠幫咱們把數組轉換成元素的數列.filter
根據每一個條目返回的boolean, 決定去留. true保留, false刪除導包 import PropTypes from 'prop-types';
propTypes只在開發模式下進行檢查,當給組件傳入錯誤的值(或未傳值),JS控制檯會打印警告信息。在生產環境不會進行檢查(影響頁面效率)
屬性類型及Required檢查
/** * 屬性類型及isRequired檢查 * order: 數字類型 * item: 字符串類型 */ TodoItem.propTypes = { order: PropTypes.number.isRequired, item: PropTypes.string, }
設置屬性默認值(當父組件沒有傳入指定值時,使用默認值)
/** * 設置屬性默認值 */ TodoItem.defaultProps = { item: "默認的條目描述" }
ref用來訪問DOM節點或React元素 ref是reference的縮寫
ref={(input) => {this.inputNode = input}}
this.inputNode
便可元素 | 屬性值 | 變化回調 | 在回調中獲取值 |
---|---|---|---|
<input type="text" /> |
value="string" |
onChange |
event.target.value |
<input type="checkbox" /> |
checked={boolean} |
onChange |
event.target.checked |
<input type="radio" /> |
checked={boolean} |
onChange |
event.target.checked |
<textarea /> |
value="string" |
onChange |
event.target.value |
<select /> |
value="option value" |
onChange |
event.target.value |
在受控組件和非受控組件之間抉擇:參考文檔
若是表單的UI交互很是簡單:經過refs實現非受控組件便可。
若是表單的UI交互比較複雜:官方推薦使用受控組件實現表單,把DOM節點/React元素的值或數據交給React組件處理(保存到state)。
安裝:
yarn add react-router-dom
導入Module:
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
聲明路由器及路由:
<Router> <div> <Route exact={true} path="/" render={() => (<TodoComponent showTitle={true} />)}/> <Route path="/about" component={About}/> </div> </Router>
經過Link跳轉
<Link to="/about">關於about</Link> <Link to="/">主頁Home</Link>
exact={true}
表示嚴格匹配pathReact提供了強大的組合模型,官方建議使用組合(而非繼承)來複用組件代碼。
{props.children}
,使用時在標籤內部填入自定義的元素內容便可。subTitle
聲明:
function AboutPanel(props) { return ( <div className="about-panel"> <h2 className="about-title">{props.title}</h2> {props.subTitle} <p>{props.desc}</p> {props.children} </div> ); }
使用:
<AboutPanel title="興趣愛好" desc="性別男, 愛好女。最大的缺點是太實誠,總愛習慣性給公司免費加班" > <input type="text" ref={(input) => this.textInput = input}/> <button onClick={() => alert(this.textInput.value)}>點評</button> </AboutPanel>
// 這裏AboutPanelSpcial 是 AboutPanel 的特殊實例 class AboutPanelSpcial extends React.Component{ render(){ return ( <AboutPanel title="工做履歷" subTitle={<h5>人生精力豐富, 行業跨度大</h5>} desc="走過男闖過北, 火車道上壓過腿; 養過狼放過虎, 少林寺裏練過武" /> ) } }
npm run build
運行服務器代碼: build包含index.html文件的文件夾
前臺運行: serve -s build
後臺運行(指定端口80): nohup serve -s build -l 80 &
react-router-dom 路由
應用場景:頁面切換
安裝方式:
yarn add react-router-dom
serve 開啓服務
應用場景:部署打包好的應用
安裝方式:
yarn global add serve
移動開發
[TOC]
Facebook發起的開源的一套新的APP開發方案,Facebook在當初深刻研究Hybrid開發後,以爲這種模式有先天的缺陷,因此果斷放棄,轉而自行研究,後來推出了本身的「React Native」方案,不一樣於H5,也不一樣於原生Native,更像是用JS寫出原生應用
開發成本小於Native模式 Andriod-Java-Kotlin IOS-OC-Swift
性能體驗高於Hybrid
一次學習,跨平臺開發Android和iOS, 小程序
社區繁榮
安裝腳手架react-native-cli 同時安裝新的版包管理工具
npm install -g yarn react-native-cli
建立項目:doubanMovie(在不包含中文的目錄執行)
react-native init xxx --version react-native@0.55.4
運行項目
打開USB調試, 配置SDK
adb devices
查看已鏈接設備鏈接模擬器: adb connect 127.0.0.1:62001
更改gradle路徑doubanMovie\android\gradle\wrapper\gradle-wrapper.properties
distributionUrl
值修改成file\:///E:/Lesson/bc1/React/day03/Resource/gradle-2.14.1-all.zip
直接複製過來的路徑要把反斜線\改爲正斜線/在項目根目錄執行react-native run-android
運行期間會開啓一個Node服務,不要關閉
第一次運行報錯,須要在設備上設置app的Node服務地址
解決方式: 打開app > 菜單按鈕 > Dev Settings -> Debug server host ...
填寫服務ip和端口號, 注意冒號用英文半角,重啓服務,重啓應用
React-Native與React對比
組件寫法
RN提供View,Text組件,沒有html的dom元素
View -> div 佈局容器
Text -> p 顯示文字
樣式寫法
使用
const styles = StyleSheet.create({...})
React-Native平臺相關代碼處理
const instructions = Platform.select({ ios: 'Press Cmd+R to reload,\n Cmd+D or shake for dev menu', android: 'Double tap R on your keyboard to reload,\n', });
react-native-router-flux
源碼地址:https://github.com/aksonov/react-native-router-flux
應用場景:在RN項目中進行路由跳轉時使用
安裝方式:
yarn add react-native-router-flux
使用:
Router(路由): 通常寫在項目的根組件
Stack (棧):給Scene場景提供容器
Scene(場景):設置路由跳轉規則
Actions (動做):觸發路由跳轉
const App = () => ( <Router> <Stack key="root"> <Scene key="login" component={Login} title="Login"/> <Scene key="register" component={Register} title="Register"/> <Scene key="home" component={Home}/> </Stack> </Router> );
注意事項:
最新版的react-native-router-flux會在react-native 0.55.4版本出現isMounted(...)警告,可在App.js添加如下代碼忽略警告。隨後兩個框架更新後,此警告也可消除。
import { YellowBox } from 'react-native' YellowBox.ignoreWarnings(['Warning: isMounted(...) is deprecated'])
觸發路由:三種方式 (注意導入Actions組件)
<Text onPress={Actions.movieList}>電 影</Text> <Text onPress={() => { Actions.movieList()}}>電 影</Text> <Text onPress={() => { Actions['about'].call() }}>關 於</Text>
彈性佈局參考: http://www.runoob.com/w3cnote/flex-grammar.html
開源輪播圖react-native-swiper
源碼地址:https://github.com/leecade/react-native-swiper
應用場景:在首頁展現輪播圖
安裝方式:
yarn add react-native-swiper
經常使用屬性:
index={1} 默認位置, 從0開始 showsButtons={true} 是否顯示按鈕 autoplayTimeout={2.5} 自動播放停留時間 autoplay={true} 是否自動播放 showsPagination={true} 顯示分頁指示器
在 componentDidMount
執行請求並在回調中執行setState
// 組件已經掛載 componentDidMount() { const url = 'http://api.douban.com/v2/movie/in_theaters'; fetch(url).then(res => res.json()) .then(data => { // 處理網絡json數據 this.setState({ isLoading: false, movieList: data.subjects }) // console.warn(data.subjects) }).catch((err) => { console.error(err); }); }
長列表優化
<FlatList data={this.state.movieList} keyExtractor={(item, index) => item.id} renderItem={({ item, index }) => { return ( <View style={{ padding: 10, flexDirection: 'row' }}> <Text>{item.title}: {item.year} : {index} </Text> </View> ) }} />
加載指示器
<View style={{ flex: 1, padding: 20 }}> <ActivityIndicator /> </View>
條目點擊跳轉
Actions.movieDetail({ "movieId": movie.id, "movieTitle": movie.title});
查看RN日誌:
react-native log-ios react-native log-android
android也可在PC控制檯輸入
adb logcat *:S ReactNative:V ReactNativeJS:V
應用內的錯誤與警告
console.warn('Yellow.'); console.error('Red.');
Debug調試
在Android設備菜單中選擇「Debug JS Remotely」,PC會自動經過Chrome瀏覽器打開調試頁面 http://localhost:8081/debugger-ui (須要自行安裝Chrome)。這裏注意自動打開的主機地址可能不是localhost,須要手動改爲localhost (不修改,則手機頁面多是空白)
在Chrome瀏覽器按Ctrl + Shift + I
或F12
打開控制檯
選中Sources選項卡 -> Network標籤 -> debuggerWorker.js 打開指定組件文件便可
若是沒有沒有debuggerWorker.js, 查看頁面最下邊的Status提示。
Status: Another debugger is already connected
另外一個調試器已鏈接,直接使用或關閉那個調試器
Status: Waiting, press Ctrl R in simulator to reload and connect.
等待中,建議從新加載模擬器
能夠在代碼中打斷點,Console中執行js代碼打印變量、執行腳本
關閉調試:在Android設備菜單中選擇「Stop Remote JS Debugging」便可
參見中文官網文檔:https://reactnative.cn/docs/0.51/signed-apk-android.html#content
react-native-router-flux 路由
應用場景:在RN項目中進行路由跳轉時使用
安裝方式:
yarn add react-native-router-flux
react-native-swiper 開源輪播圖
應用場景:在首頁展現輪播圖
安裝方式:
yarn add react-native-swiper