React面向组件编程

这篇具有很好参考价值的文章主要介绍了React面向组件编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基本理解和使用

使用React开发者工具调试
React面向组件编程
效果
函数式组件:
React面向组件编程

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1. 创建函数式组件,组件首字母大写
        function MyComponent(){
            console.log(this)       //  此处的this时undefined,因为Babel编译后开启了严格模式
            return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
        }
        // 2.渲染组件到页面
        ReactDOM.render(<MyComponent/>, document.getElementById('test'))

        /**
         *  执行了ReactDOM.render(<MyComponent/>, document.getElementById('test')))之后发生了什么
         *      1.react会解析组件标签,找到了MyComponent组件
         *      2.发现组件是使用函数定义的,随后调用该函数,蒋返回的虚拟DOM转为真实DOM,随后呈现在页面中
         * **/
    </script>
</body>

</html>

类式组件:

React面向组件编程

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1. 创建类式组件,必须要继承React.Component
        class MyComponent extends React.Component{
            render(){
                // render方法放在了那里?- MyComponent类的原型对象上,供实例对象使用
                // render中的this实施诶---MyComponent组件实例对象
                console.log("render中的this:", this)
                return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
            }

        }

        // 2.渲染组件到页面
        ReactDOM.render(<MyComponent/>, document.getElementById('test'))

        /**
         *  执行了ReactDOM.render(<MyComponent/>, document.getElementById('test'))之后发生了什么
         *      1.react会解析组件标签,找到了MyComponent组件
         *      2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法
         *      3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中
         * **/

         /**
          * 组件的三大属性:
            props:{}
            refs:{}
            state:null
          * **/
    </script>
</body>

</html>

复杂组件的状态state如何理解:
组件中的状态驱动页面渲染
组件实例对象生成的state

注意
1.组件名必须首字母大写
2.虚拟DOM元素只能有一个根元素
3.虚拟DOM元素必须有结束标签

渲染类组件标签的基本流程
1.React内部会创建组件实例对象
2.调用render()得到虚拟DOM, 并解析为真实DOM
3.插入到指定的页面元素内部

组件三大核心属性1: state

效果

需求: 定义一个展示天气信息的组件
1.默认展示天气炎热 或 凉爽

2.点击文字切换天气

state.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // let that
        
        // 1.创建组件
        class Weather extends React.Component{
            // 参数取决于new的时候需要传递的内容
            // 构造器调用几次?----- 1次
            constructor(props){
                console.log('constructor')
                super(props)
                // 初始化状态
                this.state = {isHot:false, wind:'微风'}
                // that = this
                // 解决changeWeather中this指向问题,将原型上的changeWeather挂在到实例对象上
                this.changeWeather = this.changeWeather.bind(this)
            }
            
            // render调用几次-----1+n次,1是初始化次数,n是状态更新的次数
            render(){
                console.log('render')
                // 读取状态
                const {isHot, wind} = this.state
                // react中onClick要大写,函数后面不需要加括号,只用指定函数,由react调用
                return <h1 onClick = {this.changeWeather}> 今天天气很{isHot ? '炎热':'凉爽'} , {wind}</h1>
            }
            
            // changeWeaher调用几次?点几次调几次
            changeWeather(){
                // changeWeather放在那里-----类的原型对象上,供实例使用
                // 通过Weather实例对象调用changeWeather时,changeWeather中的this就是Weather实例
                // 为什么这里this.state是undefined,因为他不是通过实例调用
                // 由于changeWeather是作为onClick回调,所以不是通过实例嗲偶用的,是直接调用
                // 类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
                // console.log(this.state.isHot)

                // 获取原来的isHot值
                const isHot = this.state.isHot
                // 严重注意:状态state不能直接更改,下面这行就是直接更改,要借助一个内置API
                // this.state.isHot = !isHot   // 这是错误写法
                // 严重注意,状态必须通过setState更改,且更新是一种合并的操作
                this.setState({isHot:!isHot})
            }
        }

        // 2.渲染组件到页面
        ReactDOM.render(<Weather/>, document.getElementById('test'))

        // const title = document.getElementById('title')
        // title.addEventListener('click', ()=>{
        //     console.log("标题被点击了")
        // })

        // const title = document.getElementById('title')
        // title.onclick = ()=>{
        //     console.log("标题被点击了")
        // }
        // function changeWeather(){
        //     alert('此处修改isHot的值')
        //     // 这里的this是window
        //     // const {isHot} = this.state
        //     // console.log(isHot)
        //     console.log(that.state.isHot)
        // }
    </script>
