React基础学习第二篇

136 阅读3分钟

前言

梦想注定是孤独的旅程,路上少不了质疑和嘲笑,但那又怎样,哪怕遍体鳞伤也要勇往直前。有梦别怕痛,想赢别喊停!

1.有状态组件

<div id="root"></div>
    <script type="text/babel">
        class Hello extends React.Component {
            // 有状态的组件需要使用render方法进行渲染,是生命周期里面非常基础和底层的方法,一定要用它来进行渲染
            render() {
                return <h1>hello weiyu</h1>
            }
        }
        ReactDOM.render(
            <Hello/>,
            document.getElementById("root")
        )
    </script>

2.有状态组件props

  <div id="root"></div>
    <script type="text/babel">
        class Hello extends React.Component {
            render() {
                return <div>
                    <h1>这是一个有状态组件</h1>
                    <h1>姓名:{this.props.name}</h1>
                    <h1>年龄:{this.props.age}</h1>
                    <h1>性别:{this.props.sex}</h1>
                </div>
            }
        }
        ReactDOM.render(
            <Hello name="weiwei" age="18" sex="男"/>,
            document.getElementById("root")
        )
    </script>

3.有状态组件state

<div id="root"></div>
    <script type="text/babel">
        class Hello extends React.Component {
            // super是把属性传递给父级的构造类对象
            // 子类必须在constructor构造器里调用super方法,从而得到父类的this对象,
            // super()加不加props的区别究竟在哪里
            // 需要在构造器函数中使用this.props则在super中添加props参数,
            // 如果不需要传值的话就不用在super中接收props
            constructor(props) {
                super(props)
                this.state = {
                    age: '18',
                    sex: '男'
                }
                console.log(props, this.props);
                // this.props = props
            }
            render() {
                return <div>
                    <h1>这是一个有状态组件</h1>
                    <h1>姓名:{this.props.name}</h1>
                    <h1>年龄:{this.state.age}</h1>
                    <h1>性别:{this.state.sex}</h1>
                </div>
            }
        }
        ReactDOM.render(
            <Hello name="weiwei"/>,
            document.getElementById("root")
        )
    </script>

4.state简写

<div id="root"></div>
    <script type="text/babel">
        class Hello extends React.Component {
            // 在开发中比较倾向于下面这种写法
            state = {
                age: '16',
                sex: '男'
            }
            render() {
                return <div>
                    <h1>这是一个有状态组件</h1>
                    <h1>姓名:{this.props.name}</h1>
                    <h1>年龄:{this.state.age}</h1>
                    <h1>性别:{this.state.sex}</h1>
                </div>
            }
        }
        ReactDOM.render(
            <Hello name="weiwei"/>,
            document.getElementById("root")
        )
        // 怎么选择使用有状态组件还是无状态组件?我们开发中更多的应该去使用哪种组件?
        // 更多时间尽可能的去选择使用无状态组件,因为如果是有状态组件,它就会触发生命周期所对应的一些函数
        // 状态改变,就会触发虚拟dom重新渲染,它就会影响当前项目的运行,除非是需要对数据做一些存储、处理等,这个时候就选择有状态组件。
    </script>

5.事件处理

 <div id="root"></div>
    <script type="text/babel">
        class Hello extends React.Component {
            constructor(props) {
                super(props)
                this.state = {
                    age: '16',
                    sex: '男',
                    flag: true
                }
                this.updateAge = this.updateAge.bind(this)
            }
            // 1、函数的作用域由函数调用的时候决定的,而不是函数声明的时候
            // 如果使用函数的形式直接定义,要在constructor去绑定this改变this指向
            updateAge() {
                // console.log(this); // 如果不在constructor里面去绑定this打印出来的是undefined
                this.setState({
                    age: 5
                })
            }

            // 2、要么使用箭头函数赋值的方法来定义函数,这是工作中比较常用的方法
            updateState = () => {
                this.setState({
                    flag: !this.state.flag
                })
            }

            render() {
                return <div>
                    <h1>这是一个有状态组件</h1>
                    <h1>姓名:{this.props.name}</h1>
                    <h1>年龄:{this.state.age}</h1>
                    <h1>性别:{this.state.sex}</h1>
                    <button onClick={this.updateAge}>更新年龄</button>
                    <button onClick={this.updateState}>{this.state.flag ? 'YES' : 'NO'}</button>
                </div>
            }
        }
        ReactDOM.render(
            <Hello name="weiwei"/>,
            document.getElementById("root")
        )
    </script>
    
    

