npx create-react-app tsui 
cd tsui
yarn start
//React负责逻辑控制,数据 -> VDOM
import React from "react";
//ReactDom渲染实际DOM,VDOM -> DOM
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

// React JSX => React.createElement(...)
// babel-loader把JSX 编译成相应的 JS 对象,
// React.createElement再把这个JS对象构造成React需要的虚拟dom。
ReactDOM.render(<App />, document.getElementById("root"));

serviceWorker.unregister();

# jsx在react中

  • for循环用可以在jsx中使用arr.map代替,(注意 forEach,则不会返回数据 )
  • 过滤部分数据array.filter
  • if else 语句可以使用三目运算符代替
  • 函数调用可以直接写在jsx表达式中
  • if 判断的话可以依赖 && 运算符实现
  • 模块化module用来实现css不会相互干扰
  • CSS属性:静态值用双引号,动态值用花括号;class => className 、 for => htmlFor 等要特殊处理。
  • 需要最外层添加包裹标签,可以是<></>,JSX 虽然看起来很像 HTML,但在底层其实被转化为了 JavaScript 对象,你不能在一个函数中返回多个对象,除非用一个数组把他们包装起来。这就是为什么多个 JSX 标签必须要用一个父元素或者 Fragment 来包裹。
import React from "react";
import ReactDOM from "react-dom";
// import "./index.css";
import styles from "./index.module.css";
import logo from "./logo192.png";

const name = "React";
const obj = {
  fistName: "Harry",
  lastName: "Potter"
};
function formatName(name) {
  return name.fistName + " " + name.lastName;
}
const greet = <div>good</div>;
const show = true;
const a = [0, 1, 2];
const jsx = (
  <div className={styles.app}>
    <div>hello, {name}</div>
    <div>{formatName(obj)}</div>
    {greet}
    {show ? greet : "登录"}
    {show && greet}
    <ul>
      {/* diff时候,首先比较type,然后是key,所以同级同类型元素,key值必须得 唯一 */}
      {a.map(item => (
        <li key={item}>{item}</li>
      ))}
    </ul>
    <img
      src={logo}
      // className="logo"
      className={styles.logo}
      style={{ width: "50px", height: "30px" }}
    />
  </div>
);

ReactDOM.render(jsx, document.getElementById("root"));

//基本使用 表达式用{}包裹
//函数
//JSX对象
//条件语句
//数组
//属性
//模块化

# react constructor的使用

constructor 是类通用的构造函数,常用于初始化。所以在过去,constructor 通常用于初始化 state 与绑定函数。

import React from 'react'
class Counter extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0,
    }
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
     // do some stuff
  }
  render() {
     return null
  }
}

当类属性开始流行之后,React 社区的写法发生了变化,即去除了 constructor。

import React from 'react'
class Counter extends React.Component {
   state = {
      count: 0,
   }
// 类属性第三阶段提案
handleClick = () => {
// do some stuff
}
render() {
  return null
}

社区中去除 constructor 的原因非常明确:

  • constructor 中并不推荐去处理初始化以外的逻辑;
  • 本身 constructor 并不属于 React 的生命周期,它只是 Class 的初始化函数;
  • 移除 constructor,代码也会变得更为简洁。

# react路由表写法

import { BrowserRouter,HashRouter } from "react-router-dom";
import Router from "@/routers/index";

function App() {
  return (
    <HashRouter>
      <Router />
    </HashRouter>
  )
}

export default App

import { Navigate, useRoutes } from 'react-router-dom'
import LayoutCustom from '@/layouts/index'
import Login from '@/views/login/index'
import DigitalTwin from '@/views/digitalTwin/index'
import ProjectManage from '@/views/projectManage/index'

export interface MetaProps {
  keepAlive?: boolean
  requiresAuth?: boolean
  title: string
  key?: string
}

export interface RouteObject {
  caseSensitive?: boolean
  children?: RouteObject[]
  element?: React.ReactNode
  path?: string
  meta?: MetaProps
  isLink?: string
}

export const rootRouter: RouteObject[] = [
  {
    path: '/',
    element: <Navigate to="/login" />,
  },
  {
    path: '/login',
    element: <Login />,
    meta: {
      requiresAuth: false,
      title: '登录页',
      key: 'login',
    },
  },
  {
    element: <LayoutCustom />,
    children: [
      {
        path: '/digital/index',
        element: <DigitalTwin />,
        meta: {
          requiresAuth: true,
          title: 'home',
          key: 'digital',
        },
      },
    ],
  },
  {
    element: <LayoutCustom />,
    children: [
      {
        path: '/project/scene/:ID/:Name',
        element: <ProjectManage />,
        meta: {
          requiresAuth: true,
          title: '项目管理',
          key: 'digital',
        },
      },
    ],
  }
]

const Router = () => {
  const routes = useRoutes(rootRouter)
  return routes
}
export default Router

# useRoutes

useRoutes是一个React的钩子(Hook),它允许您在函数组件中使用路由。它是React Router v6中引入的新功能,用于替代传统的React Router v5中的组件。

# outlet子路由渲染

在 react-router-dom 中,Outlet 是一个用于渲染子路由的组件。当用户导航到一个子路由时,Outlet 会渲染对应的子路由组件。

import { Outlet } from "react-router-dom";
import { Layout } from "antd";

import LayoutHeader from "./components/Header";
import SiderMenu from "./components/SiderMenu";
import "./index.scss";

const LayoutCustom = () => {
	const { Content } = Layout;
	return (
		<section className="container">
			<LayoutHeader></LayoutHeader>
			<Layout>
				<SiderMenu></SiderMenu>
				<Content>
					<Outlet></Outlet>
				</Content>
			</Layout>
		</section>
	);
};

export default LayoutCustom;

# reactdom

自 React v0.14 开始,官方将与 DOM 相关的操作从 React 中剥离,组成单独的 react-dom库,从而让 React 能兼容更多的终端。在引入 react-dom 库后,就能调用一个全局对象:ReactDOM。

ReactDOM只包含了unmountComponentAtNode()、findDOMNode()、createPortal()和render()等为数不多的几个方法。

  1. findDOMNode():当组件被渲染到页面真实的 DOM 中后,就能通过 findDOMNode()方法得到生成的 DOM 元素,然后就能完成诸如读值和计算尺寸等操作。注意,findDOMNode()只能获取已挂载的组件,并且不能用于函数组件。在组件的生命周期中,它只能存在于 componentDidMount()和 componentDidUpdate()两个回调函数中,在其他地方调用会抛出一个错误,具体如下所示。(官方不推荐使用,未来版本移除)
class Btn extends React.Component {
 render() {
  ReactDOM.findDOMNode(this); //抛出错误
  return <button>提交</button>;
 }
 componentDidMount() {
  ReactDOM.findDOMNode(this); //<button>提交</button>
 }
}

在上面的示例中,this 指向的是 Btn 组件实例,在将 this 传给 findDOMNode()方法后,得到了一个<button>元素。有一点要注意,如果组件中的 render()返回 null 或 false,那么findDOMNode()只会返回 null。

  1. createPortal():在 React v16 中,新增了 Portal 特性,能让组件渲染到父组件以外的DOM 节点中。这个特性适用于需要跳出容器的场景,例如,创建页面内定制的弹框。在 React 中使用 Portal 特性,需要调用 ReactDOM 上的一个新方法:createPortal()。此方法能接收两个参数,第一个参数是可渲染的 React 子元素,例如,字符串或 React 元素数组等;第二个参数是 DOM 元素,也就是要挂载的容器。关于这个方法的具体使用可参考下面的示例。
class Btn extends React.Component {
 render() {
 return ReactDOM.createPortal(this.props.children, document.body);
 }
}
ReactDOM.render(<Btn><p>按钮</p></Btn>, document.getElementById("container")); 
  1. unmountComponentAtNode:此 API 将在未来的 React 主要版本中被移除。在 React 18, unmountComponentAtNode 已被 root.unmount() 取代.

unmountComponentAtNode 用于从 DOM 中移除一个已挂载的 React 组件。 unmountComponentAtNode(domNode)

# 常见插件

  1. Formik 是一个用于 React 的小型表单库,提供了验证、跟踪表单状态和处理表单提交等功能,让表单的测试和重构变得轻而易举。
  2. Relay 是一个用于 React 的 GraphQL 客户端框架,它提供了一种声明式方式来处理数据,并自动管理缓存和数据更新。
  3. immer或者其他use-immer类库.方便修改setState生成的对象只想改很少的部分。
最后更新: 3/4/2025, 7:13:47 PM