</body>

</html>

间写

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">

        class Weather extends React.Component{
        
            // 初始化状态
            state = {isHot:false, wind:'微风'}
            
            render(){
                const {isHot, wind} = this.state
                return <h1 onClick = {this.changeWeather}> 今天天气很{isHot ? '炎热':'凉爽'} , {wind}</h1>
            }
            
            // 自定义方法-----要用赋值语句的形式+箭头函数
            // 将function改成了箭头函数,可以实现,箭头函数没有自己的this,
            // 在里面写this不会报错,它会找外层函数的this,作为箭头函数的this去使用
            changeWeather = ()=>{
                const isHot = this.state.isHot
                this.setState({isHot:!isHot})
            }
        }

        // 2.渲染组件到页面
        ReactDOM.render(<Weather/>, document.getElementById('test'))

    </script>
</body>

</html>

理解

1.state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
2.组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

强烈注意

1.组件中render方法中的this为组件实例对象
2.组件自定义的方法中this为undefined,如何解决?
a)强制绑定this: 通过函数对象的bind()
b)箭头函数
3.状态数据,不能直接修改或更新

组件三大核心属性2: props

效果

需求: 自定义用来显示一个人员信息的组件

1.姓名必须指定,且为字符串类型;
2.性别为字符串类型,如果性别没有指定,默认为男
3.年龄为字符串类型,且为数字类型,默认值为18

React面向组件编程

理解

1.每个组件对象都会有props(properties的简写)属性
2.组件标签的所有属性都保存在props中

作用

1.通过标签属性从组件外向组件内传递变化的数据
2.注意: 组件内部不要修改props数据

编码操作

1.内部读取某个属性值

this.props.name

2.对props中的属性值进行类型限制和必要性限制
第一种方式(React v15.5 开始已弃用):

Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number
}

第二种方式(新):使用prop-types库进限制(需要引入prop-types库)

Person.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number. 
}

3.扩展属性: 将对象的所有属性通过props传递

<Person {...person}/>

4.默认属性值:

Person.defaultProps = {
  age: 18,
  sex:'男'
}

5.组件类的构造函数

constructor(props){
  super(props)
  console.log(props)//打印所有属性
}

props基本使用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test1">
    </div>
    <div id="test2">
    </div>
    <div id="test3">
    </div>

    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1.创建组件
        class Person extends React.Component{
            render(){
                console.log(this.props)
                const {name, sex, age} = this.props
                return (
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age+1}</li>
                    </ul>
                )
            }
        }
        // 类似html标签key-value的形式,,注意要传递number类型的参数,不能直接使用引号,需要用大括号括起来
        // 对传递的标签属性age进行类型鉴定,name进行必要性鉴定,性别需要指定默认值
        ReactDOM.render(<Person name="tom" age={19} sex='女'/>, document.getElementById('test1'))
        ReactDOM.render(<Person name="java" age={20} sex='男'/>, document.getElementById('test2'))
        // 要保证两者属性名全部相同
        //仅适用于标签属性的传递
        const p = {name:'老刘', age:18, sex:'女'}
        ReactDOM.render(<Person {...p}/>, document.getElementById('test3'))

        // 传递props,就是传递标签属性
        

    </script>
</body>

</html>

