React快速入門

weixin_34370347發表於2018-12-08

建立專案


1.npx create-react-app myapp

2.cd myapp

3.npm start


檔案說明

index.js檔案:
//加快react執行速度的js檔案
import * as serviceWorker from './serviceWorker';
補充:元件名稱首字母必須大寫

案例說明

資料基本繫結

import React, { Component } from 'react';
class Home extends Component {
    constructor() {
        super()
        this.state={
            user:{
                username:"qiang",
                age:30
            }
        }
    }

    render() {
        return (
            <div>
                <p>{this.state.user.username}</p>
                <p>{this.state.user.age}</p>
            </div>
        )
    }
}
export default Home;

style和class的繫結

說明:
class=> className
for => htmlFor


import React,{Component} from 'react';
import  '../assets/css/list.css';
class List extends Component{
    constructor(){
        super()
        this.state={
            name:["a","b","c"],
            style:{
                color:'red',
                fontsize:'40px'
            },
            color:'red',
            blue:'blue'
        }
    }

    render(){
        return(
            <div>
                <ul>
                <li style={this.state.style}>{this.state.name[0]}</li>
                // 注意此處:之所以兩層{}是因為內部也是物件
                <li style={{color:'red'}}>{this.state.name[1]}</li>
                <li style={{color:this.state.color}}>{this.state.name[2]}</li>
                </ul>
                <br/>
                <ul>
                    <li className='blue'>字串css</li>
                    <li className={this.state.blue}>變數css</li>
                </ul>
                // 此處for的特殊寫法
                <label htmlFor='in'>測試</label>
                <input type='text' id='in'/>
                <br/>
            </div>
            
    
        )
    }
}
export default List;

圖片引入和遍歷

import React, { Component } from 'react';
import img from '../assets/image/a.png'

class New extends Component {
    constructor() {
        super()
        this.state = {
            arr:["a","b"],
            //注意此處內部元素沒有""包裹
            arr1:[<p key="1">a</p>,<p key="2">b</p>]
        }
    }
    render() {
        //遍歷方式一
        let listResult=this.state.arr.map((val,index)=>{
            return <p key={index}>{val}--{index}</p>
        })
        return (
            <div>
                <p>引入圖片方式一</p>
                <img src={img} />
                <p>引入圖片方式二</p>
                <img src={require('../assets/image/a.png')} /><br/>
                {this.state.arr1}<br/>
                {listResult}<br/>
                //遍歷方式二
                {
                    this.state.arr.map((val,index)=>{
                        return <p key={index}>{val}</p>
                    })
                }
            </div>
        );
    }
}

export default New;

繫結this和傳參

說明:jsx的點選事件是onClick,而且不能加(),這代表立即執行
import React, { Component } from 'react';

class New extends Component {
    constructor() {
        super()
        this.state = {
            msg: '後設資料'
        }
        this.bindThis2 = this.bindThis2.bind(this)
    }
    test() {
        console.log("成功");
    }
    bindThis1() {
        console.log(this.state.msg);
    }
    bindThis2() {
        console.log(this.state.msg);
    }
    bindThis3 = () => {
        console.log(this.state.msg);
    }
    setStateInfo(info) {
        this.setState({
            msg: info
        })
    }
    render() {

        return (
            <div>
                {this.state.msg}
                <button onClick={this.test}>點選事件</button>
                <button onClick={this.bindThis1.bind(this)}>繫結this方式一</button>
                <button onClick={this.bindThis2}>繫結this方式二</button>
                <button onClick={this.bindThis3}>繫結this方式三</button>
                <button onClick={this.setStateInfo.bind(this,"修改的值")}>引數修改state值</button>
            </div>
        );
    }
}

export default New;

事件物件案例(獲取資料的兩種方式)

import React, { Component } from 'react';

