• React框架的基本运行原理与组件定义方式


    React框架的基本运行原理
    React的本质是内部维护了一套虚拟DOM树,这个虚拟DOM树就是一棵js对象树,它和真实DOM树是一致的,一一对应的。
    当某一个组件的state发生修改时,就会生成一个新的虚拟DOM,让它和旧的虚拟DOM通过Diff算法进行对比,生成一组差异对象。
    然后变量差异对象,将修改更新到真实的DOM树上。

    React的三大特性:JSX语法糖,虚拟DOM, Diff算法
    它们之间的关系可以简单理解为:
    1.JSX语法糖转换:在webpack进行编译时,JSX语法糖 被转换成 React.createElement的React的API调用,React.createElement的React的API调用会得到一个js对象。
    2.生成抽象语法树:通过将这棵JSX树中的每个元素 转换成相应的 React.createElement 的API调用,最终得到一棵js对象树, 这棵js对象树就是虚拟DOM树。
    3.使用Diff算法对这棵树进行比较运算,得出要更新的虚拟DOM差异对象,然后遍历这些差异对象,将修改更新到真实的DOM中去。
    Diff算法对这棵js对象树的diff分三层:
    tree diff :树层级的对比
    component diff :组件层级的对比
    element diff: 元素层级的对比
    key: key属性,把页面上的DOM节点与虚拟DOM节点做一层关联关系。

     

    DOM与虚拟DOM的概念
    原来的DOM是浏览器中的JS提供的功能,所以我们只能使用浏览器提供的API,如:getElementById进行操作DOM对象。
    虚拟DOM是程序员手动模拟的,类似与浏览器中的DOM。

    虚拟DOM出现的原因
    是为了提升浏览器的渲染性能,避免因为某一部分DOM元素的更新,刷新整棵DOM树。所以使用js创建一个js对象来模拟一个DOM对象。
    一个js对象中包含多个子对象,就构成了一棵虚拟的DOM树。
    通过前后比较2棵虚拟DOM树的差异,将得到的差异对象进行遍历批量更新,从而真实的DOM得到了页面更新。
    React内部已经实现了虚拟DOM, 所以通过React框架开发的web页面,默认就有了这个能力。

    JSX语法糖
    在React中,不能像Vue中那样直接写html元素,要通过react的API创建元素React.createElelement()
    React.createElement有三个参数,并返回一个dom对象,也就是js对象
    参数一:标签名字符串
    参数二:属性对象
    参数三及其更多:子元素

    JSX的原理是什么?
    JSX是符合XML规范的JS语法
    JSX只是一个语法糖,它内部运行的时候是把类似于HTML这样的标签代码转换为React.createElement的形式。
     
    需要安装:npm i babel-preset-react -D
    webpack没法编译jsx代码,它会找到babel进行编译这个代码,babel发现它是react内的语法,就会调用babel-preset-react插件进行解析

    babel碰到<>按照html的语义, 使用React.createElement进行解析
    碰到{}会按照js进行解析, {}中只能存放一个带返回值的js语句
    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
    50
    51
    52
    /*
    React: 创建,修改React组件,管理组件的生命周期
    ReactDOM: 操作真实Dom, 将虚拟Dom渲染到真实的Dom之上。
    */
    import React from "react";
    import ReactDOM from "react-dom";
     
    /*
    在React中,不能像Vue中那样直接写html元素,要通过react的API创建元素React.createElelement()
    React.createElement有三个参数,并返回一个dom对象,也就是js对象
    参数一:标签名字符串
    参数二:属性对象
    参数三及其更多:子元素
    */
     
    /*
        JSX的原理是什么?
        JSX是符合XML规范的JS语法
        JSX只是一个语法糖,它内部运行的时候是把类似于HTML这样的标签代码转换为React.createElement的形式。
     
        需要安装:npm i babel-preset-react -D
        webpack没法编译jsx代码,它会找到babel进行编译这个代码,babel发现它是react内的语法,就会调用babel-preset-react插件进行解析
    */
     
     
    /*
        babel碰到<>按照html的语义, 使用React.createElement进行解析
        碰到{}会按照js进行解析, {}中只能存放一个带返回值的js语句
    */
     
    var list = []
    for (let i = 0; i < 10; i++) {
        var p =

    这是for循环生成的p标签

        list.push(p)
    }
     
    var myTitle = "这是标题的title"
    var h2D =
        这是一个jsx的h2标题
        

    JSX真好用

        { list }
        {/* 这是jsx中的注释 */}
     
     
     
    var divD = React.createElement("div", {title:"这是一个div", id:"rootSub"},"这是一个React创建的div", h2D)
     
    /*
    将react元素渲染到页面对应的位置上。
    */
    ReactDOM.render(divD, document.getElementById("root"))

    React组件定义方式 

    JS中定义对象的方式有2种:
    1.使用构造函数
    2.使用类

    构造函数组件
    js文件内部的构造函数组件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*
        React中,构造函数就是一个最基本的组件, 使用时把构造函数的名称当做html标签名使用。
        React自定义的组件必须是大写字母开头,小写字母编译器默认是浏览器提供的组件。会从浏览器中去查找。
    */
    function Hello() {
        return
            这是使用Hello构造函数 创建的基本组件Hello
        
    }
    jsx文件内的构造函数组件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import React from "react"
     
    function World(props) {
        return
            接收到的参数:{props.name}
            
        
    }
    export default World
    可以通过对象参数扩散的方式进行批量传参
    1
    2
    {/* 如果传递的参数是个对象,可以进行对对象进行属性扩散进行批量传参 */}
     
    类组件
    在类中定义的方法和利用构造函数创建对象时将方法放在构造函数protoType中,在内存中的位置是一样的。
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    // 1.构造函数, 创建对象
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    //Person.prototype中定义的方法和属性是是定义在当前对象的protoType中的(A区域)
    Person.prototype.say = function () {
        console.log('hello')
    }
    Person.prototype.myId = 220
     
    var p1 = new Person('jack', 12);
    console.log(p1);
     
     
     
    // 2.类,创建对象, 类的本质也是一个构造方法实现的
    class Per {
        //构造器, 调用new方法创建对象时,会调用个constructor
        constructor(name, age){
            this.name = name
            this.age = age
        }
        //es6 定义的方法定义方式,类中的方法也是定义在当前对象的protoType中的(A区域)
        say() {
            console.log('这是Person中的hello方法')
        }
     
        //class中的static方法和变量,是放在了constructor方法内部的原型对象中(B区域)
        static myId = 230;
        static myIdGet = function () {
            console.log('myIdGet')
        }
    }
     
    var p2 = new Per('jack22', 122);
    console.log(p2);
    类的重要特性:封装,继承,多态,
     
     
     
    // 3.类的重要特性:封装,继承,多态,
    //继承:实现功能的复用
    class Chinese extends Per {
        constructor(address, sex, name, age){
            super(name, age)
            this.address = address
            this.sex = sex
        }
    }
     
    var c1 = new Chinese('北京', '男', 'jack', 12)
    console.log(c1);
    Chinese.myIdGet();
     
    //多态:父类中定义一个抽象空方法,不同的子类进行不同的重写实现
    class Animal {
        say() {
     
        }
    }
    class Dog extends Animal {
        say(){
            console.log("wang wang");
        }
    }
    class Cat extends Animal {
        say(){
            console.log("miao miao");
        }
    }

     函数组件与类组件的区别

    函数组件内部没有state, 只有从外部传入的props
    类组件内部有state和props, 并且通过setState更新数据可以刷新UI界面
    结论:
    1.函数组件是无状态组件,类组件是有状态组件
    2.类组件是一个组件模板,它有生命周期。函数组件没有生命周期

    如何选择使用?
    1.如果组件需要保存私有状态,并根据不同的状态执行不同的逻辑,那么使用类组件。
    2.如果组件只用于UI展示,那么就用函数组件。
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    import React from "react";
    import ReactDOM from "react-dom";
     
     
     
    var h1Dom = React.createElement("h2", {title:"hello, jsx的h1"}, '这是jsx的子元素')
     
    //1.构造函数组件 的参数需要在参数中进行显示声明
    function Hello(props) {
        return
            Hello 构造函数 组件:{props.name} - {props.age}
        
    }
     
    // 2.通过继承React.Component类,就得到一个类组件模板
    // 类组件的参数 内部会将参数自动包装到props的内部
    class Hello2 extends React.Component {
        constructor(props) {
            super(props)
            //在constructor中是不能直接通过this.props获取参数的,如果想获取参数,需要显示的在constructor中添加参数
            console.log(this.props)
            console.log('---------')
            console.log(props)
     
     
            //props外部传参,不能进行修改
            //state:私有状态变量,调用setState修改可以更新UI
            this.state = {
                msg: 'des',
                state: 10
            }
        }
     
        render() {
            return
                这是一个React.Component的组件:{this.props.name} - {this.props.age}
            
        }
    }
     
    /*
    函数组件与类组件的区别
    函数组件内部没有state, 只有从外部传入的props
    类组件内部有state和props, 并且通过setState更新数据可以刷新UI界面
    结论:
    1.函数组件是无状态组件,类组件是有状态组件
    2.类组件是一个组件模板,它有生命周期。函数组件没有生命周期
     
    如何选择使用?
    1.如果组件需要保存私有状态,并根据不同的状态执行不同的逻辑,那么使用类组件。
    2.如果组件只用于UI展示,那么就用函数组件。
     
    */
     
     
    ReactDOM.render(
        {h1Dom}
        "jack" age={20}>
        "jack" age={20}>
    , document.getElementById("root"))
    函数组件与类组件的使用
    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
    1.类组件基本使用
    class CommentList extends React.Component {
        constructor(props) {
            super(props)
     
            this.state = {
                list : [
                    {user:'zhang san', content: '呵呵呵'},
                    {user:'zhang san2', content: '呵呵,55'},
                    {user:'zhang san3', content: '呵呵呵kk'},
                    {user:'zhang san4', content: '呵呵呵dfgfd'},
                    {user:'zhang san5', content: '呵呵呵fff'},
                    {user:'zhang san6', content: '呵呵呵dddd'},
                    {user:'zhang san7', content: '呵呵呵3333'},
                ]
            }
        }
     
        render(){
            return
                {
                    this.state.list.map((item,index) => {
                        return
                            

    姓名:{item.user}

                            

    内容:{item.content}

                        
                    })
                }
            
        }
    }
     
     
    ReactDOM.render(
        
    , document.getElementById("root"))

     

     
     
  • 相关阅读:
    BLEU: a Method for Automatic Evaluation of Machine Translation
    使用Python CV2融合人脸到新图片--优化版
    招投标系统软件源码,招投标全流程在线化管理
    软件测试 | 当面试时被问到“搭建过测试环境吗”, 身为小白要怎么回答?
    【JavaScript】DOM查询(子节点、父节点、兄弟节点)源码详解
    【计算机视觉】Image Feature Extractors方法介绍合集(二)
    FreeRTOS 中互斥锁的基本使用方法
    阿里大牛总结的Netty手册,面试再也不怕被问Netty了,奥利给
    音频怎么转文字?学会这3招,轻松拉满你的工作效率
    JavaEE——HttpServletRequest
  • 原文地址:https://www.cnblogs.com/zhou--fei/p/17778789.html