props进行限制

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test1">
    </div>
    <div id="test2">
    </div>
    <div id="test3">
    </div>

    <!--react的核心库,React对象-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM, ReactDom对象-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!---引入prop-types,用于对组件标签属性进行限制,PropType对象-->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1.创建组件
        class Person extends React.Component{
            render(){
                console.log(this.props)
                const {name, sex, age} = this.props
                // props是只读的
                //this.props.name='java'      // 此行代码会报错,因为props是只读的
                return (
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age+1}</li>
                    </ul>
                )
            }
            
        }
        //对标签属性进行类型、必要性的限制
        Person.propTypes = {
            name:PropTypes.string.isRequired,           //限制name必传,且为字符串
            sex:PropTypes.string,       //限制sex字符串
            age:PropTypes.number,       //限制age为数值
            speak:PropTypes.func        //限制speak为函数
        }
        // 指定默认标签属性值
        Person.defaultProps = {
            sex:'男' ,     // sex默认值为男
            age:18         //age默认值为18
        }
        ReactDOM.render(<Person name="tom" age={19} sex='女'/>, document.getElementById('test1'))
        ReactDOM.render(<Person name="java" speak={speak}/>, document.getElementById('test2'))
        const p = {name:'老刘', age:18, sex:'女'}
        ReactDOM.render(<Person {...p}/>, document.getElementById('test3'))

        function speak(){
            console.log('我说话了')
        }
    </script>
</body>

</html>

props简写方式

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test1">
    </div>
    <div id="test2">
    </div>
    <div id="test3">
    </div>

    <!--react的核心库,React对象-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM, ReactDom对象-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!---引入prop-types,用于对组件标签属性进行限制,PropType对象-->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1.创建组件
        class Person extends React.Component {
            //对标签属性进行类型、必要性的限制
            static propTypes = {
                name: PropTypes.string.isRequired,           //限制name必传,且为字符串
                sex: PropTypes.string,       //限制sex字符串
                age: PropTypes.number,       //限制age为数值
                speak: PropTypes.func        //限制speak为函数
            }
            // 指定默认标签属性值
            static defaultProps = {
                sex: '男',     // sex默认值为男
                age: 18         //age默认值为18
            }
            render() {
                console.log(this.props)
                const { name, sex, age } = this.props
                // props是只读的
                //this.props.name = 'java'      // 此行代码会报错,因为props是只读的
                return (
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age + 1}</li>
                    </ul>
                )
            }

        }



        ReactDOM.render(<Person name="tom" age={19} sex='女' />, document.getElementById('test1'))
        ReactDOM.render(<Person name="java" speak={speak} />, document.getElementById('test2'))
        const p = { name: '老刘', age: 18, sex: '女' }
        ReactDOM.render(<Person {...p} />, document.getElementById('test3'))

        function speak() {
            console.log('我说话了')
        }
    </script>
</body>

</html>

props与构造器

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test1">
    </div>
    <div id="test2">
    </div>
    <div id="test3">
    </div>

    <!--react的核心库,React对象-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM, ReactDom对象-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!---引入prop-types,用于对组件标签属性进行限制,PropType对象-->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1.创建组件
        class Person extends React.Component {
            // 类中的构造器有什么作用呢?有必要传props吗?
            // 在react中,构造函数仅用于以下两种情况
            // 1.通过给this.state赋值对象来初始化内部state,2.为事件处理函数绑定实例
            // 类中的构造器可有可无
            // 在react组件挂在致癌案,会调用它的构造函数,在为react.component子类实现构造函数时,应在
            // 其他语句之前调用super(props),否则this.props在构造函数中可能会出现为定义异常
            constructor(props) {
                // 构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
                console.log(props)
                super(props)
            }

            //对标签属性进行类型、必要性的限制
            static propTypes = {
                name: PropTypes.string.isRequired,           //限制name必传,且为字符串
                sex: PropTypes.string,       //限制sex字符串
                age: PropTypes.number,       //限制age为数值
                speak: PropTypes.func        //限制speak为函数
            }
            // 指定默认标签属性值
            static defaultProps = {
                sex: '男',     // sex默认值为男
                age: 18         //age默认值为18
            }
            render() {
                return (
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age + 1}</li>
                    </ul>
                )
            }

        }



        ReactDOM.render(<Person name="tom"/>, document.getElementById('test1'))
    </script>
</body>

</html>

