React簡介
React在2013年5月開源。
React可能是將來web開發的主流工具。
React不是一個完整的MVC框架,頂多充當一個View層。
-
MVC(Model+View+Controller)
不適用于前端開發,因為View不允許知道用戶的輸入,用戶的輸入是從Controller這一層進入。然而用戶直接通過view層交互,所以不可能不監聽View層。
MVVM(Model+View+ViewModel)
——MVC的演變,更適合前端的開發模式。
-
JSX 解析器
將JSX轉化成JS,在JS中直接編寫HTML。
通過組建的state
來維護改變HTML DOM中的內容。
所有和Dom有關的都應該通過框架來維護,
將各功能做成組建——模板(容器)、控件。
-
React組件及數據傳遞
React是一個組件化的框架,在項目開發之初需要將組件分化
搭建React Start Kit
1. 新建項目文件夾
這里取名newReactproject。
在該目錄下打開終端,初始化package.json
npm init
(可以輸入項目的名稱,這里為new-react-project
)
2. 安裝插件
npm install --dev-save browser-sync gulp gulp-webpack jsx-loader react react-dom
3. JSX轉換成JS的方法
在gulpfile.js中用webpack來將.jsx文件轉化為.js文件
(gulp的使用在其他的章節里面會詳細說明)
var webpackConfig = {
output:{
filename: 'index.js'
},
devtool: 'inline-source-map',
module:{
loaders:[
{test: /\.jsx$/, loader: 'jsx-loader'}
]
},
resolve:{
extensions:['','.js','.jsx']
}
}
gulp.task('script',function(){
gulp.src('./jsx/index.jsx') //以index.jsx為程序的入口
.pipe(webpack(webpackConfig))
.pipe(gulp.dest('./www/script/'))
.pipe(browserSync.stream());//同步瀏覽器
})
如此一來,就可以在.jsx文件中撰寫開發代碼了。
同時,需要注意的是:index.jsx中需要引用react
var React = require('react');
var ReactDom = require('react-dom')
如果需要在index.jsx中引用的組件,例如header,footer等,需要使用module.exports
module.exports = React.createClass({
render:function(){
return <p>這是一個React頁面</p>
}
})
注意:實際項目中,node_modules文件會被刪除 ,那么運行項目的時候需要在終端輸入以下命令:
npm install gulp-cli -g
npm install
gulp
4. render語法
render一個變量時,要用html的方法來寫。
例如:
ReactDom.render(<Main />,document.getElementById('main'));
前面一個指render的內容,后一個變量是render的目的地
注意:ReactDom.render
是新版本的寫法,舊版本是React.render()
//jsx語法中類名:
className="className";
//jsx語法中樣式:
style={{background:'#f00'}}
//jsx語法:
<tag prop={a:value}>{children}</tag>
//轉換成js是:
React.createElement(tag, {a:value}, children)
創建一個組件類,需要注意的幾點:
- React中創建的組件類以大寫字母開頭,
駝峰命名法
- 在React中使用React.createClass方法創建一個組件類
- 核心代碼:每個組件類都必須實現自己的
render
方法。輸出定義好的組件模板。返回值:null、false、組件模板 - 注意:組件類只能包含一個頂層標簽
5. React Component
- render:渲染html的方法
- getInitialState: 返回初始化的State的方法
- getDefaultProps:返回默認props的方法
(state維護component內部的狀態變化,props是component的外部的參數傳入component的方式)- propTypes:定義props的類型的屬性
- mixins:用來合并兩個組件的屬性
- statics:定義靜態對象的屬性
- displayName:定義該類在Debug信息中顯示的名稱
6. Props
Props是組件自身的屬性,一般用于嵌套的內外層組件中,負責傳遞信息(通常是由父層組件向子組件傳遞)
注意:props對象中的屬性與組件的屬性一一對應,不要直接去修改props中的屬性值。
//定義WebName
var WebName = React.createClass({
render:function(){
return <h1>{this.props.webname}</h1>;
}
})
//定義WebLink
var WebLink = React.createClass({
render:function(){
return <a href={this.props.weblink}>{this.props.weblink}</a>;
}
})
//定義WebShow
var WebShow = React.createClass({
render:function(){
return (
<div>
<WebName webname={this.props.wname} />
<WebLink weblink={this.props.wlink} />
</div>
);
}
})
//渲染
ReactDOM.render(
<WebShow wname="網站名稱" wlink="http://www.baidu.com" />,
document.getElementById("container")
)
-
...this.props:
Props
提供的語法糖,可以將父組件中的全部屬性都復制給子組件
例如:定義一個組件Link,Link組件中只包含一個<a>
,我們不給<a>
設置任何屬性,所有屬性全部從父組件膚質得到。代碼如下:
var Link = React.createClass({
render:function(){
return <a {...this.props}>{this.props.name}</a>
}
});
ReactDOM.render(
<Link name="百度"/>,
document.getElementById("container")
)
//這樣父組件上的屬性href和name都會被復制到子組件Link中的<a>上。
-
this.props.children:
children是一個例外,不是跟組件的屬性對應的。children表示組建的所有子節點
var ListComponent = React.createClass({
render:function(){
return (
<ul>
{
/*
列表項數量以及內容不確定,在創建模板時才能確定
利用this.props.children從父組件獲取需要展示的列表項內容
獲取到列表項內容后,需要遍歷children逐行進行設置
使用React.Children.map方法
該方法的返回值:數組對象
*/
React.Children.map(this.props.children, function(child){
//child是便利得到的父組件的子節點
return <li>{child}</li>
})
}
</ul>
)
}
});
//渲染
ReactDOM.render(
(
<ListComponent>
<h1>百度</h1>
<a >http://www.baidu.com</a>
</ListComponent>
),
);
7. 屬性驗證 propTypes
組件類的屬性,用于驗證組建實例的屬性是否符合要求
var ShowTitle = React.createClass({
propTypes: {
//title數據類型必須為字符串
title:React.PropTypes.string.isRequired
},
render:function(){
return <h1>{this.props.title}</h1>
}
});
ReactDOM.render(
<ShowTitle title="123" />,
document.getElementById("container")
)
-
設置組件屬性的默認值
通過實現組件的getDefaultProps方法,對屬性設置默認值。
var MyTitle = React.createClass({
getDefaultProps: function(){
return {
title: "百度"
};
},
render: function(){
return <h1>{this.props.title}</h1>
}
});
ReactDOM.render(
<MyTitle />,
document.getElementById("container")
);
8. state:
state和props一樣都是組件自身的屬性,都可以用來傳遞數據。
在和用戶交互的過程中,組件的狀態可能需要更新,就會觸發組件的重新渲染。
先舉個例子說明React事件的引用:
//定義一個button組件,綁定onClick事件
//React中的事件名稱首字母小寫,駝峰命名法
var MyButton = React.createClass({
handleClick: function(){
alert('點擊按鈕觸發的效果');
},
render: function(){
return (
<button onClick={this.handleClick}>{this.props.buttonTitle}</button>
)
}
});
ReactDOM.render(
<MyButton buttonTitle="按鈕" />,
document.getElementById("container")
);
在知道事件引用的方法后,再舉個經典案例:
需求:創建一個CheckButton的組件,包含一個checkbox類型的input,復選框在選中和未選中的兩種狀態下回顯示不同的文字,即根據狀態渲染。
var CheckButton = React.createClass({
//定義初始狀態
getInitialState: function(){
return {
//在這個對象中設置的屬性將會存儲在state中
//默認狀態是:未選中
isCheck: false
}
},
//定義事件綁定的方法
handleChange: function(){
//修改狀態值,通過this.state讀取設置的狀態值
this.setState({
isCheck: !this.state.isCheck
});
},
render:function(){
//根據狀態值,設置顯示的文字
//在JSX語法中,不能直接使用if..else函數,使用三目運算符
var text = this.state.isCheck ? "已選中" : "未選中";
return (
<div>
<input type="checkbox" onChange={this.handleChange} />
{text}
</div>
);
},
});
//渲染
ReactDOM.render(
<CheckButton />,
document.getElementById("container")
);
需要注意的時:當state發生變化時,會調用組件內部的render方法
-
表單
舉例說明:
需求:定義一個組件,將用戶在輸入框內輸入的內容進行實時顯示
分析:組件與用戶交互過程中,存在狀態的變化,即輸入框的值。
var Input = React.createClass({
getInitialState: function(){
return (
value: "請輸入"
);
},
handleChange: function(event){
//通過event.target.value讀取用戶輸入的值
this.setState({
value: event.target.value
});
},
render: function(){
var value = this.target.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
)
},
});
ReactDOM.render(
<input />,
document.getElementById("container")
);
9. React Component生命周期時間
組件的生命周期分為三個狀態
:
-
Mounting
: 組件掛載,已插入真實DOM相關接口:
(1)
componentWillMount
- 組件將要掛載。
在render之前執行,但僅執行一次,即使多次重復渲染該組件,或者改變了組件的state(2)
componentDidMount
- 組件已經掛載。
在render之后執行,同一個組件重復渲染只執行一次 -
Updating
: 組件更新,正在被重新渲染相關接口:
(1)
componentWillReceiveProps
(object nextProps)- 已加載組件收到新的props之前調用,注意組件初始化渲染時則不會執行(2)
shouldComponentUpdate
(object nextProps, object nextState) - 組件判斷是否重新渲染時調用。該接口實際是在組件收到了新的props或者新的state的時候會立即調用,然后通過下面兩個方法來進行更新(3)
componentWillUpdate
(object nextProps, object nextState) - 組件將要更新(4)
componentDidUpdate
(object prevProps, object prevState) - 組件已經更新 -
Unmounting
: 組件移出,已移出真實DOM相關接口:
componentWillUnmount
- 在組件要被移除之前的時間點觸發,可以利用該方法來執行一些必要的清理組件的工作
生命周期中與props和state相關的接口:
(1)getDefaultProps
- 設置props屬性默認值
(2)getInitialState
- 設置state屬性初始值
總結下來,一共九個接口,如下:
- componentWillMount:組件的html即將加載時調用
- componentDidMount:組件的html已經加載時調用
- componentWillReceiveProps:組件props改變時調用
- shouldComponentUpdate:判定組件是否更新HTML
- componentWillUpdate:組件即將更新HTML時調用
- componentDidUpdate:組件HTML更新完后調用
- componentWillUnmount:組件HTML即將卸載時調用
- getDefaultProps:設置props屬性默認值
- getInitialState:設置state屬性初始值
組件的生命周期可分為四個階段
:創建
、實例化
、更新
、銷毀
生命周期個階段介紹
var Demo = React.createClass({
/*
一、創建階段
流程:只調用getDefaultProps方法
*/
getDefaultProps: function(){
//在創建類的時候被調用,設置this.props的默認值
console.log("getDefaultProps");
return {};
},
/*
二、實例化階段
流程:
getInitialState,
componentWillMount,
render,
componentDidMount
*/
getInitialState: function(){
//設置this.state的默認值
console.log("getInitialState");
return {};
},
componentWillMount: functon(){
//在render之前調用
console.log("componentWillMount");
},
render:function(){
//渲染并返回一個虛擬DOM
console.log("render");
return <div>Hello React</div>
},
componentDidMount: function(){
//在render之后調用
//在該方法中,React會使用render方法返回的虛擬DOM對象創建真實的DOM結構
//可以在這個方法中讀取DOM節點
console.log("componentDidMount");
},
/*
三、更新階段
流程:
componentWillReceiveProps,
shouldComponentUpdate (如果返回值是false,后三個方法不執行),
componentWillUpdate,
render,
componentDidUpdate
*/
componentWillReciveProps: function(){
console.log("componentWillReciveProps")
},
shouldComponentUpdate: function(){
//是否需要更新
console.log("shouldComponentUpdate");
return true;
},
componentWillUpdae: function(){
console.log("componentWillUpdae");
},
componentDidUpdate: functon(){
console.log("componentDidUpdate")
},
/*
四、銷毀階段
流程:componentWillUnmount
*/
componentWillUnmount: function(){
console.log("componentWillUnmount")
},
});
//第一次創建并加載組件
//將得到以下順序:getDefaultProps,getInitialState,componentWillMount,render,componentDidMount
ReactDOM.render(
<Demo />,
document.getElementById("container")
);
//第二次創建并加載組件
//將在第一次加載的基礎上,添加以下順序:componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate
ReactDOM.render(
<Demo />,
document.getElementById("container")
);
//移除組件
ReactDOM.unmountComponentAtNode(document.getElementById("container"))
10. 設置組件的樣式
- 內連樣式
- 對象樣式
- 選擇器樣式
注意:在React
和HTML5
中,樣式的書寫方式是有所區別的
主要體現在:
- HTML5以;結尾,React以,結尾
- HTML5中key、value都不加引號,React中屬于JavaScript對象,key的名字不能出現“-”,需要使用駝峰命名法。如果value為字符串,需要加引號。
- HTML5中,value如果是數字,需要帶單位,React中不需要帶單位。
//樣式
<style>
.pStyle {
font-size:20px;
}
</style>
//創建設置h1樣式對象
var hStyle = {
backgroundColor:"green",
color:"red"
}
var ShowMessage = React.createClass({
render:function(){
return(
//內連樣式
<div style={{backgroundColor:"yellow",borderWidth:5,borderColor:"black",borderStyle:"solid"}}>
//對象樣式
<h1 style={hStyle}>{this.props.firstRow}</h1>
//選擇器樣式
<p className="pStyle">{this.props.secondRow}</p>
</div>
)
}
})
//渲染效果
ReactDOM.render(
<ShowMessage firstRow="第一行" secondRow="第二行"/>,
document.getElementById("container")
)
注意:在React中使用選擇器樣式設置組件樣式時,屬性名不能使用class
,因為class
是React
中的保留字,需要使用className
替換。
類似的還有使用htmlfor
替換for
,因為for
也是React
中的保留字。
11. 復合組件 —— 也稱為組合組件,父子組件(創建多個組件合成一個組件)
//定義WebName組件
var WebName = React.createClass({
render:function(){
return <h1>網站名稱</h1>;
}
});
//定義WebLink組件
var WebLink = React.createClass({
render:function(){
return <a >http://www.baidu.com</a>;
}
});
//定義WebShow復合組件
var WebShow = React.createClass({
render:function(){
return (
<div>
<WebName />
<WebLink />
</div>
);
}
});
//渲染
ReactDOM.render(
<WebShow />,
document.getElementById("container")
);
注:以上所有內容都是本人的學習筆記和總結,僅供學習和參考,如果有遺漏或者不當的地方請諒解,請勿轉載。