[Web Fronted] 前端基础框架: React

  • 部分开源项目是基于 Web 前端框架 React 构建的,有必要了解一二。

避免一脸懵逼,不知道怎么修改相关代码和配置

概述: React

React 的简介

  • React 起源于 Facebook内部项目

因为该公司对市场上所有 JavaScript MVC 框架 都不满意,就决定自己写一套,用来架设 Instagram 的网站。
做出来以后,发现这套东西很好用,就在2013年5月开源了。

  • React 是一个用于动态构建用户界面的 JavaScript 库(只关注于视图)。

React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。

React 的特点

  1. 声明式设计与编码 − React采用声明范式,可以轻松描述应用。

  2. 高效 − React通过对DOM的模拟,最大限度地减少与DOM的交互。

高效(优秀的Diffing算法)

  1. 灵活 − React可以与已知的库或框架很好地配合。

  2. JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。

  3. Component & 组件化编码 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。

  4. 单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

单向数据绑定

  1. 虚拟 DOM

  2. React Native 编写原生应用

React 高效的原因

  • 使用虚拟(virtual)DOM, 不总是直接操作页面真实DOM。
  • DOM Diffing算法, 最小化页面重绘。

React 官网

React 的主要原理

  • 传统的web应用操作DOM一般是直接更新操作

但是我们知道DOM更新通常是比较昂贵的。
而React为了尽可能减少对DOM的操作,提供了一种不同的而又强大的方式来更新DOM,代替直接的DOM操作。
就是VirtualDOM,一个轻量级的虚拟的DOM,就是React抽象出来的一个对象,描述dom应该什么样子的,应该如何呈现。
通过这个Virtual DOM去更新真实的DOM,由这个Virtual DOM管理真实DOM的更新。

  • 为什么通过这多一层的Virtual DOM操作就能更快呢? > + 这是因为React有个diff算法,更新VirtualDOM并不保证马上影响真实的DOM,React会等到事件循环结束,然后利用这个diff算法,通过当前新的dom表述与之前的作比较,计算出最小的步骤更新真实的DOM。

最明显的一点好处就是React所谓的 dom diff ,能够实现delta级别的dom更新。
当有数据变动导致DOM变动时,React不是全局刷新,而是通过它内部的dom diff 算法计算出不同点,然后以最小粒度进行更新。
这也是React号称性能好的原因。

Facebook为什么要建造React

  • Facebook的工程师在做大型项目时,由于他们非常巨大的代码库和庞大的组织,使得MVC很快变得非常复杂,每当需要添加一项新的功能或特性时,系统的复杂度就成级数增长,致使代码变得脆弱和不可预测,结果导致他们的MVC正在土崩瓦解,所以Facebook认为MVC不适合大规模应用,当系统中有很多的模型和相应的视图时,其复杂度就会迅速扩大,非常难以理解和调试,特别是模型和视图间可能存在的双向数据流动。

基于上面的原因,Facebook认为MVC无法满足他们的扩展需求,为了解决上述问题需要“以某种方式组织代码,使其更加可预测”,于是他们提出的FluxReact来实现。

React Hello World Application

Hello World Application

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello, React Application!</title>
    <!-- 引入 React 核心库 -->
    <!-- <script src="../js/react.development.js"></script> -->
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <!-- 引入 react-dom 用于支持 react 操作 DOM -->
    <!-- <script src="../js/react-dom.development.js"></script> -->
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

    <!-- 引入babel:
        1. ES6 ==> ES5
        2. jsx ==> js
    -->
    <!-- <script src="../js/babel.min.js"></script> -->
    <!-- 生产环境中不建议使用 | 在浏览器中使用 Babel 来编译 JSX 效率是非常低的 -->
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
</head>
<body>
    <!-- 准备好一个 DOM 容器 -->
    <div id="test"></div>


    <!-- 方式1 -->
    <!-- <script type="text/babel">
        // 1. 创建虚拟 DOM
        const VDOM = <h1>Hello,React</h1>

        // 2. 渲染到页面中的指定 DOM
        // ReactDOM.render(虚拟DOM,真实DOM)
        ReactDOM.render(VDOM,document.getElementById('test'))
    </script> -->


    <!-- 方式2 -->
    <script type="text/babel">
    // 简单的 React 组件
    function App() {
        return <h1>Hello, React Application!!</h1>;
    }
    
    const root = ReactDOM.createRoot(document.getElementById("test"));
    // 渲染 React 组件到 DOM
    root.render(<App />);
    </script>