函数式组件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test1">
    </div>
    <div id="test2">
    </div>
    <div id="test3">
    </div>

    <!--react的核心库,React对象-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM, ReactDom对象-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!---引入prop-types,用于对组件标签属性进行限制,PropType对象-->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1.函数式组件只能使用props
        function Person(props) {
            const { name, age, sex } = props
            return (
                <ul>
                    <li>姓名:{name}</li>
                    <li>性别:{sex}</li>
                    <li>年龄:{age + 1}</li>
                </ul>
            )
        }
        //对标签属性进行类型、必要性的限制
        Person.propTypes = {
            name: PropTypes.string.isRequired,           //限制name必传,且为字符串
            sex: PropTypes.string,       //限制sex字符串
            age: PropTypes.number,       //限制age为数值
            speak: PropTypes.func        //限制speak为函数
        }
        // 指定默认标签属性值
        Person.defaultProps = {
            sex: '男',     // sex默认值为男
            age: 18         //age默认值为18
        }

        ReactDOM.render(<Person name="tom" />, document.getElementById('test1'))
    </script>
</body>

</html>

组件三大核心属性3: refs与事件处理

效果

需求: 自定义组件, 功能说明如下:

点击按钮, 提示第一个输入框中的值
当第2个输入框失去焦点时, 提示这个输入框中的值

React面向组件编程

理解

组件内的标签可以定义ref属性来标识自己(类似id)

编码

1.字符串形式的ref

<input ref="input1"/>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1. 创建类式组件,必须要继承React.Component
        class Demo extends React.Component{
            // 展示左侧输入框的数据
            showData = ()=>{
                // 注意收集出来的属性是refs
                const {input1} = this.refs
                console(input1)
                alert(input1.value)
                
            }
            // 展示右侧输入框的数据
            showData2 = ()=>{
                const {input2} = this.refs
                alert(input2.value)
                
            }
            render(){
                return (
                    // 打了标识之后,都收集到组件对象的refs属性中
                    <div>
                        <input ref = "input1" type="text" placeholder="点击按钮提示数据"/>
                        <button ref = "button1" onClick={this.showData}>点我提示左侧的数据</button>
                        <input onBlur = {this.showData2} ref = "input2" type="text" placeholder="失去焦点提示数据"/>  
                    </div>

                )
            }

        }

        // 2.渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'))

    </script>
</body>

</html>

2.回调形式的ref

<input ref={(c)=>{this.input1 = c}}/>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1. 创建类式组件,必须要继承React.Component
        class Demo extends React.Component{
            // 展示左侧输入框的数据
            showData = ()=>{
                const{input1} = this
                alert(input1.value)
            }
            // 展示右侧输入框的数据
            showData2 = ()=>{
                const {input2} = this
                alert(input2.value)
                
            }
            render(){
                return (
                    // 打了标识之后,都收集到组件对象的refs属性中
                    /**
                     * <input ref = {(a)=>{this.input1 = a}} type="text" placeholder="点击按钮提示数据"/>
                     * 这句的含义是把ref当前所处的节点挂在了当前实例自身上,并且取了个名字叫input1
                     * react会自动帮你调用回调函数
                     * **/
                    <div>
                        
                        <input ref = {c => this.input1 = c } type="text" placeholder="点击按钮提示数据"/>
                        <button ref = "" onClick={this.showData}>点我提示左侧的数据</button>
                        <input onBlur = {this.showData2} ref = {c => this.input2 = c } type="text" placeholder="失去焦点提示数据"/>
                    </div>

                )
            }

        }

        // 2.渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'))

    </script>
</body>

</html>

回调中的函数执行次数

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1. 创建类式组件,必须要继承React.Component
        class Demo extends React.Component{
            state = {isHot:true}
            showInfo = ()=>{
                const {input1} = this
                alert(input1.value)
            }
            changeWeather = ()=>{
                const {isHot} = this.state
                // 获取原来的天气
                this.setState({isHot:!isHot})
            }
            saveInput = (c)=>{
                this.input1 = c;
                console.log('@',c)

            }
            render(){
                const {isHot} = this.state
                return (
                    /**
                     * 如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。
                     * 这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。
                     * 通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
                     * **/
                    <div>
                        <h2>今天天气很{isHot ? '炎热':'寒冷'} </h2>
                        {/*<input ref = {(c) => {this.input1 = c;console.log('@', c);}} type="text" />*/}
                        <input ref = {this.saveInput} type="text" />
                        <button onClick={this.showInfo}>点我提示左侧的数据</button>
                        <button onClick={this.changeWeather}>点我切换天气</button>
                    </div>

                )
            }

        }

        // 2.渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'))

    </script>