class New extends Component {
    constructor() {
        super()
        this.state = {
            msg: ''
        }
    }
    test(event){
        // console.log(event);事件物件
        //獲取自定義屬性aid
        let aid=event.target.getAttribute('aid');
        console.log(aid);//123
    }
    inputChange=(event)=>{
        //獲取資料的方式一
        // let value=event.target.value;
        //獲取資料的方式二
        let value=this.refs.name.value;
        this.setState({
            msg:value
        })
    }
    showInfo=()=>{
        console.log(this.state.msg);
    }
    render() {
        return (
            <div>
               <button aid='123' onClick={this.test.bind(this)}>事件物件</button>
               <input type="text"  onChange={this.inputChange} ref='name'/>
                <input type="button" value="顯示輸入框的值" onClick={this.showInfo}/>
            </div>
        );
    }
}
export default New;

鍵盤事件

import React, { Component } from 'react';

class New extends Component {
    constructor() {
        super()
        this.state = {
            msg: ''
        }
    }
    
    onKeyUpChange=(event)=>{
        // console.log(event.keyCode);獲取鍵盤事件碼
        //enter事件
        if(event.keyCode==13){
            let value=event.target.value;
            this.setState({
                msg:value
            })
        }
    }
    render() {
        return (
            <div>
                <p>{this.state.msg}</p>
               <input type="text"  onKeyUp={this.onKeyUpChange} ref='name'/>
            </div>
        );
    }
}
export default New;

實現雙向資料繫結

import React, { Component } from 'react';

class New extends Component {
    constructor() {
        super()
        this.state = {
            msg: ''
        }
    }
    
    inputChange=(e)=>{
        this.setState({
            msg:e.target.value
        })
    }
    render() {
        return (
            <div>
                <p>{this.state.msg}</p>
               <input type="text"  value={this.state.msg} onChange={this.inputChange}  />
            </div>
        );
    }
}
export default New;
說明:input繫結value時候必須加上onChange方法否則會報錯,除非使用defaultValue
react中只有model改變影響view的單向資料流,所以如想實現雙向資料繫結,必須手寫
上面其實就是view改變改變model的過程程式碼
補充:
非約束型元件:例如非約束性元件中defaultValue就相當於原生dom的value,react不參與管理
約束型元件:例如非約束性元件中value,react參與管理(this.handleChange管理)
實際上,input中的value根本不是使用者輸入的值,而是onChange事件觸發後,由於this.setState導致一次重新渲染,不過react會優化演算法

表單相關

import React, { Component } from 'react';

class New extends Component {
    constructor() {
        super()
        this.state = {
            city:'',
            citys:["北京","上海"],
            sexs:[
                {key:"乒乓球",value:false},
                {key:"籃球",value:false},
                {key:"足球",value:true}
            ]
        }
    }
    submitMethod=(e)=>{
        //阻止預設事件
        e.preventDefault();
        console.log(this.state);
    }
    optionSet=(e)=>{
        this.setState({
            city:e.target.value
        })
    }
    sexsChange(index){
        //react接管了預設點選操作,如果布變更資料,則介面點選無效
        let sexs=this.state.sexs;
        sexs[index].value=!sexs[index].value;
        this.setState({
            sexs
        })
    }
    render() {
        return (
            <div>
                <p>{this.state.city}</p>
                <form>
                    <select value={this.state.city} onChange={this.optionSet}>
                    {
                        this.state.citys.map((value,index)=>{
                            return <option key={index}>{value}</option>
                        })
                    }
                    </select>
                    
                    {
                        this.state.sexs.map((value,index)=>{
                            return <span key={index}>
                                <input type="checkbox" onChange={this.sexsChange.bind(this,index)}  checked={value.value}/>{value.key}
                            </span>
                        })
                    }

                    <br/>
                    <input type="submit" value="提交" onClick={this.submitMethod}/>
                </form>
            </div>
        );
    }
}
export default New;

父子元件相關

父子元件互相傳參

父元件:
import React, { Component } from 'react';
import Header from './Header'

