React-peng

React-peng

React

react 是 Facebook 出的一款针对视图层的 library 库,主要作用是做页面处理。可以让我们一个项目页面拆分成一个一个组件进行管理

官网地址

<!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>模板</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="./libs/babel.min.js"></script>
    <script src="./libs/react.development.js"></script>
    <script src="./libs/react-dom.development.js"></script>
    <script type="text/babel">
      const root = ReactDOM.createRoot(document.querySelector("#root"));

      const App = () => (
        <>
          <h1>这是一个组件</h1>
        </>
      );

      root.render(<App />);
    </script>
  </body>
</html>

React 基础语法和常见 API

jsx 语法

所谓 jsx 语法,就是在 js 中直接写 html 标签

如果需要展示富文本内容,可以使用以下方式

{
  /* dangerouslySetInnerHTML设置一个富文本内容,通过设置属性__html实现 */
}
<div dangerouslySetInnerHTML={{ __html: strHtml }}></div>;

function 定义组件

组件的属性或者状态数据改变之后,组件都会重新渲染。即组件的这个 function 会被重新执行。

const Person = ({ children }) => {
  return (
    <div className="person">
      <h1>天才威</h1>
      <p>一个倒霉的天才发明家,明明可以改变世界,但是却被两头熊给破坏了</p>
      {children}
    </div>
  );
};

需要注意的地方:

  1. 组件名字必须大写
  2. 每一个组件都需要返回一个值,这个值表示组件展示的内容

组件传参

  1. 父传子,使用 props 属性
  2. 子传父,使用方法调用
  3. 非相关组件传参,使用 context 上下文或者 redux

常见 hooks

function 定义的组件又叫无状态组件,但是在 react16.8 之后新增了 hooks api,可以让我们在 function 定义的组件中模拟局部状态数据和生命周期钩子函数。

注意:hooks 不能写在循环语句或者条件表达式中,因为 hooks 实现的原理是使用了数组结合闭包,如果放在循环或者条件语句中就没办法判断 hooks 的顺序了。所以 hooks 只能放在组件的最外层进行定义,不能放在循环语句或者条件判断中。hooks 只能在 function 定义的组件内使用

useState

useState 的作用是定义一个局部状态数据,接收一个默认值作为参数,返回一个数组。数组的第一项表示我们可以用来获取状态数据的变量名,第二项表示改变状态数据的方法

const [count, setCount] = React.useState(0);
// 状态数据的改变,只能调用setCount方法实现
//  setCount可以接收两种形式的参数
//  1. 直接是一个值
//  2. 接收一个function作为参数,function的返回值表示数据的最新值。function默认接收数据上一次的最新值作为参数

// setCount(3) // 设置值为3

// setCount((v)=>v+1) // v表示上一次的最新值,v+1这个返回值会作为改变之后的最新值

useEffect

useEffect 翻译成中文就是副作用的意思,可以接收两个参数。参数一是一个回调函数,参数二是一个依赖数组。当参数二中的数据改变的时候,回调函数会重新执行。

参数二有三种常见的形式

  1. 参数二为一个空数组,那么参数一的回调函数在组件初始化多的时候只执行一次
  2. 参数二的数组中存在数据,那么数组的每一项发生改变的时候,回调函数都会执行
  3. 参数二如果不存在(只有第一个回调函数),那么每一次组件重新渲染的时候,回调函数都会执行。这种情况不能在回调函数中改变 state 数据,会引起死循环

参数一的回调函数,可以返回一个 function,这个返回的方法在组件销毁的时候执行

React.useEffect(() => {
  //
  return () => {
    // 这个方法会在组件销毁的时候执行
  };
  // OR
  // return function () {
  //   // 这个方法会在组件销毁的时候执行
  // };
}, []);

memo

memo 的作用是对组件做性能优化,当组件接收的数据不改变的时候,组件不会重新渲染。在开发的时候建议多使用

const Item = (props) => {
  return <>...</>;
};

const MemoItem = React.memo(Item); // 对Item组件做缓存,当组件接收的属性不改变的时候,组件不会重新渲染

useMemo

作用缓存一个值,他接收的第二个参数是一个依赖数组。当依赖的数据不改变的时候缓存的值不会重新计算