</body>

</html>

3.createRef创建ref容器·

myRef = React.createRef() 
<input ref={this.myRef}/>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 1. 创建类式组件,必须要继承React.Component
        class Demo extends React.Component{
            /**
             * 它本身是一个函数,React.createRef()调用后可以返回一个容器,调用后可以存储被ref所标识的节点,
             * 改容器是专人专用的
             * **/
            myRef = React.createRef()
            myRef2 = React.createRef()
            // 展示左侧输入框的数据
            showData = ()=>{
                alert(this.myRef.current.value)
            }
            // 展示右侧输入框的数据
            showData2 = ()=>{
                alert(this.myRef2.current.value)
                
            }
            render(){
                return (
                    <div>
                        
                        <input ref = {this.myRef} type="text" placeholder="点击按钮提示数据"/>
                        <button ref = "" onClick={this.showData}>点我提示左侧的数据</button>
                        <input onBlur={this.showData2} ref = {this.myRef2} type="text" placeholder="失去焦点提示数据"/>
                    </div>

                )
            }

        }

        // 2.渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'))

    </script>
</body>

</html>

2.4.4. 事件处理

1.通过onXxx属性指定事件处理函数(注意大小写)

  • 1)React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
  • 2)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)

2.通过event.target得到发生事件的DOM元素对象

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">

        // 1. 创建类式组件
        class Demo extends React.Component {
            /**
             *  1.通过onXxx属性指定事件处理函数(注意大小写,react是大写,原生是小写),
                    1)React使用的是自定义(合成)事件, 而不是使用的原生DOM事件        为了更好的兼容性
                    2)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)   为了更高效
                2.通过event.target得到发生事件的DOM元素对象     ----不要过度使用ref
             * **/
            // 创建ref容器
            myRef = React.createRef()
            myRef2 = React.createRef()
            // 展示左侧输入框的数据
            showData = () => {
                alert(this.myRef.current.value)
            }
            // 展示右侧输入框的数据
            showData2 = () => {
                alert(event.target.value)

            }
            render() {
                return (
                    <div>

                        <input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
                        <button ref="" onClick={this.showData}>点我提示左侧的数据</button>
                        {/**发生事件的元素是正要操作的元素,ref可以省略**/}
                        <input onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
                    </div>

                )
            }

        }

        // 2.渲染组件到页面
        ReactDOM.render(<Demo />, document.getElementById('test'))
    </script>
</body>

</html>

收集表单数据

效果

需求: 定义一个包含表单的组件 输入用户名密码后, 点击登录提示输入信息
React面向组件编程

理解

包含表单的组件分类

1.受控组件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 随着输入维护状态,就称之为非受控组件
        // 创建组件
        class Login extends React.Component{
            
            state = {
                username:'',        //用户名
                password:''         //密码
            }
            handleSubmit = (event)=>{
                event.preventDefault()  //  阻止表单提交,不会跳转到新的页面
                const {username, password} = this.state
                alert(`输入的用户名是:${username}, 你输入的密码是:${password}`)
            }

            // 保存用户名到状态中
            saveUsername = (event)=>{
                this.setState({username: event.target.value})
            }

            // 保存用户名到密码中
            savePassword = (event)=>{
                this.setState({password: event.target.value})
            }

            render() {
                return (
                    // 不指定的话,默认发get请求,带的参数默认是get参数
                    <form action="http://www.baidu.com" onSubmit={this.handleSubmit}>
                        用户名:<input onChange={this.saveUsername} type = "text" name ="username"/>
                        密码:<input onChange={this.savePassword} type = "password" name="password"/>
                        <button>登陆</button>
                    </form>
                )
            }
        }
        ReactDOM.render(<Login/>, document.getElementById('test'))
    </script>
</body>

</html>