</body>
</html>

效果

基础库的安装与导入

CDN与本地引入方式

  • React 库: 用于构建用户界面。
  • ReactDOM 库:用于在浏览器中渲染 React 组件。
  • Babel Standalone 库:用于在浏览器中即时编译 JSX 语法。(不建议生产环境中使用)
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

<!-- 生产环境中不建议使用 | 在浏览器中使用 Babel 来编译 JSX 效率是非常低的 -->
<script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/babel-standalone/6.26.0/babel.min.js"></script>

NPM Install 导入方式

创建项目,并导入React框架

mkdir my-react-app
cd my-react-app

npm init
  # 注:填写新npm项目的信息

npm install react@18.2.0 react-dom@18.2.0 react-scripts@5.0.1 cra-template@1.2.0 babel-standalone@6.26.0
  # 注:安装react依赖,babel-standalone 可不安装

创建并编辑index.html

mkdir -p my-react-app/public
vim index.html

编辑内容:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <!-- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> -->
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <!-- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> -->
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> -->
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

创建并编辑App.js组件及自定义的组件

  • 创建并编辑Add.js组件
mkdir -p my-react-app/src
vim my-react-app/src/Add.js

编辑内容:Add.js

import React,{Component} from 'react';
import PropTypes from 'prop-types';

class Add extends Component{
    constructor(props){
        super(props);
        this.state={
            todoInput:''
        }
        this.add = this.add.bind(this);
    }
    add(){
        //读取文本框值
        const todo = this.todoInput.value.trim();
        //值合法性判断
        if(!todo){
            return;
        }
        //添加
        this.props.addTodo(todo);
        this.todoInput.value='';
    }
    render(){
        return (
            <div>
                <input type="text" ref={input=>this.todoInput=input}/>
                <button onClick={this.add}>Add #{this.props.count+1}</button>
            </div>
        );
    }
}
Add.propTypes={
    count:PropTypes.number.isRequired,
    addTodo:PropTypes.func.isRequired
}
export default Add;
  • 创建并编辑List.js组件
mkdir -p my-react-app/src
vim my-react-app/src/List.js

编辑内容:List.js

import React,{Component} from 'react';
import PropTypes from 'prop-types';

class List extends Component{

    render(){
        const {todos} = this.props;
        return (
            <ul>
               {
                todos.map((item,index)=>{
                       return <li key={index}>{item}</li>
                   })
               }
            </ul>
        );
    }
}
List.propTypes = {
    todos:PropTypes.func.isRequired
}
export default List;
  • 创建并编辑App.js组件
mkdir -p my-react-app/src
vim my-react-app/src/App.js

编辑内容如下(可按自己需要另作编码)

import React, { Component } from 'react';
//import logo from './logo.svg';
//import './App.css';
import Add from './Add';
import List from './List';

class App extends Component{
    constructor(props){
        super(props);
        this.state={
            todos:['C#从入门到放弃','Java从入门到放弃','C++从入门到放弃']
        }
        this.addTodo = this.addTodo.bind(this);
    }
    addTodo(todo){
        const {todos} = this.state;
        todos.unshift(todo);
        this.setState({todos});
    }
    render(){
        const {todos} = this.state;
        return (
        <div>
            <div>编程语言列表(Program Languages List)</div>
            <Add count={todos.length} addTodo={this.addTodo}/>
            <List todos={todos}/>
        </div>
        );
    }
}

 
/**
class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <h2>欢迎来到MyApp</h2>
        </div>
        <p className="App-intro">
          你可以在 <code>src/App.js</code> 文件中修改。
        </p>
      </div>
    );
  }
}
**/
 
export default App;

编辑并创建index.js

vim src/index.js
  • src/index.js: 这是 React 应用的入口文件。它是应用的启动点,通常在这里调用 ReactDOM.render 将组件渲染到页面的根节点。

编辑内容:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

配置package.json

  • 编辑/配置package.json

更新:scripts

"start": "set PORT=8081 && react-scripts start",
"build": "react-scripts build"
"test": "echo \"Error: no test specified\" && exit 1"

启动项目

npm run start

运行效果

NPM + create-react-app 导入方式

  • 还可以使用 create-react-app 工具创建的 react 开发环境:
import React from "react";
import ReactDOM from "react-dom";

function Hello(props) {
  return <h1>Hello World!</h1>;
}

ReactDOM.render(<Hello />, document.getElementById("root"));
  • Step1 安装 nodejs 和 npm / cnpm