useMemo 和 useCallback 的区别,useCallback 缓存的是一个 function,useMemo 缓存的是一个值

在组件性能优化的时候使用

useRef

作用是获取 dom 元素

受控组件和非受控组件,组件的值被 state 数据进行控制管理,那么这个组件就是受控组件;如果组件的值在需要使用的时候通过 dom 直接获取,这种组件就是非受控组件

useCallback

作用是缓存一个 function,他接收的参数形式和 useEffect 很像。第一个参数是一个函数,表示我们要缓存的方法;第二个参数是依赖项。当依赖项的数据改变之后,被缓存的方法会重新执行

在组件性能优化的时候使用

useContext

作用是实现跨组件之间传参

useReducer

useReducer 是另一种数据存储的方案,使用的是类似 redux 中单向数据流的实现思路。

// useReducer接收两个参数,返回一个数组(第一项是最新的状态数据,第二项是dispatch方法)
//  参数一 是一个reducer函数
//    这个函数接收两个参数,返回一个最新的状态数据
//      参数一 是状态数据的值
//      参数二 是一个action,里面包含两个属性type和payload
//  参数二 是一个初始状态
//  reducer中的数据改变只能通过dispatch派发一个action实现
const [state, dispatch] = React.useReducer((state, action) => {
  // 根据action中type不一样做不同的操作进行数据改变
  switch (action.type) {
    case "PLUS":
      return { ...state };
    default:
      return state;
  }
  // return state;
}, initState);

class 定义组件

class 定义组件是另一种定义组件的方法,目前虽然官方推荐的是 function 定义组件,但是大写也需要了解 class 的写法。

<!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>模板</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="./libs/babel.min.js"></script>
    <script src="./libs/react.development.js"></script>
    <script src="./libs/react-dom.development.js"></script>
    <script type="text/babel">
      const root = ReactDOM.createRoot(document.querySelector("#root"));

      // class定义组件,可以继承再
      //  Component或者PureComponent
      //  Component和PureComponent的区别:PureComponent定义的组件已经做过优化,
      //    它会对组件接收到的数据或者状态数据做浅比较,但是Component进行的是深度比较
      //    建议大家使用PureComponent定义组件,在性能上会更好一些
      // class定义的组件可以有自己的局部状态和生命周期钩子函数
      // class定义的组件和function定义的组件可以混合使用
      class Counter extends React.Component {
        // 都需要包含一个render方法,表示当前组件显示的html内容
        // 直接定义state
        // state = { count: 1, name: "这是一个计数器" };

        // 或者在构造函数中定义
        constructor(props) {
          super(props);
          this.state = {
            count: 1,
            name: "这是一个计数器",
          };
        }

        // 如果要改变数据,使用setState实现
        //  setState是异步的,我们可以接收第二个回调函数来获取最新的数据
        // 当组件的状态数据或者属性改变的时候,render函数都会重新执行
        render() {
          return (
            <>
              <h1>{this.state.name}</h1>
              <button
                onClick={() => {
                  this.setState(
                    {
                      count: this.state.count + 1,
                    },
                    () => {
                      console.log("新的count为:" + this.state.count);
                    }
                  );
                  console.log(this.state.count);
                }}
              >
                改变---{this.state.count}
              </button>
            </>
          );
        }
      }

      const App = () => (
        <>
          <Counter />
        </>
      );

      root.render(<App />);
    </script>
  </body>