2.非受控组件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <!-- babel将jsx代码翻译为js代码 -->
    <script type="text/babel">
        // 创建组件
        class Login extends React.Component{
            // 页面所有输入类的dom,都是现用现取,就是非受控组件
            // 
            handleSubmit = (event)=>{
                event.preventDefault()  //  阻止表单提交,不会跳转到新的页面
                const {username, password} = this
                alert(`输入的用户名是:${username.value}, 你输入的密码是:${password.value}`)
            }
            render() {
                return (
                    // 不指定的话,默认发get请求,带的参数默认是get参数
                    <form action="http://www.baidu.com" onSubmit={this.handleSubmit}>
                        用户名:<input ref={c=>this.username=c} type = "text" name ="username"/>
                        密码:<input ref={c=>this.password=c} type = "password" name="password"/>
                        <button>登陆</button>
                    </form>
                )
            }
        }
        ReactDOM.render(<Login/>, document.getElementById('test'))
    </script>
</body>

</html>

组件的生命周期(重要)

效果

需求:定义组件实现以下功能:

让指定的文本做显示 / 隐藏的渐变动画
从完全可见,到彻底消失,耗时2S
点击“不活了”按钮从界面中卸载组件

React面向组件编程

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">
        // 创建组件
        // 生命周期回调函数<===>生命周期钩子函数
        // react会在合适的时机把函数勾起来执行。

        class Life extends React.Component {
            // 状态的数据驱动页面的更新
            state = { opacity: 1 }
            death = () => {
                // 卸载组件unmount
                ReactDOM.unmountComponentAtNode(document.getElementById('test'))

            }
            // action =()=>{
            //     setInterval(()=>{
            //         // 获取原来状态
            //         let {opacity} = this.state
            //         // 减小0.1
            //         opacity -= 1
            //         if (opacity <= 0) opacity = 1
            //         // 设置新的透明度
            //         this.setState({opacity})
            //     }, 200);
            // }
            // 名字一定不要写错
            // 组件挂载完毕之后调用
            componentDidMount() {
                
                this.timer = setInterval(() => {
                    // 获取原来状态
                    let { opacity } = this.state
                    // 减小0.1
                    opacity -= 0.1
                    if (opacity <= 0) opacity = 1
                    // 设置新的透明度
                    this.setState({opacity})
                }, 200);
            }
            
            //组件将要卸载
            componentWillUnmount(){
                // 清空定时器
                clearInterval(this.timer)
            }

            // render调用1+n次,调用的时机:初始化渲染,状态更新之后
            render() {
                // 无线递归,定时器每隔200s都会更新状态,更新状态就会导致组件重新挂在,render再次执行,定时器又重新初始化了
                // 
                console.log('render')
                // setInterval(()=>{
                //     // 获取原来状态
                //     let {opacity} = this.state
                //     // 减小0.1
                //     opacity -= 1
                //     if (opacity <= 0) opacity = 1
                //     // 设置新的透明度
                //     this.setState({opacity})
                // }, 200);
                return (
                    <div>
                        <h2 style={{ opacity: this.state.opacity }}>React学不会怎么办</h2>
                        <button onClick={this.death}>不活了</button>
                        <button onClick={this.action}>开始变化</button>
                    </div>
                )
            }
        }
        // 渲染组件,实际上就是挂载(mount),
        ReactDOM.render(<Life />, document.getElementById('test'))
    </script>
</body>

</html>

理解

1.组件从创建到死亡它会经历一些特定的阶段。
2.React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
3.我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。

生命周期流程图(旧)

