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

一、在react项目中引入bootstrap

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

bash 复制代码
npm install bootstrap react-bootstrap

后面那个必须要下载,应该有什么联动的包要用。

然后在index.tsx中引入

typescript 复制代码
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap";

二、ts中的interface接口

2.1 对象类型接口

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

里面的数据可以定义以下几种类型。

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

2.2 函数类型接口

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

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

三、react中定义组件的方式

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

3.1函数式组件

typescript 复制代码
//基本定义方式
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 类式组件

typescript 复制代码
//基本定义方式
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

typescript 复制代码
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

typescript 复制代码
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函数

typescript 复制代码
let newFunction = useCallback(oldFunction,[dependentValue])

我的理解是只有当后面的依赖值发生变化时,前面的函数才会被运行。否则返回一样的值。

因此如果传的是空数组则oldFunction只会被定义一次。

typescript 复制代码
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函数,用来引入组件。

路由表定义:

typescript 复制代码
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组件将所有懒加载的组件全包裹了就可以。
typescript 复制代码
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;
相关推荐
程序员拂雨39 分钟前
Angular 知识框架
前端·javascript·angular.js
文静小土豆41 分钟前
K8S redis 部署
redis·kubernetes·bootstrap
GoodStudyAndDayDayUp1 小时前
gitlab+portainer 实现Ruoyi Vue前端CI/CD
前端·vue.js·gitlab
程序员阿明1 小时前
vite运行只能访问localhost解决办法
前端·vue
前端 贾公子1 小时前
uniapp -- 验证码倒计时按钮组件
前端·vue.js·uni-app
淡笑沐白1 小时前
AJAX技术全解析:从基础到最佳实践
前端·ajax
龙正哲2 小时前
如何在Firefox火狐浏览器里-安装梦精灵AI提示词管理工具
前端·firefox
徐徐同学2 小时前
轻量级Web画板Paint Board如何本地部署与随时随地在线绘画分享
前端
LuckyLay2 小时前
Vue百日学习计划Day4-8——Gemini版
前端·vue.js·学习
八戒社2 小时前
WooCommerce短代码Shortcodes使用方法
前端·wordpress·woocommerce