React基础(一)


组件声明

React中声明组件有两种方式,一是函数式组件,就是把一个函数作为组件的构造器;二是class组件,即用ES6class语法声明一个类作为组件的构造器。在16.8版本以前函数式组件不能使用组件的staterefs属性等诸多特性,这使得函数式组件只能用来定义一些简单组件,对于复杂一些的组件只能使用class组件。而此版本以后React加入了Hook,使得函数式组件也能够使用组件的其它特性。官方文档

函数式组件

函数式组件中我们只能用props属性,定义一个函数式组件只需要创建一个开头为大写字母的函数,然后再将函数最后return回一个jsx标签即可。代码如下:

function Person(props) {
    return (
    	<div>
            <h2>{props.name}</h2>
        </div>
    )
}
ReactDOM.render(<Person name="Asuhe" />,document.querySelector('#root'))

class组件

class组件要比函数式组件强大的多,它可以完全使用组件三大属性:statepropsrefs。它还有生命周期函数可供使用,在生命周期函数中我们可以进行许多操作。但创建一个class组件需要从React对象中继承一个类React.Component。代码如下:

class MyComponent extends React.Component {
    // render函数必须要有
    render(){
        return (
            <div>
                <h2>Asuhe</h2>
            </div>
        )
    }
}
ReactDOM.render(<MyComponent />,document.querySelector('#root'))

当我们需要在class组件上挂载事件处理函数时有两种方式,一是在constructor中重写该事件处理函数,二是利用箭头函数和class语法声明函数。

class Weather extends React.Component {
    /* 第一种方法 在jsx中调用的this调用weather和设置state
    constructor(props) {
        super(props)
        this.state = { isHot: true, breeze: '微风' }
        // 关键步骤:将原型上的changeWeather挂载载到组件实例对象的changeWeather里并更改this
        this.changeWeather = this.changeWeather.bind(this)
    }
    changeWeather() {
        let {isHot} = this.state
        this.setState({
            isHot: !isHot
        })
    }
    // 未重写changeWeather前,onClick绑定的this.changeWeather相当于
    // let a = new Weather()
    // let x = a.changeWeather
    // x()
    */
    // 第二种方法 不在原型上挂载changeWeather
    state = { isHot: true, breeze: '微风' }
    changeWeather = () => {
        let { isHot } = this.state
        this.setState({
            isHot: !isHot
        })
    }
    render() {
        return (
            <h2 onClick={this.changeWeather}>
                今天天气很{this.state.isHot ? '炎热' : '凉爽'},{this.state.breeze}
            </h2>
        )
    }
}
ReactDOM.render(<Weather />, el)

组件的三大属性

组件实例中有很多属性,但比较常用的就三个分别是:state、props、refs。

image-20220614101741901

state

state属性是用来存储该组件实例的状态的。当我们使用this.setState函数去修改state时,页面会因为组件状态改变而同步改变。以上面的MyComponent组件为例,我们可以给组件定义一个初始状态:

class MyComponent extends React.Component {
    /* 第一种方式在构造器里初始化状态
    constructor(props){
    	// 使用了构造器就一定要调用super 否则React报错
        super(props)
        this.state = {name:'Asuhe'}
        // 若不给super传props,则在constructor中使用this.props可能会出错
    }
    */
    // 第二种方式
    state = {name:'Asuhe'}
    // render函数必须要有
    render(){
        return (
            <div>
                <h2>{this.state.name}</h2>
            </div>
        )
    }
}

props

props属性是用来接收外部传给组件的数据的,如果我们直接在标签上写数据,props会自动接收该数据。

ReactDOM.render(<MyComponent age={18} />,document.querySelector('#root'))

image-20220614103444298

限制props的数据类型

有时候我们希望限制传入数据的类型,此时我们需要额外加载一个prop-types.js包,里面有PropTyps对象以供我们使用。示例代码如下:

// 需求: 
// 1.name属性必须为string,age属性必须为number,sex属性必须为string
// 2.sex属性必须传入
// 3.sex若未传入则默认值为male
class Person extends React.Component {
    static propTypes = {
        name: PropTypes.string,
        age: PropTypes.number,
        // sex为必须
        sex: PropTypes.string.isRequired
    }
    // 设置默认props值
    static defaultProps = {
        sex: 'male'
    }
    render() {
        return (
            <ul>
                <li>name:{this.props.name}</li>
                <li>age:{this.props.age}</li>
                <li>sex:{this.props.sex}</li>
            </ul>
        )
    }
}
let data = {
    name: 'asuhe',
    age: 22,
    // sex: 'male'
}
ReactDOM.render(<Person {...data} />, el)

refs

当我们需要获取标签or组件实例时,可以使用ref标记。然后就可以在函数中利用this.refs找到该组件or标签。ref有三种形式分别是:字符串类型、回调函数类型和refs对象类型。

字符串类型的ref

字符串形式的ref 已经不推荐使用, ref会被自动收录进组件的refs里,如同props。

class Person extends React.Component {
    showData = (event) => {
        event.preventDefault()
        let { input2: { value } } = this.refs
        console.log(value)
    }
    render() {
        return (
            <form>
                <input ref="input1" type="text" placehoder="username" />
                <button onClick={this.showData}>提交</button>
                <input ref="input2" type="password" placehoder="password" />
            </form>
        )
    }
}
ReactDOM.render(<Person />, el)

image-20220614104753532

回调函数类型的ref

回调函数形式的ref 会将该标签DOM传给回调函数的形参,用this接住挂载在组件实例上。

class Person extends React.Component {
    showData = (event) => {
        event.preventDefault()
        let { input2: { value } } = this
        console.log(value)
    }
    render() {
        return (
            <form>
                <input ref={a => this.input1 = a} type="text" placehoder="username" />
                <button onClick={this.showData}>提交</button>
                <input ref={b => this.input2 = b} type="password" placehoder="password" />
            </form>
        )
    }
}
ReactDOM.render(<Person />, el)

image-20220614104935057

refs对象类型的ref

使用自定义ref对象 ref对象内含{ current:被ref标记的标签实例 } 当多个标签使用同一个ref对象标记时,仅保留最后一个。

class Person extends React.Component {
    // 若要ref标记多个标签实例,则需要声明多个属性创建多个React.createRef
    myRefs = React.createRef()
    showData = (event) => {
        event.preventDefault()
        let { current: { value } } = this.myRefs
        console.log(value)
    }
    render() {
        return (
            <form>
                <input ref={this.myRefs} type="text" placehoder="username" />
                <button onClick={this.showData}>提交</button>
                <input ref={this.myRefs} type="password" placehoder="password" />
            </form>
        )
    }
}
ReactDOM.render(<Person />, el)

image-20220614105049968