在开始之前,确保你已经安装了 Node.js 和 npm,你可以通过以下命令检查它们是否已经安装:

node -v
npm -v

如果你的系统还不支持 Node.js 及 NPM 可以参考:

我们建议在 React 中使用 CommonJS 模块系统,比如 browserifywebpack,本篇使用 webpack

国内使用 npm 速度很慢,你可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:

$ npm install -g cnpm --registry=https://registry.npmmirror.com
$ npm config set registry https://registry.npmmirror.com

这样就可以使用 cnpm 命令来安装模块了:

$ cnpm install [packageName]

更多信息可以查阅: http://npm.taobao.org/。

  • Step2 使用 create-react-app 快速构建 React 开发环境
  • React 提供了一个官方工具 Create React App,用于快速搭建 React 项目。
  • create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境。
  • create-react-app 自动创建的项目是基于 Webpack + ES6
  • 执行以下命令创建项目:
$ cnpm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start
  • 也可以使用 npx 命令来创建,npxnpm 5.2.0 及更高版本中包含的一个工具,用于执行本地或远程的 npm 包:
npx create-react-app my-app

在浏览器中打开 http://localhost:3000/ ,结果如下图所示:

项目的目录结构:

my-first-react-app/
├── node_modules/
├── public/
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src/
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   ├── reportWebVitals.js
│   └── setupTests.js
├── .gitignore
├── package.json
├── README.md
└── yarn.lock (或 package-lock.json)
  • 目录和文件说明
  • node_modules/

存放所有项目的依赖包。这个目录由 npm 或 yarn 自动生成,包含了项目运行所需的所有第三方库和模块。

  • public/

存放静态文件,Webpack 不会对这个目录中的文件进行处理。public 目录下的文件会被直接复制到构建目录。

  • favicon.ico:浏览器标签页上的小图标。
  • index.html:HTML 模板文件,React 组件将被挂载到这个文件中的 div 元素中。
  • logo192.png / logo512.png: 不同尺寸的 React logo 图标。
  • manifest.json: Web 应用清单文件,用于定义应用的名称、图标等元数据。
  • robots.txt:用于告诉搜索引擎哪些页面可以被抓取。
  • src/

存放应用的源代码。这里是你主要进行开发的地方。

  • App.css: App 组件的样式文件。
  • App.js:主组件文件,定义了一个基础的 React 组件。
  • App.test.js: App 组件的测试文件。
  • index.css: 全局样式文件。
  • index.js: 应用的入口文件,负责渲染 React 组件到 DOM 中。
  • logo.svg: React logo 的 SVG 文件。
  • reportWebVitals.js: 用于性能监测的文件,可以帮助你了解和分析应用的性能。
  • setupTests.js: 用于设置测试环境的文件。
  • .gitignore

列出 Git 应该忽略的文件和目录,例如 node_modules/ 和构建输出的目录。

  • package.json

项目的配置文件,包含项目信息、脚本、依赖项等。

  • README.md : 项目的自述文件,包含项目的基本信息和使用说明。
  • yarn.lock / package-lock.json : 锁定文件,记录了确切的依赖版本,确保在不同环境中安装的依赖一致。这个package-lock.json 是在 npm install时生成一份文件,用以记录当前状态下实际安装的各个npm package的具体来源和版本号,以保证其他人在npm install时大家的依赖能保证一致。

例如:

"dependencies": {
"@types/node": "^8.0.33",
},

向上标号^是定义了向后(新)兼容依赖,指如果 types/node的版本是超过8.0.33,并在大版本号(8)上相同,就允许下载最新版本的 types/node库包,例如实际上可能运行npm install时候下载的具体版本是8.0.35。波浪号

原来package.json文件只能锁定大版本,也就是版本号的第一位,并不能锁定后面的小版本,你每次npm install都是拉取的该大版本下的最新的版本,为了稳定性考虑我们几乎是不敢随意升级依赖包的,这将导致多出来很多工作量,测试/适配等。
所以,package-lock.json文件就出来了,当你每次安装一个依赖的时候就锁定在你安装的这个版本。

  • 尝试修改 src/App.js 文件代码:src/App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
 
class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>欢迎来到MyApp</h2>
        </div>
        <p className="App-intro">
          你可以在 <code>src/App.js</code> 文件中修改。
        </p>
      </div>
    );
  }
}
 
export default App;

原理探究

创建虚拟DOM的方式

  • 方式1:纯JS方式(一般不用)
  • 方式2:虚拟DOM

