天天看點

react可控元件和不可控元件

在React中的input标簽是有些小坑的,input本身就有自己的緩存機制,然後React的State也有緩存機制。這兩種緩存機制我們在編碼中是要進行取舍的。将input中的value綁定到state的React元件就是可控元件,反之則是不可控元件。

先看一個不可控的input代碼

//測試效果用
import React, { Component } from 'react';

class MyForm extends Component {
    constructor(props) {
        //super指代父類的執行個體(即父類的this對象)
        super(props);
        this.state = { 
            username: '',
            gender: 'man',
            checked: true,
            value: 'ferrysoul'
         };
    }
    getInitialState(){
    return { value: 'ferrysoul' }
};
handleChange(event) {
    this.setState({ value: event.target.value });
    console.log(this.state.value)
};
render() {
    return (
        <div>
            <input type="text" value={this.state.value}  />
        </div>
    )
}
}


export default MyForm;      

不可控的input無法改變值,不管你怎麼敲擊鍵盤輸入,input中的數值不會發生任何改變,打開控制台會有一個報錯資訊,

react可控元件和不可控元件

原因是:

因為input标簽,沒有定義onChange 但是提供了value屬性。React會抛出警告,并将元素設定為隻讀。

如果目标是隻讀字段,最好使用readOnly屬性明确加以定義。這不僅會消除警告,也會確定代碼的可讀性。

解決:

可以添加readOnly={true} ,或者直接添加readOnly屬性,而不設定值,React會預設将該屬性的值設為true。

一。設定onchang,變成可控input

(1)直接在函數後面.bind(this)

//測試效果用
import React, { Component } from 'react';

class MyForm extends Component {
    constructor(props) {
        //super指代父類的執行個體(即父類的this對象)
        super(props);
        this.state = { 
            username: '',
            gender: 'man',
            checked: true,
            value: 'ferrysoul'
         };
    }
    getInitialState(){
    return { value: 'ferrysoul' }
};
handleChange(event) {
    console.log(event.target.value)
    this.setState({ value: event.target.value });
    console.log(this.state.value)
};
render() {
    return (
        <div>
            <input type="text" value={this.state.value} onChange={this.handleChange.bind(this)} />
            <p>顯示你的value如下:</p>
            <p>{this.state.value}</p>
        </div>
    )
}
}


export default MyForm;      

(2.)在constructor中綁定this,在render中調用的時候就不需要bind了,直接  this.函數名

//測試效果用
import React, { Component } from 'react';

class MyForm extends Component {
    constructor(props) {
        //super指代父類的執行個體(即父類的this對象)
        super(props);
        this.state = { 
            username: '',
            gender: 'man',
            checked: true,
            value: 'ferrysoul'
        };
        this.handleChange = this.handleChange.bind(this);
    }
    getInitialState(){
    return { value: 'ferrysoul' }
};
handleChange(event) {
    console.log(event.target.value)
    this.setState({ value: event.target.value });
    console.log(this.state.value)
};
render() {
    return (
        <div>
            <input type="text" value={this.state.value} onChange={this.handleChange} />
            <p>顯示你的value如下:</p>
            <p>{this.state.value}</p>
        </div>
    )
}
}


export default MyForm;      

(3).直接使用箭頭函數:這種适用于函數塊代碼比較少的情況

//測試效果用
import React, { Component } from 'react';

class MyForm extends Component {
    constructor(props) {
        //super指代父類的執行個體(即父類的this對象)
        super(props);
        this.state = { 
            username: '',
            gender: 'man',
            checked: true,
            value: 'ferrysoul'
        };
    }
    getInitialState(){
    return { value: 'ferrysoul' }
};
// handleChange(event) {
//     console.log(event.target.value)
//     this.setState({ value: event.target.value });
//     console.log(this.state.value)
// };
render() {
    return (
        <div>
            <input type="text" value={this.state.value} onChange={(event) => { this.setState({ value: event.target.value });}} />
            <p>顯示你的value如下:</p>
            <p>{this.state.value}</p>
        </div>
    )
}
}


export default MyForm;      

二。依舊是不可控input,但是沒有報錯的問題了

//測試效果用
import React, { Component } from 'react';

class MyForm extends Component {
    constructor(props) {
        //super指代父類的執行個體(即父類的this對象)
        super(props);
        this.state = { 
            username: '',
            gender: 'man',
            checked: true,
            value: 'ferrysoul'
        };
    }
    getInitialState(){
    return { value: 'ferrysoul' }
};
render() {
    return (
        <div>
            <input type="text" value={this.state.value} readOnly={true}  />
            <p>顯示你的value如下:</p>
            <p>{this.state.value}</p>
        </div>
    )
}
}


export default MyForm;      

----------------------------------------------------------------------------------------------------------

//測試效果用
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class MyForm extends Component {
    constructor(props) {
        //super指代父類的執行個體(即父類的this對象)
        super(props);
        this.state = { 
            username: '',
            gender: 'man',
            checked: true,
            value: 'ferrysoul'
        };
        this.handleChange = this.handleChange.bind(this);
    }
    getInitialState(){
    return { value: 'ferrysoul' }
};
handleChange(event) {
    var inputValue = ReactDOM.findDOMNode(this.refs.ferrysoul).value;
    console.log(inputValue);
    this.setState({ value: event.target.value });
};
render() {
    return (
        <div>
            <input type="text" value={this.state.value} ref="ferrysoul" onChange={this.handleChange} />
            <p>顯示你的value如下:</p>
            <p>{this.state.value}</p>
        </div>
    )
}
}


export default MyForm;