</html>
  • 如何定义

    通过继承自 Component 或者 PureComponent 实现。他们两个的区别是:PureComponent 已经针对组件的 shouldComponentUpdate 函数做了优化,在进行属性和数据比较的时候只进行浅比较。相对来说性能更好,建议大家在开发的是使用 PureComponent 定义组件

  • 状态数据和改变

    class 定义的组件有自己的局部状态和生命周期钩子函数。我们可以直接在 class 中定义 state 或者在构造函数中定义

    改变 state 数据的时候使用 setState 方法,这个方法是异步的。数据改变之后没办法实时获取最新的数据,可以使用参数二的回调函数获取最新值

  • 组件传参

    • 父传子,使用 props 属性
    • 子传父,使用方法调用
    • 非相关组件,使用 context 上下文或者 redux
  • refs

    refs 可以获取组件中设置了 ref 属性的标签

  • contextType

    为 class 定义的组件设置了 contextType 之后,就可以在组件内部直接使用 this.context 获取 context 中的 value 数据

  • 组件生命周期

    1. react 组件生命周期钩子函数中 16.3 之前和之后的区别(作为了解)

      react16.3 之后删除了几个 will 开头的生命周期钩子函数,新增了几个获取状态和属性的函数。删除了 componentWillMount、componentWillReceiveProps、componentWillUpdate,新增了 getDerivedStateFromProps 和 getSnapshotBeforeUpdate 方法

    2. react class 组件中在什么时候调接口获取数据?为什么?

      在 componentDidMount 这个钩子函数中调接口获取数据。组件挂载成功之后调接口获取数据,因为数据获取是异步的,数据改变之后组件会重新渲染。我们需要在组件创建成功之后再获取数据,重新更新组件,要不然会引起页面更新不完全的情况

    3. react class 定义的组件如何做优化?

      1. 定义组件的时候继承子 pureComponent
      2. 在 shouldComponentUpdate 方法中做判断,如果改变的属性或者数据不需要在页面上显示,我们可以返回 false,那么组件更新阶段的生命周期钩子函数就不会执行(组件就不会重新 render 渲染)
    4. class 定义组件的生命周期钩子函数和 useEffect 如何对应的

      1. componentDidMount 和 useEffect 参数二为空白数组的时候对应
      2. componentDidUpdate 和 useEffect 参数二中存在数据的时候对应
      3. componentWillUnmount 和 useEffect 参数一的回调函数中的返回函数对应
    5. 嵌套组件的生命周期钩子函数执行顺序

      执行到父组件的 componentWillMount 之后,开始执行 render 解析 dom 元素,如果解析到子组件,那么执行子组件从创建到挂载完成的生命周期钩子函数。当所有的子组件都挂载完成之后执行父组件的挂载完成


    • constructor(初始化)
    • componentWillMount(组件挂载之前)
    • componentDidMount(组件挂载完成)【重要】,组件挂载成功之后执行,常常用来调接口取数据
    • componentWillReceiveProps(组件接收到新的属性)
    • shouldComponentUpdate(组件是否需要更新)【重要】,组件优化的时候使用。返回一个 bool 值,为 true 会执行更新阶段的函数,为 false 不会执行更新
    • componentWillUpdate(组件将要更新)
    • componentDidUpdate(组件更新完成)
    • componentWillUnmount(组件销毁)【重要】,组件销毁的时候需要删除没有完成的网络请求和清楚计时器等

脚手架项目和常用插件

官方脚手架

create-react-app 这个是 react 官方的脚手架。他很慢

npx create-react-app my-first-react-app # 创建一个react项目
cd my-first-react-app # 进入目录
npm start # 启动项目

官方脚手架搭建的项目内置了测试框架 jest,所有的*.test.js 都是测试文件

vite 直接创建项目

npm init vite@latest # 按照提示创建react项目就好

react 路由组件

react 路由

react 路由插件是你面试的时候百分百不会问的一个问题,但是这个插件很重要,需要你会用。每一个版本的路由,写法都有差异,所以没办法在面试的时候文

我们讲的 react 路由时 6.4 的版本

安装和使用

npm i react-router-dom # 安装

组件

  • HashRouter,路由组件的最外层组件。所有的路由插件都需要放在它里面
  • Route,每一个对应的地址展示的组件。需要 path 和 element 两个属性,path 表示路径、element 表示需要展示的组件
  • Link,生成链接,需要一个 to 属性(表示跳转到哪里去)。可以添加 replace 属性,表示跳转之后不会生成历史记录;添加 state 属性可以用来传递对象类型的复杂数据
  • NavLink,会自动的为当前标签添加选中样式

hooks

  • useLocation,可以获取当前的 location 数据,就是 url 中传递的信息

    • pathname,路径
    • search
    • state
  • useNavigate,可以实现编程式跳转

    const navigate = useNavigate();
    const toPage = () => {
      navigate("/detail", {
        // replace:true, // 设置为,表示不生成历史记录、替换当前路由
        // state: {}, // 传递的参数
      });
    };
    
  • xx

