前言
簡介
構建用戶界面的JAVASCRIPT庫,主要用于構建UI
起源于 Facebook 的內部項目,用來架設 Instagram 的網站,擁有較高的性能,代碼邏輯非常簡單,并于 2013 年 5 月開源。
特點
1.聲明式設計 ?React采用聲明范式,可以輕松描述應用。
2.高效 ?React通過對DOM的模擬,最大限度地減少與DOM的交互。
3.靈活 ?React可以與已知的庫或框架很好地配合。
4.JSX ? JSX 是 JavaScript 語法的擴展。React 開發不一定使用 JSX ,但我們建議使用它。
5.組件 ? 通過 React 構建組件,使得代碼更加容易得到復用,能夠很好的應用在大項目的開發中。
6.單向響應的數據流 ? React 實現了單向響應的數據流,從而減少了重復代碼,這也是它為什么比傳統數據綁定更簡單。
JSX語法
const element = <h1>Hello, world!</h1>;
React 書寫格式
以前使用JS 定義一個變量使用 var 現在用 const
const div = document.createElement('div');
渲染方法
所有的 js,html 都可通過它進行渲染繪制,他有兩個參數,內容和渲染目標 js 對象
ReactDOM.render(<App />, div);
React 安裝和構建React 開發環境
通過 npm 使用 React
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
$ npm config set registry https://registry.npm.taobao.org
//使用
$ cnpm install [name]
使用 create-react-app
快速構建 React 開發環境
create-react-app 自動創建的項目是基于 Webpack + ES6
$ cnpm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start
在瀏覽器中打開 http://localhost:3000/
H5項目說明
簡介
使用create-react-app
腳手架搭建,采用react+antd+mobile
技術
項目路徑在H5dev 項目的 m文件里
Build目錄
里是 npm run build
命令后 打包存放的目錄
Public
跟域名訪問的目錄
Src
自己開發的項目文件
Api目錄
主要存放了 一下接口相關的
Components
存放了一些公用組件
Config
存放了配置文件
Images
圖片
Pages
每個頁面的路徑
Style
樣式
Utils
存放一些公用方法
Index.js
入口文件
Router.js
路由文件
Activity 存放了一些活動
常見用法
1.元素渲染
const element = <h1>Hello, world!</h1>;
ReactDOM.render(
element,
document.getElementById('example')
);
2.更新元素渲染
創建一個新的元素,然后將它傳入 ReactDOM.render()
方法
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>現在是 {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('example')
);
}
setInterval(tick, 1000);
3.元素取值和賦值
用 this.props.屬性名
來取值。
可以多層 props 來傳值,在 ReactDOM.render 定義屬性值,傳給調用方法 App,再在調用的ES6類調用中用 props.屬性直接賦值過去。
var myStyle = {color:'red',textAlign:'center'}
class Name extends React.Component {
render() {
return <h1 style={myStyle}>網站名稱:{this.props.name}</h1>;
}
}
class Url extends React.Component {
render() {
return <h1>網站地址:{this.props.url}</h1>;
}
}
class Nickname extends React.Component {
render() {
return <h1>網站地址:{this.props.nickname}</h1>;
}
}
function App(props) {
return (
<div>
<Name name={props.name}/>
<Url url={props.url}/>
<Nickname nickname={props.nickname}/>
</div>
);
}
多個屬性的傳入注意不用逗號或分號隔開而是空格符隔開:
ReactDOM.render(
<App name={"StevenHu教程"} url={"http://www.runoob.com"} nickname={"Runoob"}/>,
document.getElementById('example')
);
4.JSX語法
執行更快,類型安全,在編譯過程中就能發現錯誤
const element = <h1>Hello, world!</h1>;
JSX, 一種 JavaScript 的語法擴展。 我們推薦在 React 中使用 JSX 來描述用戶界面
JSX 是在 JavaScript 內部實現的。JSX 就是用來聲明 React 當中的元素
var myDivElement = <div className="foo" />;
ReactDOM.render(myDivElement, document.getElementById('example'));
5.獨立文件
你的 React JSX 代碼可以放在一個獨立文件上,例如我們創建一個 helloworld_react.js 文件,代碼如下
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
在 HTML 文件中引入該 JS 文件
<body>
<div id="example"></div>
<script type="text/babel" src="helloworld_react.js"></script>
</body>
6.JavaScript 表達式
ReactDOM.render(
<div>
<h1>{1+1}</h1>
</div>
,
document.getElementById('example')
);
在 JSX 中不能使用 if else 語句,但可以使用 conditional (三目運算) 表達式來替代。以下實例中如果變量 i 等于 1 瀏覽器將輸出 true, 如果修改 i 的值,則會輸出 false.
ReactDOM.render(
<div>
<h1>{i == 1 ? 'True!' : 'False'}</h1>
</div>
,
document.getElementById('example')
);
7.樣式
React 推薦使用內聯樣式
。
var myStyle = {
fontSize: 100,
color: '#FF0000'
};
ReactDOM.render(
<h1 style = {myStyle}>StevenHu教程</h1>,
document.getElementById('example')
);
8.注釋
注釋需要寫在花括號中,實例如下:
ReactDOM.render(
<div>
<h1>StevenHu教程</h1>
{/*注釋...*/}
</div>,
document.getElementById('example')
);
9.數組
JSX 允許在模板中插入數組,數組會自動展開所有成員
var arr = [
<h1>StevenHu教程</h1>,
<h2>學的不僅是技術,更是夢想!</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
10.事件處理
- React 事件綁定屬性的命名采用駝峰式寫法,而不是小寫
- 如果采用 JSX 的語法你需要傳入一個函數作為事件處理函數,而不是一個字符串(DOM 元素的寫法)
HTML 通常寫法是:
<button onclick="activateLasers()">
激活按鈕
</button>
React 中寫法為:
<button onClick={activateLasers}>
激活按鈕
</button>
11.不能使用返回 false 的方式阻止默認行為, 你必須明確的使用 preventDefault
通常我們在 HTML 中阻止鏈接默認打開一個新頁面,可以這樣寫
<a href="#" onclick="console.log('點擊鏈接'); return false">
點我
</a>
React 的寫法
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('鏈接被點擊');
}
return (
<a href="#" onClick={handleClick}>
點我
</a>
);
}
12.bind用法
類的方法默認是不會綁定 this 的。如果你忘記綁定 this.handleClick 并把它傳入 onClick, 當你調用這個函數的時候 this 的值會是 undefined。
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 這邊綁定是必要的,這樣 `this` 才能在回調函數中使用
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('example')
);
13.向事件處理程序傳遞參數
class Popper extends React.Component{
constructor(){
super();
this.state = {name:'Hello world!'};
}
preventPop(name, e){ //事件對象e要放在最后
e.preventDefault();
alert(name);
}
render(){
return (
<div>
<p>hello</p>
{/* 通過 bind() 方法傳遞參數。 */}
<a onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
</div>
);
}
}
14.條件渲染
React 中的條件渲染和 JavaScript 中的一致,使用 JavaScript 操作符 if 或條件運算符來創建表示當前狀態的元素,然后讓 React 根據它們來更新 UI。
先來看兩個組件
function UserGreeting(props) {
return <h1>歡迎回來!</h1>;
}
function GuestGreeting(props) {
return <h1>請先注冊。</h1>;
}
創建一個 Greeting 組件,它會根據用戶是否登錄來顯示其中之一
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// 嘗試修改 isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('example')
);
15.與運算符 &&
可以通過用花括號包裹代碼在 JSX 中嵌入任何表達式 ,也包括 JavaScript 的邏輯與 &&,它可以方便地條件渲染一個元素
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
您有 {unreadMessages.length} 條未讀信息。
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('example')
);
如果條件是 true,&& 右側的元素就會被渲染,如果是 false,React 會忽略并跳過它。
16.三目運算符
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
17.阻止組件渲染
在極少數情況下,你可能希望隱藏組件,即使它被其他組件渲染。
讓 render 方法返回 null 而不是它的渲染結果即可實現
。
在下面的例子中,<WarningBanner />
根據屬性 warn 的值條件渲染。如果 warn 的值是 false,則組件不會渲染
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
警告!
</div>
);
}
class Page extends React.Component {
constructor(props) {
super(props);
this.state = {showWarning: true}
this.handleToggleClick = this.handleToggleClick.bind(this);
}
handleToggleClick() {
this.setState(prevState => ({
showWarning: !prevState.showWarning
}));
}
render() {
return (
<div>
<WarningBanner warn={this.state.showWarning} />
<button onClick={this.handleToggleClick}>
{this.state.showWarning ? '隱藏' : '顯示'}
</button>
</div>
);
}
}
ReactDOM.render(
<Page />,
document.getElementById('example')
);
組件的 render 方法返回 null 并不會影響該組件生命周期方法的回調
18.使用 JavaScript 的 map() 方法來創建列表
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numbers) =>
<li>{numbers}</li>
);
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('example')
);
19.修改state里面的屬性
// Correct
this.setState({comment: 'Hello'});
20.狀態更新可能是異步的
例如,此代碼可能無法更新計數器
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
正確
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
上方代碼使用了箭頭函數,但它也適用于常規函數:
// Correct
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});
21.React 事件
通過 onClick 事件來修改數據
class HelloMessage extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'Hello Runoob!'};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: '菜鳥教程'})
}
render() {
var value = this.state.value;
return <div>
<button onClick={this.handleChange}>點我</button>
<h4>{value}</h4>
</div>;
}
}
ReactDOM.render(
<HelloMessage />,
document.getElementById('example')
);
React 組件生命周期
組件的生命周期可分成三個狀態
- Mounting:已插入真實 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真實 DOM
生命周期的方法
componentWillMount
在渲染前調用
componentDidMount
在第一次渲染后調用
componentWillReceiveProps
在組件接收到一個新的 prop (更新后)時被調用。在初始化render時不會被調用。
shouldComponentUpdate
返回一個布爾值在組件接收到新的props或者state時被調用。在初始化時或者使用forceUpdate時不被調用。
componentWillUpdate
組件接收到新的props或者state但還沒有render時被調用。在初始化時不會被調用
componentDidUpdate
在組件完成更新后立即調用。在初始化時不會被調用
componentWillUnmount
在組件從 DOM 中移除之前立刻被調用
生命周期介紹
初始化調用
1、getDefaultProps()
設置默認的props,也可以用dufaultProps設置組件的默認屬性.
2、getInitialState()
在使用es6的class語法時是沒有這個鉤子函數的,可以直接在constructor中定義this.state。此時可以訪問this.props
3、componentWillMount()
組件初始化時只調用,以后組件更新不調用,整個生命周期只調用一次,此時可以修改state。
4、 render()
react最重要的步驟,創建虛擬dom,進行diff算法,更新dom樹都在此進行。此時就不能更改state了。
5、componentDidMount()
組件渲染之后調用,只調用一次。
更新
1、componentWillReceiveProps(nextProps)
組件初始化時不調用,組件接受新的props時調用。
2、shouldComponentUpdate(nextProps, nextState)
react性能優化非常重要的一環。組件接受新的state或者props時調用,我們可以設置在此對比前后兩個props和state是否相同,如果相同則返回false阻止更新,因為相同的屬性狀態一定會生成相同的dom樹,這樣就不需要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤其是在dom結構復雜的時候
3、componentWillUpdata(nextProps, nextState)
組件初始化時不調用,只有在組件將要更新時才調用,此時可以修改state
4、render()
組件渲染
5、componentDidUpdate()
組件初始化時不調用,組件更新完成后調用,此時可以獲取dom節點。
卸載
6、componentWillUnmount()
組件將要卸載時調用,一些事件監聽和定時器需要在此時清除。
初始化 state , setNewnumber 用于更新 state。所有生命周期在 Content 組件中
class Button extends React.Component {
constructor(props) {
super(props);
this.state = {data: 0};
this.setNewNumber = this.setNewNumber.bind(this);
}
setNewNumber() {
this.setState({data: this.state.data + 1})
}
render() {
return (
<div>
<button onClick = {this.setNewNumber}>INCREMENT</button>
<Content myNumber = {this.state.data}></Content>
</div>
);
}
}
class Content extends React.Component {
componentWillMount() {
console.log('Component WILL MOUNT!')
}
componentDidMount() {
console.log('Component DID MOUNT!')
}
componentWillReceiveProps(newProps) {
console.log('Component WILL RECEIVE PROPS!')
}
shouldComponentUpdate(newProps, newState) {
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('Component WILL UPDATE!');
}
componentDidUpdate(prevProps, prevState) {
console.log('Component DID UPDATE!')
}
componentWillUnmount() {
console.log('Component WILL UNMOUNT!')
}
render() {
return (
<div>
<h3>{this.props.myNumber}</h3>
</div>
);
}
}
ReactDOM.render(
<div>
<Button />
</div>,
document.getElementById('example')
);
React AJAX(數據請求)
React 組件的數據可以通過 componentDidMount 方法中的 Ajax 來獲取,當從服務端獲取數據時可以將數據存儲在 state 中,再用 this.setState 方法重新渲染 UI。
當使用異步加載數據時,在組件卸載前使用 componentWillUnmount
來取消未完成的請求
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 實例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
class UserGist extends React.Component {
constructor(props) {
super(props);
this.state = {username: '', lastGistUrl: ''};
}
componentDidMount() {
this.serverRequest = $.get(this.props.source, function (result) {
console.log(result);
var lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
}
componentWillUnmount() {
this.serverRequest.abort();
}
render() {
return (
<div>
{this.state.username} 用戶最新的 Gist 共享地址:
<a href={this.state.lastGistUrl}>{this.state.lastGistUrl}</a>
</div>
);
}
}
ReactDOM.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
document.getElementById('example')
);
</script>
</body>
</html>
補充
①Component定義和Render使用
import React from 'react';
class CommentBox extends React.Component {
render(){
return(
<div className="ui comments">
<h1>評論</h1>
<div className="ui divider"></div>
</div>
);
}
}
export {CommentBox as default};
第二種
class CommentList extends React.Component {
render(){
let commentNodes = this.props.data.map(comment =>{
return (
<Comment author={comment.author} date={comment.date}>
{comment.text}
</Comment>
);
})
}
};
②this.props.children
表示組件的所有子節點
this.props.children的值有三種可能:
- 當前組件沒有子節點,為 undefined
- 若只有一個子節點,類型為 Object
- 若有多個子節點,類型為 Array
通常不直接處理this.props.children,而是用React.Children.map/forEach等API來操作,
該API進行了類型處理,保證不會出錯。
③加載本地json
[圖片上傳失敗...(image-d44f69-1559823451981)]