class New extends Component {
    constructor(props) {
        super(props)
        this.state = {
           msg:"New傳入的引數"
        }
    }
    show=()=>{
        console.log("被子元件呼叫的父元件的方法");
    }
    send2Parent=(info)=>{
        this.setState({
            msg:info
        })
    }
    getChildCom=()=>{
        //既然可以獲取子元件,則屬性方法自然都可以使用
        console.log(this.refs.header);
    }
    render() {
        return (
            <div>
                <p>{this.state.msg}</p>
                <input type="button" value="父元件獲取子元件" onClick={this.getChildCom}/>
                <Header msg={this.state.msg} ref='header' new={this} method={this.show}/>
            </div>
        );
    }
}
export default New;

defaultProps和propTypes


  1. defaultProps:父子元件傳值中,如果父元件呼叫子元件的時候不給子元件傳值,則可以在
    子元件中使用defaultProps定義的預設值

  2. propTypes:驗證父元件傳值的型別合法性


子元件:
import React, { Component } from 'react';
//驗證資料型別需要引入PropTypes
import PropTypes from 'prop-types';
class Header extends Component {
    showParent=()=>{
        console.log(this.props.new);
    }
    render() {
        return (
            <div>
                <p>{this.props.msg}</p>
                <button onClick={this.props.method}>呼叫父元件方法</button>
                <button onClick={this.showParent}>獲取整個父元件</button>
                <button onClick={this.props.new.send2Parent.bind(this,"子元件傳遞的")}>子元件給父元件傳值</button>
            </div>
        );
    }
}
//如果例如父元件沒傳入title則使用該預設值,否則使用父元件傳值
//針對的是this.props.title是否傳入
Header.defaultProps={
    title:"標題"
}
//驗證資料型別,注意propTypes和PropTypes
Header.propTypes={
    title:PropTypes.string
}
export default Header;

生命週期


1.元件載入的時候觸發的函式:

constructor(建構函式) componentWillMount(元件將要掛載) render(渲染) componentDidMount(元件掛載完畢)

2.元件更新的時候觸發的函式:

shouldComponentUpdate(更新資料) ComponentWillUpdate(元件將要更新) render componentDidMount

2.1 補充

shouldComponentUpdate(nextProps,nextState){

比較props或者states,返回true則更新照常,返回false則取消更新,
且不會呼叫下面的兩個生命週期函式

}

分別是更新後的父子元件的傳遞引數和更新後的state

使用場景:父元件有子元件A和子元件B,當父元件呼叫this.setState更新一個作為子元件A屬性
的state時,render方法被再次呼叫,此時元件A和元件B同時被更新,其實真正改變的只有元件
A,但元件B也同時被要求更新了,這是沒有必要的,於是shouldComponentUpdate就顯的有用
了,在該函式體內比較props或是states,如果沒有改變就取消這個更新,這對效能上算是一個提
升。因為傳遞過來到元件的都是更新過的,可以和該元件當前的prop和state比較,從而通過返回布林值確定是否需要更新該元件

3.在父元件裡面改變props傳值的時候觸發的函式:

componentWillReceiveProps

4.元件銷燬的時候觸發的函式:

componentWillUnmount

注意:絕對不要在componentWillUpdate和componentDidUpdate中呼叫this.setState方法,否則將導致無限迴圈呼叫。


元件銷燬的案例:

父元件:
import React, { Component } from 'react';
import Header from './Header'

class New extends Component {
    constructor(props) {
        super(props)
        this.state = {
           msg:"引數",
           flag:true
        }
    }
    destoryChild=()=>{
        this.setState({
            flag:!this.state.flag
        })
    }
    render() {
        return (
            <div>
                <button onClick={this.destoryChild}>切換子元件</button>
                {
                    this.state.flag?<Header />:''
                }
            </div>
        );
    }
}
export default New;

子元件:
import React, { Component } from 'react';

class Header extends Component {
   
    render() {
        return (
            <div>
               <p>Header元件</p>
            </div>
        );
    }
    componentWillUnmount(){
        console.log("元件銷燬");
    }
}
export default Header;
說明:每一次點選切換子元件都可以讓子元件顯示或者銷燬,每次銷燬時候觸發子元件的componentWillUnmount