插件 qs

qs 插件可以把一个对象转换为一个 url 编码的参数,或者把一个 url 编码的参数转换为一个对象

GitHub - ljharb/qs: A querystring parser with nesting support

antd

antd 是蚂蚁金服出的一款 ui 组件库,主要用来做中后台管理系统

官网

国内镜像

npm i antd # 安装
npm i @ant-design/icons # 安装图标库

antd 使用的一个小坑

这个坑可以作为你面试找工作的时候的一个技术难点来讲。Modal 和 Form 组件结合使用的时候,设置了 destroyOnClose 也不会销毁 Form 中的数据,需要单独设置 Form 的 preserve 属性,官网有说明


<https://ant-design.antgroup.com/components/modal-cn/>

<Modal /> 和 Form 一起配合使用时,设置 destroyOnClose 也不会在 Modal 关闭时销毁表单字段数据,需要设置 <Form preserve={false} />

redux

redux 是一个状态管理插件,可以在任何一个框架里面使用,只做数据处理和存储。是一个遵循 Flux 架构的单向数据流的框架。单向数据流,数据是单向流动的,在 view 视图中通过 dispatch 派发一个 action 改变 state 数据,数据改变了之后视图重新渲染

redux 核心库

npm i redux
npm i react-redux # 这个插件的作用是实现react项目和redux数据的关联

redux-toolkit

是 redux 官方提供的一个工具包。RTK

npm install @reduxjs/toolkit # 安装

redux 常见面试点

  1. action 的 type 为什么不能重复,如何解决?

    因为 dispatch 派发之后,所有的 reducer 函数都会被触发,所以 action 的 type 不能重复,必须唯一,如果重复了就不知道改改变哪个数据了。为了解决这个问题,我们可以使用 symbol 设置 action 的 type 或者使用命名空间前缀的方式设置

  2. 如何把 redux 中的数据和组件进行关联 使用 react-redux 插件,通过 connect 方法或者 useSelector 实现,他们都接收一个回调函数作为参数,在这个回调函数中默认会传递所有的 state 数据作为参数。connect 可以在 function 或者 class 定义的组件中同时使用,但是 useSelector 只能在 function 定义的组件中使用

    高阶组件 :就是一个 function,接收一个组件作为参数,返回组件的时候为其添加新的属性和方法。常见的有:connect 和 withRouter 等

  3. redux 中的 action 必须返回一个 plain object(简单的数据类型),怎么处理异步操作?

    使用中间件 redux-thunk,这个插件只有几行代码,主要作用是判断 action 的类型,如果是一个对象,那么直接派发执行;如果是一个 function,那么会把 dispatch 方法当参数传递进去,然后进行派发

umi 企业级开发框架

蚂蚁金服的一款企业级开发框架,目前(2022-10-28)最新的版本是 4.x。官网

自行手动搭建

此方案简单粗暴

# 创建一个空目录
# 从3到4升级的变化,可以看这里 <https://umijs.org/docs/introduce/upgrade-to-umi-4>
npm init -y # 创建一个node项目
#
npm i @umijs/max # 安装依赖

# 修改package.json
#  配置启动项,添加
#  "dev": "max dev"

官方推荐的方法

# pnpm是nodejs的一个包管理工具,超级建议大家使用(在当前时间点2022-10左右)
# npm i pnpm -g # 全局安装pnpm,安装一次就好
pnpm dlx create-umi@latest # 使用pnpm搭建
pnpm dev # 启动项目

