React (three) - React form uncontrolled components of the controlled components

table of Contents

1. Form

1.1 The controlled components

1.1.1input

1.1.2textarea

1.1.3select-- radio

1.1.4select-- multiple choice

 1.1.5 Radio

1.2 Non-controlled components --Refs & DOM (DOM operation element)

1.2.1ref property

1.2.2 callback Refs

1.2.3React.createRef()

2. Recommendations


1. Form

In React years, HTML works form elements and other DOM element is somewhat different.

In general, the form and the form controls (such as: input, select ......) is a page with JavaScript dealing with most of the elements. While we can ref to operate their form, but that would be more trouble, React.js provides a better way for us to React.js correlate the data and logic and form controls .

1.1 The controlled components

  • 受控组件: With props incoming data, the components can be considered controlled (because the components are passed props parent control)
  • 非受控组件: Data from external incoming props data control, only stored in the internal component state , then a non-controlled components (because the outside can not directly control the state )

Broadly speaking, any element on the page is a separate component, form controls is that they will maintain the internal state of their own (such as: value, selected, checked ......) , of course, these states are former students achieve, rather than React.js controlled, but sometimes we hope React.js to manage and maintain the state of form controls, we call this control (controls) known as: controlled components , different components, state maintenance also different ways

  • input
  • textarea
  • select

Through state to a state control component

  • Create a state and a state assembly binding
  • Some components listen for events to update the state

How to become a non-controlled components controlled components?

  • input non-controlled components, maintaining the internal private data (value), passing from the external control props parameter;
  • Uncontrolled components to transform into a controlled components: by onChange monitor changes to the data, and then get target after deconstruction of the event object, and then get the data inside

The <input type "text" value = {this.state.v1} / => non-controlled components, value value, by themselves help to maintain their own internal state of the external changes, does not receive external parameters passed props. At this point you want to change the input after the input box, input the value changes are also possible, which is non-controlled components.

By listening uncontrolled assembly onChange event onChange = {this.changeValue}, this.changeValue = this.changeValue.bind (this) binding, this time will be given a method changeValue event object (event parameter is the first object), the object can be obtained through the event input value, <input type = "text" value = {this.state.v1} onChange = {this.changeValue} /> bound to the value input box.

changeValue({target:{value:v1}}) {
        this.setState({
            v1
        });
    }

1.1.1input

Controlled property  value  property.

import React from 'react';

class CanControll extends React.Component{
    constructor(props){
        super(props);
        //1.创建state状态,使val与input的value值进行绑定
        this.state = {
            val:'kaikeba'
        }
        this.changeVal = this.changeVal.bind(this);
    }

    //2.监听组件onChange事件来更新state
    //将target解构出来,再对里面的对象进行解构,赋值给别名val
    changeVal({target:{value:val}}){
        // const user = {
        //     id: 123,
        //     name: 'hehe',
        //     education: {
        //       degree: 'Masters'
        //     }
        //   };
        //   const {education: {degree:vala}} = user;
        //   console.log(vala); //prints: Masters
        
        //注意setState()是方法
        this.setState({
            val
        })
    }

    // changeVal(e) {
    //     this.setState({
    //         val: e.target.value
    //     });
    // }

    render(){
        return(
            <div>
                <input type="text" value={this.state.val} onChange={this.changeVal} />
                <hr/>
                {this.state.val}      
            </div>
        );
    }
}

export default CanControll;

By the controlled components, it can be more convenient control component interaction

...
changeValue({target:{value}}) {
    this.setState({
            v1: value.toUpperCase()
    });
}
...

1.1.2textarea

textarea and input  a similar principle, but should be noted that: use value , rather than the contents ( the innerHTML )

// 正确
<textarea value={this.state.v2} onChange={this.changeValue2} cols="30" rows="10"></textarea>
// 错误
<textarea onChange={this.changeValue2} cols="30" rows="10">{this.state.v2}</textarea>

1.1.3select-- radio

select the React.js also done some treatment, no longer by selected to represent the selected element property, but by select the tag value attributes.