虚拟DOM与真实DOM

  1. React提供了一些API来创建一种 “特别” 的一般js对象
  • const VDOM = React.createElement('xx',{id:'xx'},'xx')

上面创建的就是一个简单的虚拟 DOM 对象

  1. 虚拟DOM对象最终都会被React转换为真实的DOM

  2. 我们编码时,基本只需要操作react虚拟DOM相关数据,react会转换为真实DOM变化而更新界面。

  3. 虚拟DOM与真实DOM的区别

关于虚拟DOM:

  • 本质是Object类型的对象(一般对象)
  • 虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部生成并使用的。
  • 虚拟DOM最终会被React转换为真实DOM,渲染在页面上;
<script type="text/babel">
    // 1. 创建虚拟 DOM
    const VDOM = (
        <h1>Hello,
            <span>React</span>
        </h1>
    )

    // 2. 渲染到页面中的指定 DOM
    // ReactDOM.render(虚拟DOM,真实DOM)
    ReactDOM.render(VDOM,document.getElementById('test'))
    const TDOM = document.getElementById('demo')
    // console.log(typeof VDOM) // Object
    // console.log(VDOM instanceof Object) // true
    console.log('虚拟DOM',VDOM)
    console.log('真实DOM',TDOM)
    // 调试
    debugger
</script>

React JSX

什么是 JSX ?

  • JSXReact的核心组成部分,它使用XML标记的方式去直接声明界面界面组件之间可以互相嵌套。

可以理解为在JS中编写与XML类似的语言,一种定义带属性树结构(DOM结构)的语法
它的目的不是要在浏览器或者引擎中实现,它的目的是通过各种编译器将这些标记编译成标准的JS语言

  • 虽然你可以完全不使用JSX语法,只使用JS语法,但还是推荐使用JSX,可以定义包含属性的树状结构的语法,类似HTML标签那样的使用,而且更便于代码的阅读。

  • 使用JSX语法后,你必须要引入babelJSX解析器,把JSX转化成JS语法

这个工作会由babel自动完成。
同时引入babel后,你就可以使用新的es6语法,babel会帮你把es6语法转化成es5语法,兼容更多的浏览器。

  • 全称: JavaScript XML
  • react 定义的一种类似于 XMLJS扩展语法:

JS + XML 的本质: React.createElement(component, props, ...children) 方法的语法糖

  • 作用: 用来简化创建虚拟DOM
  • 写法:var ele = <h1>Hello JSX!</h1>
  • 注意1:它不是字符串, 也不是 HTML/XML 标签
  • 注意2:它最终产生的就是一个JS对象
  • 标签名任意: HTML 标签或其它标签

  • 标签属性任意: HTML 标签属性或其它

  • 基本语法规则

  • 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
  • 遇到以 { 开头的代码,以JS语法解析: 标签中的js表达式必须用{ }包含
  • babel.js的作用
  • 浏览器不能直接解析JSX代码, 需要 babel 转译为纯JS的代码才能运行
  • 只要用了JSX,都要加上type="text/babel", 声明需要 babel 来处理

渲染虚拟DOM(元素)

  • 语法: ReactDOM.render(virtualDOM, containerDOM)
  • 作用: 将虚拟DOM元素渲染到页面中的真实容器DOM中显示
  • 参数说明
  • 参数一: 纯js或jsx创建的虚拟dom对象
  • 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)

JSX的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .title{
            background-color: aliceblue;
            width: 200px;
        }
    </style>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入 React 核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入 react-dom 用于支持 react 操作 DOM -->
    <script src="../js/react-dom.development.js"></script>

    <!-- 引入babel:
            1. ES6 ==> ES5
            2. jsx ==> js
    -->
    <script src="../js/babel.min.js"></script>

    <script type="text/babel">

        let myData = 'Student'
        let myId = 'ITStudent'
        // 1. 创建虚拟 DOM
        const VDOM = (
            <div>
                <h1 className="title" id={myId.toUpperCase()}>Hello,
                    <span style={{color:'white',fontSize:'20px'}}>{myData}</span>
                </h1>
                <input type="text" />
                <Good></Good>
            </div>
        )

        // 2. 渲染到页面中的指定 DOM
        // ReactDOM.render(虚拟DOM,真实DOM)
        ReactDOM.render(VDOM,document.getElementById('test'))

    </script>
</body>
</html>

