手挽手帶你學React入門二檔,組件開發的開始,合理運用生命週期和組件,可以讓你的開發變地流利又happy,這篇文章帶你學會建立組件,運用組建。學起來吧!javascript
學習React,生命週期很重要,咱們瞭解完生命週期的各個組件,對寫高性能組件會有很大的幫助. 咱們先來看一張圖vue
組件初始化的時候java
一、getDefaultProps()node
設置默認的props,也能夠用dufaultProps設置組件的默認屬性.react
二、getInitialState()es6
在使用es6的class語法時是沒有這個鉤子函數的,能夠直接在constructor中定義this.state。此時能夠訪問this.props算法
三、componentWillMount()redux
組件初始化時只調用,之後組件更新不調用,整個生命週期只調用一次,此時能夠修改state。數組
四、 render()性能優化
react最重要的步驟,建立虛擬dom,進行diff算法,更新dom樹都在此進行。此時就不能更改state了。
五、componentDidMount()
組件渲染以後調用,只調用一次。
組件更新的時候 六、componentWillReceiveProps(nextProps)
組件初始化時不調用,組件接受新的props時調用。
七、shouldComponentUpdate(nextProps, nextState)
react性能優化很是重要的一環。組件接受新的state或者props時調用,咱們能夠設置在此對比先後兩個props和state是否相同,若是相同則返回false阻止更新,由於相同的屬性狀態必定會生成相同的dom樹,這樣就不須要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤爲是在dom結構複雜的時候
八、componentWillUpdata(nextProps, nextState)
組件初始化時不調用,只有在組件將要更新時才調用,此時能夠修改state,render 的時候會用你更改的值,可是這裏面不能調用 this.setState(),會讓你陷入死循環
九、render()
組件渲染
十、componentDidUpdate()
組件初始化時不調用,組件更新完成後調用,此時能夠獲取dom節點。
組件卸載的時候
十一、componentWillUnmount()
組件將要卸載時調用,一些事件監聽和定時器須要在此時清除。
// 在咱們組件第一次加載完的時候會這樣執行生命週期
export default class App extends Component {
constructor(){
super()
this.state={
}
}
// getDefaultProps(){
// es6 不支持這個
// console.log('1.執行getDefaultProps')
// 具體用法在下面
// }
// getInitialState(){
// es6裏不用它了
// console.log('2.執行getInitialState')
// 這個其實是上面的state 在 constructor實現
// }
componentWillMount(){
console.log('3.執行componentWillMount')
}
render() {
console.log('4.執行render')
return (
)
}
componentDidMount(){
console.log('5.執行componentWillMount')
}
}
// 接 getDefaultProps
// 在ES6裏這麼玩
// 還有一種玩法是ES7裏面的
// static defaultProps = {
// name: 'demo'
// }; 這裏咱們很少講了。。講多了該暈了 感興趣的加我微信 shouzi_1994
App.defaultProps = {
name: 'demo'
};
複製代碼
// 在咱們組件更新的時候咱們進行以下生命週期
export default class App extends Component {
constructor(){
super()
this.state={
name:'test'
}
}
componentWillReceiveProps(nextProps){
// props 更新的時候調用
console.log('1.執行componentWillReceiveProps')
}
shouldComponentUpdate(nextProps, nextState){
console.log('2.執行shouldComponentUpdate')
// 這個須要着重強調,咱們優化性能用它很重要!若是咱們即將更新的東西和原來的數據相同,return一個false就中止組件更新節約性能
if(nextState.name == this.state.name){
return false
}else{
return true
}
}
componentWillMount(nextProps, nextState){
// 在組件渲染前 調用這個
console.log('3.執行componentWillMount')
}
change=()=>{
this.setState({name:'QM'})
}
render() {
console.log('4.執行render')
return (
<button onClick={this.change}>測試</button>
)
}
componentDidUpdate(){
console.log('5.執行componentDidUpdate')
}
componentWillUnmount(){
// 這個在卸載的時候會調用 業務邏輯寫裏面就行了
}
}
複製代碼
生命週期簡單介紹就這些了,真正工做中要根據業務需求來調用,大大增長你的開發效率,處理你開發中遇到的難題。
其實咱們前面的App實際上就是一個組件了,咱們類比到vue裏面,它就是腳手架爲咱們建立的App.vue 是一個根組件,咱們別的組件都渲染到這個組件的內部就行了。
那麼 咱們如何建立一個子組件呢?
export default class App extends Component {
constructor(){
super()
this.state={
}
}
render() {
//要想使用子組件也很簡單 用標籤的形式拿進來就行了
return (
<Children /> ) } } //下面咱們再寫一個class 而且繼承 Component 這就是一個組件了 class Children extends Component{ constructor(){ super() this.state={ } } render(){ return( <h1>我是子組件</h1> ) } } 複製代碼
咱們學會了如何建立組件,那麼組件怎麼傳參呢?這個是很是重要的東西,畢竟組件之間不能通信,那就沒有建立它的意義了。
父子傳參
在React中父子傳參極其相似Vue 直接在標籤上填寫屬性,可是在子組件接收的時候會有所不一樣
咱們接着使用上面的代碼
export default class App extends Component {
constructor(){
super()
this.state={
}
}
render() {
//要想使用子組件也很簡單 用標籤的形式拿進來就行了
return (
<Children params={"我從父組件傳過來"}/> ) } } //下面咱們再寫一個class 而且繼承 Component 這就是一個組件了 class Children extends Component{ constructor(){ super() this.state={ } } // 經過這種形式 咱們就能夠把父組件的東西傳遞給子組件了,全部的屬性存儲在props裏面,上面咱們介紹生命週期的時候,也提了一下如何建立默認props。這裏咱們寫一下 render(){ return( <div> <h1>我是子組件</h1> <h2>{this.props.params}</h2> </div> ) } // 若是父組件沒有傳遞 params 咱們又想使用默認的props 那麼就要使用下面的寫法 } Children.defaultProps = { params: '我是默認的東西' }; // 設置了默認props之後 若是咱們不傳參就會默認展現咱們默認規定好的屬性了 複製代碼
插槽(相似Vue solt) 爲何要把插槽放在這裏講解呢?實際上React的插槽是經過傳參的形式下來的,怎麼理解呢?我以爲放進代碼中是最容易理解的。
export default class App extends Component {
constructor(){
super()
this.state={
}
}
render() {
//要想使用子組件也很簡單 用標籤的形式拿進來就行了
return (
<Children params={"我從父組件傳過來"}> <div>傳遞第一個</div> <div>傳遞第二個</div> <div>傳遞第三個</div> </Children>
)
}
}
//下面咱們再寫一個class 而且繼承 Component 這就是一個組件了
class Children extends Component{
constructor(){
super()
this.state={
}
}
// 經過這種形式 咱們就能夠把父組件的東西傳遞給子組件了,全部的屬性存儲在props裏面,上面咱們介紹生命週期的時候,也提了一下如何建立默認props。這裏咱們寫一下
render(){
console.log(this.props)
// {children:Array(3)
// params:"我從父組件傳過來"}
// children的內容爲 [
// {$$typeof: Symbol(react.element), type: "div", key: null, ref: null, props: {…}, …},
// {$$typeof: Symbol(react.element), type: "div", key: null, ref: null, props: {…}, …},
// {$$typeof: Symbol(react.element), type: "div", key: null, ref: null, props: {…}, …}
// ]
//咱們能夠看到 他們被順序放到了 this.props.children中 而且 這是個數組 內部存儲的就是虛擬dom
return(
<div> <h1>我是子組件</h1> {/* 這裏我用循環的方式把三個children取出來直接渲染便可 */} {this.props.children.map((item,key)=>{ return item })} {/* 咱們更加直觀一點 */} {this.props.children[1]} {this.props.children[0]} {this.props.children[2]} {/* 看到這裏你們應該能夠知道插槽的簡單用法了吧 */} </div>
)
}
// 若是父組件沒有傳遞 params 咱們又想使用默認的props 那麼就要使用下面的寫法
}
Children.defaultProps = {
params: '我是默認的東西'
};
複製代碼
子傳父參 在Vue中咱們能夠經過定義函數,以實參的形式傳遞,在父組件捕獲的形式來獲取想要傳遞的參數,那麼在React中這個辦法是否也一樣適用呢?答案是確定的,依舊是經過父組件聲明函數,傳遞給子組件,子組件調用並傳入參數,在父組件捕獲便可。
export default class App extends Component {
constructor(){
super()
this.state={
myPatams:"test"
}
}
getParams(params){
console.log(params,this)
this.setState({
myPatams:params
})
}
render() {
//要想使用子組件也很簡單 用標籤的形式拿進來就行了
return (
<div> {this.state.myPatams} <Children params={"我從父組件傳過來"} getParams={this.getParams.bind(this)}></Children> {/* 這裏咱們把函數傳遞下去,必定要bind this 不然在咱們在子組件中使用bind來調用的時候,this的指向會跑到子組件中 咱們拿到的參數意義就不大了 固然箭頭函數也是徹底沒問題的 */} </div>
)
}
}
//下面咱們再寫一個class 而且繼承 Component 這就是一個組件了
class Children extends Component{
constructor(){
super()
this.state={
}
}
render(){
return(
<div> <h1>我是子組件</h1> <button onClick={this.props.getParams.bind(this,"我是子傳過來的參數")}>子傳父參</button> {/* 咱們在這裏調用父組件傳遞過來的方法,而且傳入參數 */} </div>
)
}
}
Children.defaultProps = {
params: '我是默認的東西'
};
複製代碼
非父非子傳參(events 方法) 這種非關係型組件傳參通常使用redux來傳參,這裏咱們還有沒學習到,咱們藉助node的EventEmitter也能夠輕鬆實現
import React,{Component} from 'react'
// 首先咱們建立一個監聽器
import EventEmitter from 'events'; //事件監控對象
let emitter = new EventEmitter; //建立一個事件監控者 普通級別的監聽
emitter.setMaxListeners(100000); //設置監控管理器的最大監聽數量
export default class App extends Component {
constructor(){
super()
this.state={
myPatams:"test"
}
}
getParams(params){
console.log(params,this)
this.setState({
myPatams:params
})
}
render() {
//要想使用子組件也很簡單 用標籤的形式拿進來就行了
return (
<div> {this.state.myPatams} <Children params={"我從父組件傳過來"} getParams={this.getParams.bind(this)}></Children> {/* 這裏咱們把函數傳遞下去,必定要bind this 不然在咱們在子組件中使用bind來調用的時候,this的指向會跑到子組件中 咱們拿到的參數意義就不大了 固然箭頭函數也是徹底沒問題的 */} <ChildrenTwo /> </div>
)
}
}
//下面咱們再寫一個class 而且繼承 Component 這就是一個組件了
class Children extends Component{
constructor(){
super()
this.state={
emit:""
}
}
componentWillMount(){
emitter.on('childrenEmit',(param)=>{ //咱們在這裏設置監聽
console.log(param)
this.setState({
emit:param
})
})
}
render(){
return(
<div> <h1>{this.state.emit}</h1> <button onClick={this.props.getParams.bind(this,"我是子傳過來的參數")}>子傳父參</button> {/* 咱們在這裏調用父組件傳遞過來的方法,而且傳入參數 */} </div>
)
}
}
class ChildrenTwo extends Component{
constructor(){
super()
this.state={
}
}
gaveParams(param){
emitter.emit('childrenEmit',param) //從第二個子組件觸發而且傳遞參數
}
render(){
return(
<div> <h1>我是子組件</h1> <button onClick={this.gaveParams.bind(this,"我是ChildrenTwo傳過來的參數")}>非父非子傳參</button> </div>
)
}
}
複製代碼
寫了這麼多,相信你們差很少會寫本身的組件而且在組件中傳遞參數了,這裏還有一個問題,你們是否是發現個人全部組件都寫在了一個JS內部,這樣若是是一個大項目,咱們的這個JS就會變地很是臃腫,這時候咱們就要抽離這個組件。實際上很是簡單,用到的就是咱們ES6的 export 導出 便可 若是隻有一個組件 那麼 還能夠像咱們書寫App這個基礎組件同樣 使用 export default 默認導出
這裏我給你們抽離一下
// App.js
import React,{Component} from 'react'
import {Children} from './components/Children.js' // 由於咱們的Children中使用的是 export 來暴露
//import Children from './components/Children.js' // 若是使用的是 export default 則應該這樣寫
export default class App extends Component {
constructor(){
super()
this.state={
myPatams:"test"
}
}
getParams(params){
console.log(params,this)
this.setState({
myPatams:params
})
}
render() {
//要想使用子組件也很簡單 用標籤的形式拿進來就行了
return (
<div> {this.state.myPatams} <Children params={"我從父組件傳過來"} getParams={this.getParams.bind(this)}></Children> {/* 這裏咱們把函數傳遞下去,必定要bind this 不然在咱們在子組件中使用bind來調用的時候,this的指向會跑到子組件中 咱們拿到的參數意義就不大了 固然箭頭函數也是徹底沒問題的 */} </div>
)
}
}
複製代碼
// children.js
import React,{Component} from 'react'
// 當咱們抽離出來之後 必需要再次引入 react的必要組件
export class Children extends Component{ //咱們這裏使用的是export來暴露 若是隻有一個組件 也可使用 export default 來暴露
constructor(){
super()
this.state={
}
}
render(){
return(
<div> <h1>我是子組件</h1> <button onClick={this.props.getParams.bind(this,"我是子傳過來的參數")}>子傳父參</button> {/* 咱們在這裏調用父組件傳遞過來的方法,而且傳入參數 */} </div>
)
}
}
Children.defaultProps = {
params: '我是默認的東西'
};
複製代碼
大功告成了 代碼是否是清晰多了??
這一期內容很少 主要是介紹組件的生命週期 使用方法 以及如何傳參,這些內容可全都是乾貨,工做中會常常常用到,但願你們能本身寫小demo來熟悉一下寫法,下一期將會帶你們學習React-Router 以及context和高階組件的建立,爲咱們學習Redux打下基礎