React面向组件编程

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用jsx创建虚拟DOM</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test">

    </div>


    <!--react的核心库-->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!--react的扩展库,专门用于操作DOM-->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!--引入babel,用于解析jsx语法为原生js语法-->
    <script type="text/javascript" src="../js/babel.min.js"></script>


    <script type="text/babel">
        /**
         *  componentDidMount().  =====》常用
                一般在这个钩子中做一些初始化的事,例如:开启定时器,发送网络请求,订阅消息
            componentWillUnmount() ====》常用
                一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

         * 
         * **/

        class Count extends React.Component {
            // 构造器
            constructor(props) {
                console.log('Count-constructor')
                super(props)
                // 初始化状态
                this.state = { count: 0 }
            }

            //加1按钮的回调
            add = () => {
                // 获取原来的状态
                const { count } = this.state
                this.setState({ count: count + 1 })
            }

            // 卸载组件的回调
            death = () => {
                // 卸载组件unmount
                ReactDOM.unmountComponentAtNode(document.getElementById('test'))
            }

            // 强制更新按钮的回调
            force = () => {
                this.forceUpdate()
            }
            // 组件将要挂在的钩子
            componentWillMount() {
                console.log('Count-componentWillMount')
            }

            // 组件挂载完毕的钩子
            componentDidMount() {
                console.log('Count-componentDidMount')
            }

            // 组件将要卸载的钩子
            componentWillUnmount() {
                console.log('Count-componentWillUnmount')
            }

            // 控制组件更新的阀门
            shouldComponentUpdate() {
                console.log('Count-shouldComponentUpdate')
                // 不写返回值,默认为true
                // 如果是true,每次更新state的时候,都会调用一次render,如果是false,包含render在内的3个函数都不会调用
                return true
            }

            // 组件将要更新的钩子
            componentWillUpdate() {
                console.log('Count-componentWillUpdate')
            }

            // 组件更新完毕的钩子
            componentDidUpdate() {
                console.log('Count-componentDidUpdate')
            }


            render() {
                console.log('render')
                const { count } = this.state
                return (
                    <div>
                        <h2>当前求和为{count}</h2>
                        <button onClick={this.add}>点我+1</button>
                        <button onClick={this.death}>点我卸载</button>
                        <button onClick={this.force}>不修改任何状态中的数据,强制更新一下</button>
                    </div>
                )
            }
        }

        // 父组件A
        class A extends React.Component {
            // 初始化状态
            state = { carName: '奔驰' }
            changeCar = () => {
                this.setState({ carName: '宝马' })
            }
            render() {
                return (
                    <div>
                        <div>我是A组件</div>
                        <button onClick={this.changeCar}>换车</button>
                        <B carName={this.state.carName} />
                    </div>
                )
            }
        }

        // 子组件B
        class B extends React.Component {
            componentDidMount() {
                console.log("B---componentDidMount")
            }
            // 组件将要接收props调用,(第一次不调用,之后调用)
            componentWillReceiveProps() {
                console.log("B---componentWillReceiveProps", this.props)
            }

            // 控制组件更新的阀门
            shouldComponentUpdate() {
                console.log('B-shouldComponentUpdate')
                
                return true
            }

            // 组件将要更新的钩子
            componentWillUpdate() {
                console.log('B-componentWillUpdate')
            }

            // 组件更新完毕的钩子
            componentDidUpdate() {
                console.log('B-componentDidUpdate')
            }

            render() {
                console.log('B-render')
                return (
                    <div>我是B组件,接收到的车是:{this.props.carName}</div>
                )
            }
        }
        // 渲染组件,实际上就是挂载(mount),
        ReactDOM.render(<Count />, document.getElementById('test'))

    </script>
</body>

</html>

生命周期的三个阶段(旧)

初始化阶段: 由ReactDOM.render()触发—初次渲染

1.constructor()
2.componentWillMount()
3.render()
4.componentDidMount().  =====》常用
一般在这个钩子中做一些初始化的事,例如:开启定时器,发送网络请求,订阅消息

更新阶段: 由组件内部this.setSate()或父组件重新render触发

1.shouldComponentUpdate()
2.componentWillUpdate()
3.render()
4.componentDidUpdate()

卸载组件: 由ReactDOM.unmountComponentAtNode()触发

1.componentWillUnmount() ====》常用
一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

生命周期流程图(新)

React面向组件编程
新版本和旧版本相比,废弃了componentWillMount、componentWillReceiveProps、componentWillUpdate,提出了两个新的getDerivedStateFromProps、getSnapshotBeforeUpdate方法

初始化阶段: 由ReactDOM.render()触发—初次渲染

1.constructor()
2.getDerivedStateFromProps
3.render()
4.componentDidMount()

更新阶段: 由组件内部this.setSate()或父组件重新render触发

1.getDerivedStateFromProps
2.shouldComponentUpdate()
3.render()
4.getSnapshotBeforeUpdate
5.componentDidUpdate()

卸载组件: 由ReactDOM.unmountComponentAtNode()触发

1.componentWillUnmount()

重要的勾子

1.render:初始化渲染或更新渲染调用
2.componentDidMount:开启监听, 发送ajax请求
3.componentWillUnmount:做一些收尾工作, 如: 清理定时器