JSX 的语法规则

  • 定义虚拟DOM时,不要写引号;
  • 标签中混入JS表达式时,要用 {}
  • 样式的类名指定不要用class,要用className;
  • 内联样式,要用style={{key:value}}的形式去写
  • 只能有一个根元素
  • 所有标签都必须闭合
  • 标签的首字母:
    1. 若小写字母开头,则将该标签转化为html同名的元素,渲染到页面;若html没有同名的元素,则报错。
    1. 若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错;

模块与组件、模块化与组件化的理解

模块

  • 理解:向外提供特定功能的js程序, 一般就是一个js文件
  • 为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂。
  • 作用:复用js, 简化js的编写, 提高js运行效率

什么是模块化?当应用的js都以模块来编写的, 这个应用就是一个模块化的应用

组件

  1. 理解:用来实现局部功能效果的代码和资源的集合(html/css/js/image等等)
  2. 为什么要用组件: 一个界面的功能更复杂
  3. 作用:复用编码, 简化项目编码, 提高运行效率

什么是组件化?当应用是以多组件的方式实现, 这个应用就是一个组件化的应用

函数式组件

<script type="text/babel">
    // 1. 创建函数式组件
    function MyComponent(){
        // 这里的 this 是 undefined,因为 babel 编译,开启了严格模式
        console.log(this)
        // 一定需要有返回值
        return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
    }

    // 2. 渲染到页面中的指定 DOM
    // ReactDOM.render(虚拟DOM,真实DOM)
    ReactDOM.render(<MyComponent />,document.getElementById('test'))

    /*
	执行 ReactDOM.render() 方法之后,发生了什么?
		1. React 解析了组件标签,找到对应的组件
		2. 发现这个组件是一个函数定义的,随后调用该函数,生成了一个虚拟DOM
		3. 最后将虚拟DOM转化为真实DOM,呈现在页面中;
    */
</script>
  • 函数式组件执行过程?
  • React 解析组件标签,找到对应的组件
  • 发现这个组件是一个函数定义的,随后调用该函数,生成了一个虚拟DOM
  • 最后将虚拟DOM转化为真实DOM,呈现在页面中;

类式组件

<script type="text/babel">
    // 1. 创建一个类式组件
    class MyComponent extends React.Component{
        // render方法是放在原型上的
        // render中的this是谁? -- 实例对象 <===> MyComponent组件实例对象
        render(){
            console.log('render中的this',this)
            return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
        }
    }

    // 2. 渲染到页面中的指定 DOM
    // ReactDOM.render(虚拟DOM,真实DOM)
    ReactDOM.render(<MyComponent />,document.getElementById('test'))

    /*
        执行 ReactDOM.render() 方法之后,发生了什么?
            1. React 解析了组件标签,找到对应的组件
            2. 发现这个组件是一个类定义的,随后new出来一个实例对象,并通过该实例调用原型上的render方法
            3. 将render()返回的内容生成了一个虚拟DOM
            4. 最后将虚拟DOM转化为真实DOM,呈现在页面中;
    */
   let c = new MyComponent()
   console.log(c)
</script>
  • 类式组件执行过程?
  • React 解析了组件标签,找到对应的组件
  • 发现这个组件是一个类定义的,随后new出来一个实例对象,并通过该实例调用原型上的render方法
  • render()返回的内容生成了一个虚拟DOM
  • 最后将虚拟DOM转化为真实DOM,呈现在页面中;

create-react-app工具命令

  • url

查看工具版本

$ create-react-app --version
5.0.1

帮助手册

$ create-react-app --help
Usage: create-react-app <project-directory> [options]

Options:
  -V, --version                            output the version number
  --verbose                                print additional logs
  --info                                   print environment debug info
  --scripts-version <alternative-package>  use a non-standard version of react-scripts
  --template <path-to-template>            specify a template for the created project
  --use-pnp
  -h, --help                               output usage information
    Only <project-directory> is required.

    A custom --scripts-version can be one of:
      - a specific npm version: 0.8.2
      - a specific npm tag: @next
      - a custom fork published on npm: my-react-scripts
      - a local path relative to the current working directory: file:../my-react-scripts
      - a .tgz archive: https://mysite.com/my-react-scripts-0.8.2.tgz
      - a .tar.gz archive: https://mysite.com/my-react-scripts-0.8.2.tar.gz
    It is not needed unless you specifically want to use a fork.

    A custom --template can be one of:
      - a custom template published on npm: cra-template-typescript
      - a local path relative to the current working directory: file:../my-custom-template
      - a .tgz archive: https://mysite.com/my-custom-template-0.8.2.tgz
      - a .tar.gz archive: https://mysite.com/my-custom-template-0.8.2.tar.gz

    If you have any problems, do not hesitate to file an issue:

创建React应用程序

npx create-react-app {appName}
或
create-react-app {appName}

FAQ : React

Q: create-react-app my-app时,报npm同级依赖(peer dependency)错误:"While resolving: my-app@0.1.0 Found: react@19.0.0 ... Could not resolve dependency: peer react@"^19.0.0 ... " from the root project"(版本冲突/同级依赖与无法解析依赖树问题)

  • 问题描述
$ create-react-app my-app

Creating a new React app in D:\Workspace\CodeRepositories\react-app\my-app.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template...


added 1323 packages in 58s

266 packages are looking for funding
  run `npm fund` for details

Initialized a git repository.

Installing template dependencies using npm...
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: my-app@0.1.0
npm ERR! Found: react@19.0.0
npm ERR! node_modules/react
npm ERR!   react@"^19.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^18.0.0" from @testing-library/react@13.4.0
npm ERR! node_modules/@testing-library/react
npm ERR!   @testing-library/react@"^13.0.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR!
npm ERR! For a full report see:
npm ERR! C:\Users\xxx\AppData\Local\npm-cache\_logs\2025-01-04T05_14_33_516Z-eresolve-report.txt

npm ERR! A complete log of this run can be found in: C:\Users\xxx\AppData\Local\npm-cache\_logs\2025-01-04T05_14_33_516Z-debug-0.log
`npm install --no-audit --save @testing-library/jest-dom@^5.14.1 @testing-library/react@^13.0.0 @testing-library/user-event@^13.2.1 web-vitals@^2.1.0` failed
  • 原因分析

这个错误表明你当前的项目发现package.json中声明的依赖组件react的版本为19.0.0,但正在尝试安装的@testing-library/react这个库又需要一个特定的同级依赖react@"^18.0.0",导致解析依赖树失败、安装失败。

  • 解决方法

参见: [nodejs] NPM 教程 - 博客园/千千寰宇
关键词:版本冲突 / 同级依赖 / 无法解析依赖树问题 / npm install xxxx --legacy-peer-deps

  • 参考文献

Y 推荐资源

  • 官网
  • 快速入门教程

https://react.docschina.org/learn
教程:井字棋游戏 | https://react.docschina.org/learn/tutorial-tic-tac-toe
React 哲学 | https://react.docschina.org/learn/thinking-in-react

  • 在线编辑与效果试验
  • React JS Download & CDN
  • React 官方

http://react-cn.github.io/react/downloads.html

<!-- 生产环境中不建议使用 | 在浏览器中使用 Babel 来编译 JSX 效率是非常低的 -->
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>

//development
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

<script src="https://fb.me/react-0.14.3.js"></script>
<script src="https://fb.me/react-dom-0.14.3.js"></script>

<script src="https://fb.me/react-with-addons-0.14.3.js"></script>
<script src="https://fb.me/react-dom-0.14.3.js"></script>


//production
<script src="https://fb.me/react-0.14.3.min.js"></script>
<script src="https://fb.me/react-dom-0.14.3.min.js"></script>

<script src="https://fb.me/react-with-addons-0.14.3.min.js"></script>
<script src="https://fb.me/react-dom-0.14.3.min.js"></script>

//npm方式
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(<App />, ...);
  • 字节跳动的 React CDN 库
react.js: React 的核心库,用于构建用户界面。
react-dom.js: 提供与 DOM 相关的操作,用于在浏览器中渲染 React 组件。
babel.js: 用于将 ES6+ 代码转换为向后兼容的 JavaScript 版本,确保代码在不同浏览器中的兼容性。
  • Staticfile CDN 的 React CDN 库
<script src="https://cdn.staticfile.org/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/18.2.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script src="path/to/babel.js"></script>
<script src="path/to/react.js"></script>
<script src="path/to/react-dom.js"></script>
  • React 开发者工具

使用 React 开发者工具检查 React components,编辑 props 和 state,并识别性能问题。

  • 浏览器扩展: 调试 React 构建的网站最简单的办法就是安装 React 开发者工具浏览器扩展。它可用于几种流行的浏览器:

现在,如果你访问一个用 React 构建 的网站,你将看到 ComponentsProfiler 面板。

  • Safari 和其他浏览器 : 略

https://react.docschina.org/learn/react-developer-tools

  • 移动端(React Native):略

https://react.docschina.org/learn/react-developer-tools

X 参考文献

posted @ 2025-01-04 11:17  千千寰宇  阅读(37)  评论(0编辑  收藏  举报