• 03 React 面向组件编程



    可以在谷歌应用商店下载 React Developer Tools,可以更好用

    React 中定义函数式组件

    <script type="text/babel">
        //1.编写函数式组件
        function Demo() {//组件名需要大写,不然 react 会认为标签里面是 html 标签,而不是 react 组件
            console.log(this);  //此处的 this 是 undefined,因为babel 会在严格模式下翻译代码,严格模式下,函数里的 this 为 undefined
            return (
                <h1>函数式组件</h1>
            )
        }
        //2.渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'));
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    执行ReactDOM.render()之后,发生了什么?

    1. React 解析组件标签,找到了 Demo 组件
    2. 发现 Demo 组件是用函数定义的,随后调用该函数,将返回的虚拟 DOM 转为真实 DOM,然后呈现到页面中。

    React 中定义类组件

    类的基本知识

    <script type="text/javascript">
    
        /*
        1.类中的构造器不是必须要写的,要对实例进行属性初始化的时候就要写
        2.如果 A 类继承了 B 类,且 A 类写了构造器,那么构造器需要在首行调用super()
        3.类中所定义的方法,都是放在了类的原型对象上,供实例去使用。
         */
    
        //创建一个类
        class Person {
            //构造器方法
            constructor(name, age) {
            //构造器中的 this 是谁?类的示例对象
            this.name = name
            this.age = age
         }
         //一般方法
         speak() {
             //speak方法放在了哪里?类的原型对象上,供实例使用
             //通过 person 实例调用 speak 方法,speak 方法中的 this 指向了 person 实例
             console.log(`我叫${this.name},今年${this.age}岁了。`)
            }
         }
    
         const p1 = new Person('Tom', 18)
         const p2 = new Person('Jerry', 19)
    
         p1.speak()
         p2.speak()
    
         class Student extends Person {
            constructor(name, age, grade) {
                super();  //必须要调用,否则会报错。调用的好处时,父类拥有的属性赋值就不用写了
                // this.name = name; 
                // this.age = age;
                this.grade = grade;
            }
            //重写父类方法
            speak() {
                console.log(`我叫${this.name},今年${this.age}岁了,在读${this.grade}`)
            }
        }
    
        const s1 = new Student('xiaozhang', 12, '高一');
        const s2 = new Student('xiaomei', 13, '高二');
    
        s1.speak()
        s2.speak()
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    创建类式组件

    DOCTYPE html>
    <html>
    <head>
        <title>React创建类组件title>
    head>
    <body>
        <div id="test">div>
        <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin>script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin>script>
        
        <script src="https://unpkg.com/@babel/standalone/babel.min.js" crossorigin>script>
        <script type="text/babel">
            //1.创建类式组件
            class MyComponent extends React.Component{
                render() {
                    return <h1>React创建类式组件</h1>
                }
            }
            ReactDOM.render(<MyComponent/>, document.getElementById('test'))
        script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    组件的 render 是放在哪里的?

    • 组件的 render 放在类的原型对象上,供实例对象使用。

    那组件的实例呢?

    执行了 ReactDOM.render()之后,发生了什么?

    1. ReactDOM 解析组件标签,找到了 MyComponent 组件
    2. 发现组件是使用类定义的,随后 new 出来该类的实例,并通过该实例调用原型上的 render 方法
    3. 将 render 返回的虚拟 DOM 转为真实 DOM,随后呈现在页面上。

    组件实例的三大属性之state

    以下代码借助 state 状态,在按钮每次点击之后,都会改变h1标签的内容

    <script type="text/babel">
        class MyComponent extends React.Component{
        	//组件被调用几次,构造器就调用几次
            constructor(props) {
                super(props);
                this.state={isHot:false};
                this.handleClick = this.handleClick.bind(this);
            }
    
            handleClick() {
            	//setState 的操作是一种合并操作,而不是更新。但是 hooks 的操作好像是合并的
                this.setState({isHot:!this.state.isHot});
            }
    		//render被调用了 1+n 次,1 是初始化那次,n 是状态更新的次数
            render () {
                return <h1 onClick={this.handleClick}>今天的天气很{this.state.isHot?"炎热":"寒冷"}</h1>
            }
        }
    
        ReactDOM.render(<MyComponent/>, document.getElementById('test'));
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    类中的方法默认开启了严格模式,this 是 undefined
    this.handleClick = this.handleClick.bind(this)这行代码是必要的,因为它确保了在组件的方法中使用this关键字时,this关键字指向组件实例。
    在 Javascript 中,函数的this关键字指向的是当前执行上下文的对象。在 React 组件中,我们经常需要在组件的方法中使用this关键字来访问组件的状态或者其他属性和方法。但是,在不进行绑定的情况下,这些方法中的this关键字指向的是调用该方法的对象,这可能导致代码中的错误或者不可预料的行为。

    javascript 中事件绑定的三种方式:

    DOCTYPE html>
    <html>
        <head>
            <meta chatset="utf-8">
            <title>Documenttitle>
        head>
        <body>
            <button id="btn1">按钮1button>
            <button id="btn2">按钮2button>
            <button onclick="demo()">按钮3button>
    
            <script type="text/javascript">
                const btn1 = document.getElementById("btn1");
                btn1.addEventListener("click", ()=>{
                    alert("按钮1被点击了");
                });
    
                const btn2 = document.getElementById("btn2");
                btn2.onclick = () => {
                    alert("按钮2被点击了");
                }
    
                function demo() {
                    alert("按钮3被点击了");
                }
            script>
        body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    ​state 的简写方式

    class MyComponent extends React.Component{
        //初始化状态
        //这样相当于给类增加了一个属性
        state = {isHot:true};
    
        //如果这里写成函数表达式,那么 this 将找不到而导致出错
        handleClick = () => {
            this.setState({isHot:!this.state.isHot});
        }
    
        render () {
            return <h1 onClick={this.handleClick}>今天的天气很{this.state.isHot?"炎热":"寒冷"}</h1>
        }
    }
    
    ReactDOM.render(<MyComponent/>, document.getElementById('test'));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    强烈注意:

    • onClick 传递过去的是一个方法,千万不要在函数名前加括号而变成了函数返回值
    • 组件中 render 方法中的 this 为组件实例对象
    • 组件自定义的方法中 this 为 undefined,如何解决?
      - 强制绑定 this,通过函数对象的 bind()
      - 箭头函数
    • 状态数据,不能直接修改或更新 setState

    组件的三大属性之props

    <script type="text/babel">
        class Person extends React.Component {
            render() {
                return (
                    <ul>
                        <li>姓名:{this.props.name}</li>
                        <li>性别:{this.props.gender}</li>
                        <li>年龄:{this.props.age}</li>
                    </ul>
                )
            }
        }
    
        //在组件标签中传值,相当于就是往组件的 props 中传值了
        ReactDOM.render(<Person name="Tom" gender="男" age="18"/>, document.getElementB-yId('test'));
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在组件标签中传值,相当于就是往组件的 props 中传值了

    用这样的写法,可以将一个对象的键值对都放在组件的 props 中:
    (展开运算符本来不能展开对象的,但是加了花括号后可以用来对象克隆)
    (但是在这里,花括号的含义是里面要写 javascript 代码了,只是说 babel+react 语法允许我们使用展开运算符来展开对象,在正常的 javascript 代码中,展开运算符是不能展开对象的,只能与花括号配合来克隆对象)

    const p = {name:"小陈", age:18, gender:"男"}
    ReactDOM.render(<Person {...p}/>, document.getElementById('test'));
    
    • 1
    • 2

    注意,虽然react+babel可以使用展开运算符展开对象,但是也不能随意使用,比如下面这样就不太行。

    const p = {name:"小陈", age:18, gender:"男"}
    console.log(...p);   //这样不行
    
    • 1
    • 2

    复制对象时,修改对象属性的时候也可以用

    const p = {name:"小陈", age:18, gender:"男"}
    const p1 = {...p, name:'小张'}
    
    • 1
    • 2
  • 相关阅读:
    2022华为杯研究生数学建模赛题思路分析
    K8S(一)
    CodeArts Check代码检查服务用户声音反馈集锦(3)
    WMS系统是什么——史上最全WMS介绍
    C++右值引用是一个左值引发的思考
    Vue3+elementplus搭建通用管理系统实例九:通用表格实现下
    智能控制理论及应用 王耀南等编著
    Tensorflow基础 Tensorflow基本操作(三)
    MST56XXB 60V,150mA,2.1uA,高PSRR,高压低压差线性稳压器
    私有继承和虚函数私有化能用么?
  • 原文地址:https://blog.csdn.net/qq_37054755/article/details/130048569