NOTE: When using the structure {target: {options}, from the configuration options

import React from 'react';

/**
 * select的非受控组件
 */
class CanControll extends React.Component {
    constructor(props) {
        super(props);
        //1.创建state状态,使val与input的value值进行绑定
        this.state = {
            val: 'html'
        }
        this.changeVal = this.changeVal.bind(this);
    }

    //2.监听组件onChange事件来更新state
    //将target解构出来,再对里面的对象进行解构,赋值给别名val
    changeVal({target:{options}}) {
        this.setState({
            val:options
        })
    }

    render() {
        return (
            <div>
                <select value={this.state.val} onChange={this.changeValue3}>
                    <option value="html">html</option>
                    <option value="css">css</option>
                    <option value="javascript">javascript</option>
                </select>
                <hr/>
                <div>{this.state.val}</div>
                
            </div>
        );
    }
}

export default CanControll;

1.1.4 SELECT - multiple choice

We can also set multiple choice the SELECT , the corresponding value is an array

...
this.state = {
    v4: ['html', 'javascript']
}
...
​
...
changeValue4({target:{options}}) {
  this.setState({
    v4: [...options].filter(o=>o.selected).map(o=>o.value)
  });
}
...
​
...
<select value={this.state.v4} onChange={this.changeValue4} multiple>
    <option value="html">html</option>
    <option value="css">css</option>
    <option value="javascript">javascript</option>
</select>
...

Example:

import React from 'react';

/**
 * select(多选:从多个选项中选择一个)的非受控组件
 */
class CanControll extends React.Component {
    constructor(props) {
        super(props);
        //1.创建state状态,使val与input的value值进行绑定
        this.state = {
            //select多选时,对应的 value 就是一个数组
            val: ['html','js']
        }
        this.changeVal = this.changeVal.bind(this);
    }

    //2.监听组件onChange事件来更新state
    changeVal({ target: { options } }) {
        this.setState({
            //因为select多选对应的value是数组,所以通过扩展运算符,将options中所有值展开到数组中
            val:  [...options].filter(o=>o.selected).map(o=>o.value)
        })
    }

    render() {
        return (
            <div>
                <select value={this.state.val} onChange={this.changeVal} multiple>
                    <option value="html">html</option>
                    <option value="css">css</option>
                    <option value="javascript">javascript</option>
                </select>
                <hr />
                {this.state.val.join(',')}

            </div>
        );
    }
}

export default CanControll;

 1.1.5 Radio

radio and the following checkbox should be noted that the controlled property is no longer a value , but checked

...
this.state = {
    v5: '女',
        v6: ['前端', '后端'],
}
​
...
changeValue5(e) {
    this.setState({
        v5: e.target.value
    });
}
​
changeValue6({target:{value}}) {
    let {v6} = this.state;
    if (v6.includes(value)) {
        v6 = v6.filter(v=>v!==value);
    } else {
        v6.push(value)
    }
    this.setState({
        v6
    });
}
...
​
...
<label><input name="gender" type="radio" value="男" checked={this.state.v5==='男'} onChange={this.changeValue5} />男</label>
<label><input name="gender" type="radio" value="女" checked={this.state.v5==='女'} onChange={this.changeValue5} />女</label>
​
<label><input name="interest" type="checkbox" value="前端" checked={this.state.v6.includes('前端')} onChange={this.changeValue6} />前端</label>
<label><input name="interest" type="checkbox" value="后端" checked={this.state.v6.includes('后端')} onChange={this.changeValue6} />后端</label>
...

Example:

import React from 'react';

/**
 * radio和checkbox的非受控组件
 */
class CanControll extends React.Component {
    constructor(props) {
        super(props);
        //1.创建state状态,使val与input的value值进行绑定
        this.state = {
            v5: '女',
            v6: ['前端', '后端'],
        }
        this.changeValue5 = this.changeValue5.bind(this);
        this.changeValue6 = this.changeValue6.bind(this);
    }

    //2.监听组件onChange事件来更新state
    changeValue5({ target: { value: v5 } }) {
        this.setState({
            v5
        });
    }

    changeValue6({ target: { value } }) {
        let { v6 } = this.state;
        if (v6.includes(value)) {
            v6 = v6.filter(v => v !== value);
        } else {
            v6.push(value)
        }
        this.setState({
            v6
        });
    }

    render() {
        return (
            <div>
                <label><input name="gender" type="radio" value="男" checked={this.state.v5 === '男'} onChange={this.changeValue5} />男</label>
                <label><input name="gender" type="radio" value="女" checked={this.state.v5 === '女'} onChange={this.changeValue5} />女</label>

                <label><input name="interest" type="checkbox" value="前端" checked={this.state.v6.includes('前端')} onChange={this.changeValue6} />前端</label>
                <label><input name="interest" type="checkbox" value="后端" checked={this.state.v6.includes('后端')} onChange={this.changeValue6} />后端</label>
            </div>
        );
    }
}

export default CanControll;

1.2 Non-controlled components - Refs & DOM (DOM operation element)

Then again, by the above study, we know that each of the controlled components, and different states can control the types of controlled components only so few: value , the checked , but is actually a component of the state far more than these, such as input status focus, disabled, read-only, all of the components, if each state is managed by the above manner, would be particularly troublesome. Not with React and Vue and other frameworks need to operate after the DOM elements, and this time, we need to address the other way: DOM

Refs & DOM

React.js provides several ways to get DOM elements:

  • Callback Refs

  • React.createRef()

1.2.1ref property

Whether callback Refs or React.createRef () , is required by a property ref to be set. When a function value of the ref attribute .

<input ref={?} />

Example:

import React from 'react';

/**
 * 非受控组件:回调refs——获取元素信息
 */
class CanControll extends React.Component {
    constructor(props) {
        super(props);
        this.selectURL = this.selectURL.bind(this);
        this.getElementInfo = this.getElementInfo.bind(this);

        //使用React.createRef()需要在构造函数中挂载
        this.refDiv = React.createRef();
    }

    //获取复制信息
    selectURL(){
        //选中input的内容
        this.refInput.select();
        console.log(this.refInput.value);
    }

    //获取元素信息
    getElementInfo(){
        console.log(this.refDiv.current.offsetHeight);
        
    }

    render() {
        return (
            <div>
                {/* 此处el=>this.refInput = el 相当于方法
                    function(el){
                        this.refInput = el;//将当前元素el复制给this.refInput,但是此处this指向undefined,所以需要使用箭头函数
                    }
                */}
                <input ref={el=>this.refInput = el} type="text" value="http://kaikeba.com" />
                <button onClick={this.selectURL}>点击复制</button>
                <hr />
                <button onClick={this.getElementInfo}>获取元素信息</button>
                <div ref={this.refDiv} style={{ width: '100px', height: '100px', background: 'red' }}></div>
            </div>

        );
    }
}

export default CanControll;

 

1.2.2 callback Refs

In this way, we have used in the previous over

class UnControlledComponent extends React.Component {
    constructor(props) {
        super(props);
        this.selectURL = this.selectURL.bind(this);
        this.getElementInfo = this.getElementInfo.bind(this);
    }
  
    selectURL() {
        this.refInput.select();
    }
​
    getElementInfo() {
        this.refDiv.getBoundingClientRect()
    }
  
    render() {
        return (
            <input ref={el => this.refInput = el} type="text" value="http://kaikeba.com" />
            <button onClick={this.selectURL}>点击复制</button>
            <hr/>
            <button onClick={this.getElementInfo}>获取元素信息</button>
            <div ref={el => this.refDiv = el} style={{width: '100px', height:'100px',background:'red'}}></div>
        )
    }
}

1.2.3React.createRef()

This method returns a ref objects , in jsx by ref binding property of the object, the object under current attribute points to an element or component objects bound

class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
    }
