zoukankan      html  css  js  c++  java
  • 对react的研究20200723

    JSX
    在线尝试
    1. 什么是JSX
    语法糖
    React 使⽤ JSX 来替代常规的 JavaScript。
    JSX 是⼀个看起来很像 XML 的 JavaScript 语法扩展。
    2. 为什么需要JSX
    开发效率:使⽤ JSX 编写模板简单快速。
    执⾏效率:JSX编译为 JavaScript 代码后进⾏了优化,执⾏更快。
    类型安全:在编译过程中就能发现错误。
    3. 原理:babel-loader会预编译JSX为React.createElement(...)
    4. 与vue的异同:
    react中虚拟dom+jsx的设计⼀开始就有,vue则是演进过程中才出
    现的
    jsx本来就是js扩展,转义过程简单直接的多;vue把template编译
    为render函数的过程需要复杂的编译器转换字符串-ast-js函数字符
    JSX预处理前:
    import React, { Component } from "react";
    import ReactDOM from "react-dom";
    import "./index.css";
    function FuncCmp(props) {
    return <div>name: {props.name}</div>;
    }
    class ClassCmp extends Component {
    render() {
    return <div>name: {this.props.name}</div>;
    }
    }
    const jsx = (
    <div>
    <p>我是内容</p>
    <FuncCmp name="我是function组件" />
    <ClassCmp name="我是class组件" />
    </div>
    );
    console.log("jsx", jsx);
    ReactDOM.render(jsx, document.getElementById("root"));
    build后
    function FuncCmp(props) {
    return React.createElement(
    "div",
    null,
    "name: ",
    props.name
    );
    }
    class ClassCmp extends React.Component {
    render() {开课吧web全栈工程师
    return React.createElement(
    "div",
    null,
    "name: ",
    this.props.name
    );
    }
    }
     
    let jsx = React.createElement(
    "div",
    null,
    " ",
    React.createElement(
    "div",
    { className: "border" },
    "我是内容"
    ),
    " ",
    React.createElement(FuncCmp, { name: "我是function组件"
    }),
    " ",
    React.createElement(ClassCmp, { name: "我是class组件" }),
    " "
    );
    ReactDOM.render(jsx, document.getElementById('root'));
     
    实现三⼤接⼝:React.createElement,
    React.Component, ReactDom.render
     
    CreateElement
    将传⼊的节点定义转换为vdom。
    src/index.js
     
    // import React, { Component } from "react";
    // import ReactDOM from "react-dom";
    import React from "./kreact/";
    import ReactDOM from "./kreact/ReactDOM";
    import "./index.css";
    function FuncCmp(props) {
    return <div>name: {props.name}</div>;
    }
    class ClassCmp extends React.Component {
    constructor(props) {
    super(props);
    this.state = { counter: 0 };
    }
    clickHandle = () => {
    console.log("clickHandle");
    };
    render() {
    const { counter } = this.state;
    return (
    <div>
    name: {this.props.name}
    <p>counter: {counter}</p>
    <button onCclick={this.clickHandle}>点击</button>
    {[0, 1, 2].map(item => {
    return <FuncCmp name={"我是function组件" + item}
    key={item} />;
    })}
    </div>
    );
    }
    }
    let jsx = (开课吧web全栈工程师
    <div>
    <div className="border">我是内容</div>
    <FuncCmp name="我是function组件" />
    <ClassCmp name="我是class组件" />
    </div>
    );
    ReactDOM.render(jsx, document.getElementById("root"));
     
    创建./src/kkreact/index.js,它需要包含createElement⽅法
    import { Component } from "./Component";
    function createElement(type, props, ...children) {
    props.children = children;
    //判断组件类型
    let vtype;
    if (typeof type === "string") {
    // 原⽣标签
    vtype = 1;
    } else if (typeof type === "function") {
    // 类组件 函数组件
    vtype = type.isReactComponent ? 3 : 2;
    }
    return {
    vtype,
    type,
    props,
    };
    }
    const React = {
    createElement,
    Component,
    };
    export default React;
     
    render
    创建react-dom.js
    需要实现⼀个render函数,能够将vdom渲染出来,这⾥先打印vdom
    结构
    import { mount } from "./virtual-dom";
    function render(vnode, container) {
    //vnode->node
    mount(vnode, container);
    // container.appendChild(node)
    console.log("render", vnode);
    }
    export default {
    render,
    };
    实现Component
     
    要实现class组件,需要添加Component类,kreact.js
    export class Component {
    static isReactComponent = {};
    constructor(props) {
    this.props = props;
    this.state={}
    }
    }
    组件类型判断
    传递给createElememnt的组件有三种组件类型,1:dom组件, 2. class
    组件, 3. 函数组件,使⽤vtype属性标识
    转换vdom为真实dom
    export function mount(vnode, container) {
    const { vtype } = vnode;
    //创建⽂本节点
    if (!vtype) {
    mountText(vnode, container);
    }
    // 创建原⽣节点
    if (vtype === 1) {
    mountHtml(vnode, container);
    }
    // 创建函数组件
    if (vtype === 2) {
    mountFunc(vnode, container);
    }开课吧web全栈工程师
    //创建类组件
    if (vtype === 3) {
    mountClass(vnode, container);
    }
    }
    function mountText(vnode, container) {
    const textNode = document.createTextNode(vnode);
    container.appendChild(textNode);
    }
    // 创建原⽣节点
    function mountHtml(vnode, container) {
    const { type, props } = vnode;
    const node = document.createElement(type);
    const { children, ...rest } = props;
    Object.keys(rest).map(item => {
    if (item === "className") {
    node.setAttribute("class", rest[item]);
    } else if (item.slice(0, 2) === "on") {
    node.addEventListener("click", rest[item]);
    }
    });
    children.map(item => {
    if (Array.isArray(item)) {
    item.map(c => {
    mount(c, node);
    });
    } else {
    mount(item, node);
    }
    });
    container.appendChild(node);
    }开课吧web全栈工程师
    // 创建函数组件
    function mountFunc(vnode, container) {
    const { type, props } = vnode;
    const node = type(props);
    mount(node, container);
    }
    //创建类组件
    function mountClass(vnode, container) {
    const { type, props } = vnode;
    const cmp = new type(props);
    const node = cmp.render();
    mount(node, container);
    }
    执⾏渲染,kreact-dom.js
    import { mount } from "./virtual-dom";
    function render(vnode, container) {
    //vnode->node
    mount(vnode, container);
    // container.appendChild(node)
    console.log("render", vnode);
    }
    export default {
    render,
    };
    总结:
    1. webpack+babel编译时,替换JSX为
    React.createElement(type,props,...children)开课吧web全栈工程师
    2. 所有React.createElement()执⾏
    结束后得到⼀个JS对象即vdom,它能
    够完整描述dom结构
    3. ReactDOM.render(vdom, container)可以将vdom转换为dom并追加
    到container中
    4. 实际上,转换过程需要经过⼀个diffff过程,⽐对出实际更新补丁操作dom
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    【JavaScript】JavaScript学习 四 JavaScript 语句
    【Javascript】javascript学习 十二 JavaScript 函数
    【Javascript】javascript学习 六 七 JavaScript 变量/运算符
    【JavaScript】JavaScript学习 三 把 JavaScript 放置到何处
    【Javascript】javascript学习 十四 JavaScript Break 和 Continue
    【Javascript】javascript学习 十 JavaScript 消息框
    如何查询数据库的主键约束schema?
    无限级下拉列表的无限级分级[asp.net](转)
    结构体
    对typedef的了解
  • 原文地址:https://www.cnblogs.com/zhouyideboke/p/13367001.html
Copyright © 2011-2022 走看看