6.事件处理

<div id="root"></div>
    <script type="text/babel">
        class Hello extends React.Component {
            state = {
                name: 'jindu',
                age: 14,
                flag: true
            }
            updateInfo() {
                console.log(this)
                this.setState({
                    age: 5
                })
            }
            updateState() {
                this.setState({
                    flag: !this.state.flag
                })
            }
            render() {
                return <div>
                    <h1>这是一个有状态组件</h1>
                    <h1>姓名:{this.state.name}</h1>
                    <h1>年龄:{this.state.age}</h1>
                    <button onClick={this.updateInfo.bind(this)}>更新年龄</button>
                    <button onClick={() => this.updateState()}>{this.state.flag ? 'TRUE' : 'FALSE' }</button>
                </div>
            }
        }
        ReactDOM.render(
            <Hello/>,
            document.getElementById("root")
        )
    </script>

7.事件与条件处理

 <div id="root"></div>
    <script type="text/babel">
        // 根据登录状态来展示不同的组件,true展示login组件,false展示logout组件
        function Login() {
            return <button>login</button>
        }
        function Logout() {
            return <button>logout</button>
        }
        class Hello extends React.Component {
            state = {
                isLogin: true
            }
            updateState = () => {
                this.setState({
                    isLogin: !this.state.isLogin
                })
            }
            
            render() {
                // const isLogin = this.state.isLogin
                const { isLogin } = this.state
                return <div>
                    <h1>这是一个有状态组件</h1>
                    { isLogin ? <Login/> : <Logout/> }
                    <button onClick={this.updateState}>更新状态</button>
                </div>
            }
        }
        ReactDOM.render(
            <Hello/>,
            document.getElementById("root")
        )
        // React中为什么要使用setState修改状态?
        // React没有实现类似于Vue2的Object.defineProperty或者是Vue3的proxy方式来监听数据的变化
        // 所以必须通过setState来告知react状态的改变,setState是继承自Component,当我们调用setState的时候
        // 会重新执行render方法
    </script>

8.事件与条件处理

<div id="root"></div>
    <script type="text/babel">
        // 把父组件的方法传递给子组件,并且让子组件能够进行调用
        function Login(props) {
            // console.log(props);
            return <button onClick={props.updated}>login</button>
        }
        function Logout(props) {
            return <button onClick={props.updated}>logout</button>
        }
        class Hello extends React.Component {
            state = {
                isLogin: true
            }
            updateState = () => {
                this.setState({
                    isLogin: !this.state.isLogin
                })
            }
            
            render() {
                const { isLogin } = this.state
                return <div>
                    <h1>这是一个有状态组件</h1>
                    { isLogin ? <Login/> : <Logout/> }
                    { isLogin ? <Login updated={this.updateState}/> 
                    : <Logout updated={this.updateState}/> }
                    <button onClick={this.updateState}>更新状态</button>
                </div>
            }
        }
        ReactDOM.render(
            <Hello/>,
            document.getElementById("root")
        )
    </script>

9.受限组件

<div id="root"></div>
    <script type="text/babel">
        // Vue事项了响应式数据,但是React中不具备响应式特性,所以在应用中有很多东西需要我们手动完成
        class Hello extends React.Component {
            render() {
                return <input type="text" value="123" />
            }
            // 此时Hello作为一个受限组件渲染出来之后,我们去输入输入框任何值都无效,如果要响应用户输入的值,就必须使用onChange事件。
        }
        ReactDOM.render(
            <Hello/>,
            document.getElementById("root")
        )
    </script>

    <!-- 双向数据绑定 -->
    <hr>
    <div id="root2"></div>
    <script type="text/babel">
        class App extends React.Component {
            state = {
                value: 'hello'
            }
            change = (event) => {
                console.log(event);
                this.setState({
                    value: event.target.value
                })
            }
            render() {
                return <div>
                    <input type="text" value={this.state.value} onChange={this.change} />
                    <h2>{this.state.value}</h2>
                </div>
            }
        }
        ReactDOM.render(
            <App/>,
            document.getElementById("root2")
        )
    </script>

    <!-- radio、textarea、select -->
    <hr>
    <div id="root3"></div>
    <script type="text/babel">
        class Rts extends React.Component {
            render() {
                // 这些给了值之后都不能直接进行更改
                return <div>
                    <input type="radio" checked />
                    <input type="checkbox" checked />
                    <input type="checkbox" checked />
                    <input type="checkbox" checked />
                    <select value="A">
                        <option value="A">A</option>
                        <option value="B">B</option>
                        <option value="C">C</option>
                    </select>
                </div>
            }
        }
        ReactDOM.render(
            <Rts/>,
            document.getElementById("root3")
        )
    </script>