在 umi 中使用 sass,直接安装依赖就好,pnpm install sass

  • umi 代码生成器

    # <https://umijs.org/docs/guides/generator>
    # 可以快速的生成代码,执行 umi g xxx 命令就好
    # 执行 node_modules/.bin/umi g 就好
    node_modules/.bin/umi g page # 可以根据提示生成一个页面
    node_modules/.bin/umi g tailwindcss # 配置tailwindcss
    node_modules/.bin/umi g page # 配置dva插件
    
  • dva

    dva 是一个 redux 的封装,已经封装了各种 redux 常用插件,我们直接可以不需要做任何配置,在 umi 项目中进行使用

    在 umi 项目中会自动的解析 models 目录、pages/model 文件,为 redux 数据文件

    // 每一个model文件如下
    export default {
      namespace: "count", // 命名空间
      // 数据
      state: {
        num: 0,
      },
      // 同步改变数据
      reducers: {
        add(state: any) {
          state.num += 1;
        },
      },
      // 异步改变数据
      effects: {
        // generator生成器函数,是es6中的一个语法
        //  yield表示等待一个异步操作完成
        //  *表示这个函数中可以写yield
        //  直白的讲,可以拿来和async/await做对应
        *addAsync(_action: any, { put }: any) {
          yield 调接口获取数据;
          //  put 表示派发一个action,触发reducer重新执行
          yield put({ type: "add" });
        },
      },
    };
    

antd pro

官网

# 创建项目
npx @ant-design/pro-cli create xxx # 创建项目
cd xxx
npm i # 安装依赖
npm start
  • 配置

React 其他知识点

常见的其他 ui 组件库

  • MUI,是一个响应式布局的 ui 组件库
  • ionic,是一个做移动端开发的 ui 组件库。它应该是鼻祖,提供 angular、vue、react 版本

TailwindCSS

官网

这个是目前很流行的一个纯 css 库,可以让我们很方便的搭建页面.他是一个移动端优先的项目,可以在各种脚手架项目中使用

PostCSS,它是一个平台(是一堆插件的集合),其实我们一直在用,只是你不知道而已.他可以使用 js 帮我们处理 css 文件,最常见就是添加浏览器内核前缀

tailwindcss 在 vite 创建的项目中使用,参考官网

管理系统权限判断

  1. 系统设计

    角色权限信息表。

    可以通过用户的角色信息,知道这个用户可以访问哪些功能
    
    一个角色可以对应多个权限
    
    一个用户可以对应多个角色(大部分系统设计的都是一个用户只有一个角色)
    
  2. API 接口实现

    当用户登录成功之后,服务器端接口会返回给前端一个用户角色信息。前端可以根据这个角色信息,展示不同的页面导航效果

  3. 前端页面实现

    实现配置好所有的页面,为每一个页面添加好可以访问的角色信息。当用户登录之后,根据用户的角色显示不同的效果

Antv

官网,antv 是蚂蚁金服出的一套做数据可视化的解决方案

react 中使用 antv 插件

npm install @ant-design/charts --save # 安装

样式化组件

styled-components,可以让我们在定义组件的时候把样式和组件在一起写。 一个组件就是一个完整的文件,样式也在这里面直接写好了。使用它可以让我们用另一种方式开发组件

在 vscode 中使用的时候,建议大家安装插件 vscode-styled-components

npm i styled-components

ionic

官网,是一个 ui 组件库,可以用来做移动端开发。它可以实现根据我们的手机设备不一样,展示不同的效果。做出来的东西和原生 App 一致

react 项目中 css 的模块化引入

在 vite 创建的项目中可以使用命名 css 文件的之后在文件名中添加 module 关键词实现模块化引入

// import { Button, Space } from "antd-mobile";
// <https://cn.vitejs.dev/guide/features.html#css> css模块化预处理
import styles from "../home.module.scss"; // 在vite创建的项目中可以使用这种命名方式,实现css的模块化

function Home() {
  // console.log(styles);
  return (
    <>
      <p className={styles.title}>这是一段很长的文字</p>
    </>
  );
}

export default Home;

Next.js

一个 react 的服务器端渲染(SSR【Server Side Render】)框架。目前(2022-11)官网的最新版本是 13 的

【中文网站】

【官网】

npx create-next-app next-app-pre # 创建一个next项目
cd next-app-pre # 进入项目目录
npm run dev # 启动

它可以用来解决单页面应用程序没办法做 seo 的问题。我们用 next.js 做的项目生成的是多页面,可以在直接在每一个页面中添加 SEO 关键词

获取数据的方法:

  • getServerSideProps,是每一次请求页面的时候都会执行
  • getStaticPaths,是只有编译的时候执行一次
  • getStaticProps,只有编译的时候执行一次,结合 getStaticPaths 可以用来生成静态页面。便于我们项目的性能优化

在项目中使用 prisma

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值