当前位置: 首页 > article >正文

【React+ts】 react项目中引入bootstrap、ts中的接口

一、在react项目中引入bootstrap

这个直接用npm下载包然后在index.js中引入就可以了。

npm install bootstrap react-bootstrap

后面那个必须要下载,应该有什么联动的包要用。
然后在index.tsx中引入

import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap";

二、ts中的interface接口

2.1 对象类型接口

ts中的interface是用来描述对象或函数的。是一种代码协作必须遵守的契约。我的理解就是规范里面的数据,比如说,在实例化的时候哪些东西必须要,哪些东西可以不要,以及哪些东西可以任意类型。
里面的数据可以定义以下几种类型。

  1. 确定类型:必须要有的数据。
  2. 可选属性:可以没有的属性。
  3. 任意属性:说明属性类型可以更改,名字可定义。
  4. 只读属性:实例化后不可更改。
interface Person {
    age: number,           // 确定属性
    name?: string,         // 可选属性(加问号即可)
    [propName: string]: any, // 任意属性
    readonly sex: string,  // 只读属性
}

2.2 函数类型接口

列出参数列表和返回值类型的定义。

// 函数类型接口
interface Func {
    // 定义接收两个必选 number 类型参数,和一个可选字符串参数 desc,该函数返回 number 类型
    (x: number, y: number, desc?: string): number
}

三、react中定义组件的方式

有两种定义组件方式,一种是函数式组件,一种是类式组件。

3.1函数式组件

//基本定义方式
import React from "react";
 
export default function Discovery() {
  return <div>发现页</div>;
}

//组件传参数
import React from "react";
 
export default function Discovery(props: any) {
  console.log(props);
  return <div>{props.text}</div>;
}


//类型定义,说明是个函数式组件也可以简写FC
import React, { memo } from "react”;
Import type {FunctionComponent} from "react”;
 
const Discovery: FunctionComponent<any> = (props) => {
  console.log(props);
  return <div>{props.text}</div>;
};

//memo函数的作用是判断组件是否发生变化,如果没有发生变化则不重新渲染
export default memo(Discovery);

3.2 类式组件

//基本定义方式
import React, { Component } from "react";
 
class Discovery extends Component {
  render() {
    return <div>发现页</div>;
  }
}
 
export default Discovery;

//类式组件传参
import React, { Component } from "react”;
//这里两个any定义的一个是props type,一个是state type
 
class Discovery extends Component<any, any> {  
  constructor(props: any) {
    super(props);
    console.log(props);
    this.state = { text: props.text };
  }
  render() {
    return <div>{this.props.text}</div>;
  }
}
export default Discovery;

3.3interface与类式组件的互动

ReactNode和ReactElement 与 children属性
这里的ReactNode包含了ReactElement,如下图所示。
在这里插入图片描述
InterfaceTest.tsx

import React, { ReactNode } from "react";
 
interface Iprops {
  name: string;
  age: number;
  children: ReactNode;
  height?: number;
}
 
export default function InterfaceTest(props: Iprops) {
  return (
    <div>
      <div>name:{props.name}</div>
      <div>age:{props.age}</div>
      {/* 三目运算符来条件渲染 */}
      {props.height ? <div>height:{props.height}</div> : null}
      <div>{props.children}</div>
    </div>
  );
}

Discovery.tsx

import React, { Component } from "react";
import InterfaceTest from "./InterfaceTest";
class Discovery extends Component<any, any> {
  constructor(props: any) {
    super(props);
    console.log(props);
    this.state = { text: props.text };
  }
 
  render() {
    return (
      <div>
        {this.props.text}
        <InterfaceTest name="Carling" age={21} height={187}>
          <div>这里是子元素</div>
        </InterfaceTest>
      </div>
    );
  }
}
 
export default Discovery;

在这里插入图片描述

3.4代码中遇到的问题

(1)如果是类组件,子组件是否重新渲染由props和state决定;如果子组件是函数式组件,那么只要父组件渲染,子组件就会无条件进行渲染。
answer:使用memo函数对组件进行包裹。这个方法只能解决子组件属性不是函数时的情况,如果子组件是函数,则需要使用useCallback进行包裹。

这个问题出现的原因是因为,函数式组件每次重新渲染时,都会把函数体里的所有代码执行一遍。
useCallback函数

let newFunction = useCallback(oldFunction,[dependentValue])

我的理解是只有当后面的依赖值发生变化时,前面的函数才会被运行。否则返回一样的值。
因此如果传的是空数组则oldFunction只会被定义一次。

export default () => {
    console.log("父组件");
    const [count, setCount] = useState(1);

    let changeCount = () => {
        setCount(count + 1);
    }

    let increment = useCallback(()=>{
        console.log("increment");
    },[]) // 该函数永远不会重新定义(没有依赖)
    
    return (
        <>
            <h1>useCallback</h1>
            <p>{count}</p>
            <input type="button" value="修改count" onClick={changeCount} />
            <hr/>
            <SonFn onMyClick={increment} />
        </>
    )
}