总结

组件定义和事件处理

组件的分类

在React中,组件分为函数组件和class组件,也就是无状态组件和有状态组件。

  • 函数式组件(无状态组件) 直接定义函数的形式,不存在state,只会有props,它没有生命周期函数。
    // 函数式组件(无状态组件)
    function Hello() {
      return <h1>Hello,jianan</h1>
    }
    
  • class组件(有状态组件) 使用class定义、extends继承React.Component。有state进行数据的存储和管理,同时还可以拥有props,有生命周期函数。
    // class组件(有状态组件)
    class Hello extends React.Component {
      render() {
        return <h1>Hello jianan</h1>
      }
    }
    
无状态组件和有状态组件的使用规则

1、因为数据的更改都是根据状态进行更改的,如果只是单纯的处理一些逻辑,而不需要改变数据的值就使用无状态组件。我们可以使用props进行组件间的通信和传值。 2、如果需要改变某些数据的话,或是想要存储一些数据并且想要对这些数据进行一些增删改查的话,那么就应该使用有状态组件。我们使用的是state,数据会发生变化就会触发生命周期这些函数。

无状态组件和有状态组件传值的取用
  • 无状态组件 使用props传值时,使用props.属性名进行取用。
  • 有状态组件 使用props传值时,使用this.props.属性名进行取用。使用state定义状态时,使用this.state.属性名进行取用。

一般数据会通过父组件进行传递,这样就可以进行统一的数据管理,在父级进行一个集中的数据管理。以上是在没有使用redux的情况下,如果使用了redux的话,就会在redux中进行状态管理。 思考:更多时候,我们应该使用无状态组件还是有状态组件?

事件处理

事件处理函数的相关语法

React元素的事件处理和DOM元素很相似,但是语法上有些不同,React事件的命名采用小驼峰(camelCase),而不是纯小写。使用JSX语法时需要传入一个函数作为事件处理函数,而不是一个字符串。

<button onclick='fn()'>点击事件</button>
// React里
<button onClick={fn}>点击事件</button>

另外在React中阻止默认事件不能通过返回false的形式,而是要使用preventDefault

<a href="#" onclick="console.log('hello');return false">click</a>
handleClick(e) {
  e.preventDefault()
  console.log('hello')
}

<a href="#" onClick={handleClick}>click</a>
事件处理函数中的this

在JS中,class方法默认不会绑定this,如果我们忘记绑定this.handleClick并且把它传入了onClick,当我们调用这个函数的时候this的值为undefined。

class Hello extends React.Component {
  constructor() {
    super()
    // 如果不在constructor绑定this打印出来的值是undefined
    this.updateInfo = this.updateInfo.bind(this)
  }
  updateInfo() {
    console.log(this) 
  }
  updateState() {
    console.log(this)
  }
  updateAge() {
    console.log(this)
  }
  render() {
    return <div>
      <button onClick={this.updateInfo}>更新信息</button>
      {/* 像下面这样进行绑定也是可行的 */}
      <button onClick={this.updateState.bind(this)}>更新状态</button>
      <button onClick={() => this.updateAge()}>更新年龄</button>
    </div>
  }
}

或者使用下面这种用箭头函数赋值的方式来定义函数,这是在工作中最为常用的方法:

class Hello extends React.Component {
  updateInfo = () => {
    console.log(this)
  }
  render() {
    return <button onClick={this.updateInfo}>更新信息</button>
  }
}