​
    hello() {
        console.log('ChildComponent');
    }
​
    render() {
        return(
            <div>
                <h2>ChildComponent</h2>
            </div>
        );
    }
}
​
class UnControlledComponent extends React.Component {
    constructor(props) {
        super(props);
        this.selectURL = this.selectURL.bind(this);
        this.getElementInfo = this.getElementInfo.bind(this);
      
        this.refInput = React.createRef();
        this.refDiv = React.createRef();
        this.refChild = React.createRef();
    }
  
    selectURL() {
        this.refInput.current.select();
    }
​
    getElementInfo() {
        this.refDiv.current.getBoundingClientRect()
    }
  
    getElementInfo() {
        this.refChild.current;
    }
  
    render() {
        return (
            <input ref={this.refInput} type="text" value="http://kaikeba.com" />
            <button onClick={this.selectURL}>点击复制</button>
            <hr/>
            <button onClick={this.getElementInfo}>获取元素信息</button>
            <div ref={this.refDiv} style={{width: '100px', height:'100px',background:'red'}}></div>
            <hr/>
            <ChildComponent ref={this.refChild} />
            <button onClick={this.getReactComponent}>获取 React 实例对象</button>
        )
    }
}

2. Recommendations

  • Try to avoid the props derived in state
  • Try to use props , avoid the use of state
Published 95 original articles · won praise 115 · views 120 000 +

Guess you like

Origin blog.csdn.net/qq_34569497/article/details/105181659