四、组件的懒加载–webpack中的分包处理,性能优化问题–哪个需要查看下载哪个。

这个的原理就是将所有组件拆分,不放在一个文件里,哪个需要被加载去服务器下载哪个文件。
这里使用的是react库中的lazy函数,用来引入组件。
路由表定义:

import React, { lazy } from "react";
import { Navigate } from "react-router-dom";
 
//懒加载定义
const Discovery = lazy(() => import("../components/Discovery"));
const My = lazy(() => import("../components/My"));
const Follow = lazy(() => import("../components/Follow"));
const Mall = lazy(() => import("../components/Mall"));
const Musician = lazy(() => import("../components/Musician"));
const Recommended = lazy(() => import("../components/Recommended"));
const Download = lazy(() => import("../components/Download"));
 
const routes: any[] = [
  {
    path: "/discovery",
    element: <Discovery text="发现页" />,
  },
  {
    path: "/my",
    element: <My />,
  },
  {
    path: "follow",
    element: <Follow />,
  },
  {
    path: "mall",
    element: <Mall />,
  },
  {
    path: "musician",
    element: <Musician />,
  },
  {
    path: "recommended",
    element: <Recommended />,
  },
  {
    path: "download",
    element: <Download />,
  },
  {
    path: "/",
    element: <Navigate to="/discovery" />,
  },
];
export default routes;

使用路由表的时候要用Suspense组件进行包裹,Suspense组件是通过捕获异常来进行实现的,没看之前猜测是,捕获到异常就暂停该组件的渲染,等到完成再渲染。
工作原理:
使用React的Fiber架构进行实现。Fiber架构允许React将渲染工作拆分为一个个可中断的任务单元。当遇到需要暂停的操作时,Fiber可暂停当前任务,并显示fallback—Suspense组件中定义的在等待时渲染的过渡组件。

  1. 当组件抛出异常时,React标记该Fiber节点为“suspended”状态
  2. 触发重新渲染,一旦该Promise完成,React会尝试重新渲染组件。
  3. 等待Promise完成的期间会渲染fallback。
    用Suspense组件将所有懒加载的组件全包裹了就可以。
import React, { Suspense } from "react";
import routes from "./router/index";
import { NavLink, useRoutes } from "react-router-dom";
 
function App() {
  const element = useRoutes(routes);
  return (
    <div className="App">
      <nav className="navbar navbar-dark bg-primary">
        <div className="container-fluid">
          <NavLink className="navbar-brand" to="/discovery">
            发现音乐
          </NavLink>
          <NavLink className="navbar-brand" to="/my">
            我的音乐
          </NavLink>
          <NavLink className="navbar-brand" to="/follow">
            关注
          </NavLink>
          <NavLink className="navbar-brand" to="/mall">
            商城
          </NavLink>
          <NavLink className="navbar-brand" to="/musician">
            音乐人
          </NavLink>
          <NavLink className="navbar-brand" to="/recommended">
            云推歌
          </NavLink>
          <NavLink className="navbar-brand" to="/download">
            下载客户端
          </NavLink>
        </div>
      </nav>
      <Suspense fallback="loading…">
        {element}
      </Suspense>
    </div>
  );
}
 
export default App;

http://www.kler.cn/a/520594.html

相关文章:

  • Semantic Kernel - Kernel理解
  • Golang Gin系列-9:Gin 集成Swagger生成文档
  • 自签证书的dockerfile中from命令无法拉取镜像而docker的pull命令能拉取镜像
  • 动手学图神经网络(3):利用图神经网络进行节点分类 从理论到实践
  • 2024年度总结(具身智能赛道,欢迎交流)
  • 【Postman接口测试】Postman的全局变量和环境变量设置
  • JavaScript使用toFixed保留一位小数的踩坑记录:TypeError: xxx.toFixed is not a function
  • vue3中customRef的用法以及使用场景
  • LeetCode题练习与总结:两个字符串的删除操作--583
  • 9.4 GPT Action 开发实践:从设计到实现的实战指南
  • PoolingHttpClient试验
  • 独立游戏开发赚钱吗?
  • 从0到1:C++ 开启游戏开发奇幻之旅(一)
  • 重构(1)if-else
  • webview_flutter_android 4.3.0使用
  • java 字符串日期字段格式化前端显示
  • 并发操作下如何加锁,自动释放锁,异常情况可以主动释放锁
  • gitee——报错修改本地密码
  • 51单片机开发:独立键盘实验
  • 数据结构:log-structed结构MemTableSSTable
  • 代码工艺:实践 Spring Boot TDD 测试驱动开发
  • C#常考随笔2:函数中多次使用string的+=处理,为什么会产生大量内存垃圾(垃圾碎片),有什么好的方法可以解决?
  • SocketCAN
  • WebSocket 心跳机制:确保连接稳定与实时性
  • 【Rust自学】15.5. Rc<T>:引用计数智能指针与共享所有权
  • ubuntu 更新24LTS中断导致“系统出错且无法恢复,请联系系统管理员”