即将废弃的勾子

1.componentWillMount
2.componentWillReceiveProps
3.componentWillUpdate

现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。文章来源地址https://www.toymoban.com/news/detail-426981.html

到了这里,关于React面向组件编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用

    【JavaEE】 AOP(1) 1.1 AOP 与 Spring AOP AOP ( A spect O riented P rogramming),是一种思想,即 面向切面编程 Spring AOP 则是一个框架,Spring项目中需要引入依赖而使用 AOP和Spring AOP的关系就相当于IoC和DI Spring AOP让开发者能够半自动的开发AOP思想下实现的功能 1.2 没有AOP的世界是怎样的

    2024年02月11日
    浏览(47)
  • React中的性能测试工具组件Profiler的基本使用

    React中的性能测试工具组件Profiler是一个非常有用的工具,它可以帮助我们分析React应用程序的性能瓶颈。在本文中,我们将学习如何使用Profiler组件来测试React应用程序的性能。 首先,让我们来了解一下Profiler组件的基本用法。在React中,我们可以通过在组件树上添加Profiler组

    2024年02月11日
    浏览(44)
  • Redux - Redux在React函数式组件中的基本使用

    Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。 它主要的几个方法如下: 重要的有方法 有 dispatch(分发action) 、 getState(获取state) 、 subscribe(监听state的变化) ,下面会介绍到,另外两个可以不用管; 那什么时候使用Redux呢? 当遇到如下问题时,建议开始使

    2024年02月13日
    浏览(47)
  • 面向对象编程 实验三 sduwh 子窗口与控件的基本用法、资源的使用 参考实验报告1

    源自网络收集,仅供参考 实验三收集到两份完整报告,这是其一,另一份见本专栏下一篇文章。 《面向对象程序设计》 实验三 实验题目:子窗口与控件的基本用法、资源的使用 整体目的:理解、窗口之间的消息传送、调用栈;掌握光标、图标、菜单的制作和使用方式;掌

    2024年02月07日
    浏览(40)
  • 再谈编程范式(3):理解面向过程/面向对象/函数式编程的精髓

    面向过程是随着VB一起来到我的世界,那个时候会的非常有限,感觉能把程序写出来自己就非常棒了,VB是做那种可视化界面,在工具栏拖个框框放到面板上,然后就在各个事件上写完整的逻辑,什么封装,抽象,继承一概不懂,就有一种一个方法把实现过程需要的逻辑都罗列

    2024年01月20日
    浏览(42)
  • C++设计模式_21_Iterator 迭代器(理解;面向对象的迭代器已过时;C++中使用泛型编程的方式实现)

    Iterator 迭代器也是属于“数据结构”模式。 GoF中面向对象的迭代器已经过时,C++中目前使用泛型编程的方式实现,其他语言还在使用面向对象的迭代器。 在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以

    2024年02月07日
    浏览(57)
  • 深入理解一下Python中的面向对象编程

    网上关于 Java 和**C++**的面向对象编程相关介绍的博客文章已经很多了,那我为什么还写呢?因为,人生苦短,刚好我是学Python的... 今天,我们就来走进 面向对象编程的理想国 ——深入理解一下Python中的面向对象编程( Object-Oriented Programming,OOP )。 “日子一天一天过 我们

    2024年02月07日
    浏览(65)
  • 面向对象编程:深入理解抽象类和关键字

    在Java编程中,我们经常会遇到一些特殊的和概念,其中包括static、final以及抽象类等。本文将深入探讨这些和概念的作用和使用方法,并通过一个实例展示抽象类的应用。 1. 1.1 static static修饰成员变量:表示该成员变量属于类,不属于对象,所有对象共享

    2024年02月15日
    浏览(53)
  • 说说对React中类组件和函数组件的理解?有什么区别?

    通过ES6类的编写形式去编写组件,该类必须继承React.Component,通过this.props的方式去访问父组件传递过来的参数,且在类组件中必须使用render方法,在return中返回React对象,如下: 通过函数编写的形式去实现一个React组件,是React中定义组件最简单的方式,如下: 1.编写形式不

    2024年01月22日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包