2023 Vue开发者的React入门

这篇具有很好参考价值的文章主要介绍了2023 Vue开发者的React入门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

2023 Vue开发者的React入门

VueReact 都是流行的 JavaScript 框架,它们在组件化、数据绑定等方面有很多相似之处

本文默认已有现代前端开发(Vue)背景,关于 组件化、前端路由、状态管理 概念不会过多介绍

0基础建议详细阅读 Thinking in React-官方文档 了解 React 的设计哲学

  • React 新文档- https://react.dev

  • React 中文文档(翻译中)- https://react.jscn.org

经过本文的学习让没开发过 React 项目的 Vue 开发者可以上手开发现有的 React 项目,完成工作需求开发

React 新文档

React 新文档重新设计了导航结构,让我们更加轻松地找到所需的文档和示例代码 不仅提供了基础知识的介绍,还提供了更加详细的原理介绍和最佳实践,包括:React 组件的设计哲学、React Hooks的原理和用法等

并且提供了在线编辑和运行的功能,方便开发者进行测试和实验

👇 基于 函数组件

2023 Vue开发者的React入门

初学可以只学 函数组件,You Don't Need to Learn Class Components

2023 Vue开发者的React入门

👇 interactive sandboxes 可交互沙箱,边做边学

2023 Vue开发者的React入门

Fork 可以单独打开页签

2023 Vue开发者的React入门

JSX 与 SFC

  • Vue 中我们使用 单文件组件(SFC) 编写组件模版 (虽然 Vue 也支持使用 JSX , 但是更鼓励使用SFC)

  • React 中,JSX(JavaScript XML)是一种将HTML语法嵌入到 JavaScript 中的语法扩展。它可以使得我们在 JavaScript 代码中轻松地定义组件的结构和样式,从而提高代码的可读性和可维护性

虽然 ReactVue 在组件定义方式上存在差异,但是它们的组件化思想是相似的

根节点

👇 Vue

<template>
  <div>同级节点1</div>
  <div>同级节点2</div>
</template>

👇 React

const App = (
  <>
    <div>同级节点1</div>
    <div>同级节点2</div>
  </>
)

const App = (
  <React.Fragment>
    <div>同级节点1</div>
    <div>同级节点2</div>
  </React.Fragment>
)

条件渲染

👇 Vue

<div v-if="show">条件渲染</div>
<div v-show="show">条件渲染</div>

👇 React

{
  show ? <div>条件渲染</div> : null
}

循环语句

👇 Vue

<ul>
  <li v-for="i in list" :key="i.id">{i.name}</li>
</ul>

👇 React

<ul>
  { list.map(i => <li key={i.id}>{i.name}</li>) }
</ul>

表单绑定

👇 Vue

<input v-model="value"/>

👇 React

<input value={value} onChange={onChange}/>

可以看出 ReactJSX语法 学习记忆成本更低一点(当然Vue也不复杂),Vue 更语法糖一些

单向数据流与双向绑定

Vue 中,我们使用 v-bindv-modal对数据进行绑定,无论是来自用户操作导致的变更,还是在某个方法里赋值都能够直接更新数据,不需要手动进行 update 操作

this.data.msg = '直接修改数据后视图更新'

React 中,数据流是单向的,即从父组件传递到子组件,而不允许子组件直接修改父组件的数据。需要调用set 方法更新,当 React 感应到 set 触发时会再次调用 renderdom 进行刷新

msg = "Hello" // ❌ 错误写法

setMsg('Hello'); // ✅ 来自hooks的set写法 后面会介绍

🤔 Vue 本质上底层也是单向的数据流,只不过对使用者来说看起来是双向的,如 v-model 本质也要 set

React Hooks

React HooksReact 16.8 版本中引入的特性,它可以让我们在 函数组件 中使用状态(state)和其他 React 特性

Hooks 本质是一些管理组件状态和逻辑的 API ,它允许开发者在 函数式组件 中使用状态、副作用和钩子函数,可以更加方便地管理组件状态、响应式地更新DOM、使用上下文等

在没有 Hooks 前, 函数组件 不能拥有状态,只能做简单功能的UI(静态元素展示),大家使用 类组件 来做状态组件

因为 函数组件 更加匹配 React 的设计理念 UI = f(data),也更有利于逻辑拆分与重用的组件表达形式,为了能让 函数组件 可以拥有自己的状态,Hooks 应运而生

组件的逻辑复用

Hooks 出现之前,React 先后尝试了 mixins混入HOC高阶组件render-props等模式。但是都有各自的问题,比如 mixins 的数据来源不清晰,高阶组件的嵌套问题等等

class组件自身的问题

class组件就像一个厚重的‘战舰’ 一样,大而全,提供了很多东西,有不可忽视的学习成本,比如各种生命周期,this指向问题等等

useState

参数接受一个默认值,返回 [value, setValue] 的元组(就是约定好值的 JavaScript 数组),来读取和修改数据

👇 不使用 Hooks 的静态组件,当点击修改数据,视图不会重新渲染

function App() {
  let count = 1
  const add = () => count++ // 不会触发重新渲染

  return <div onClick={add}>{count}</div>
}

👇 使用 useState

import { useState } from 'react'

function App() {
  let count = 1
  const [proxyCount, setProxyCount] = useState(count)
  const add = () => setProxyCount(proxyCount+1)

  return <div onClick={add}>{proxyCount}</div>
}

我们分析一下触发数据修改的 函数组件行为

组件会第二次渲染(useState 返回的数组第二项 setProxyCount() 被执行就会触发重新渲染)

  1. 点击按钮,调用 setProxyCount(count + 1) 修改状态,因为状态发生改变,所以,该组件会重新渲染

  2. 组件重新渲染时,会再次执行该组件中的代码逻辑

  3. 再次调用 useState(1),此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 2

  4. 再次渲染组件,此时,获取到的状态 count 值为 2

👆 也就是触发重新渲染会让 useState 也重新执行,但是 useState 的参数(初始值)只会在组件第一次渲染时生效

每次的渲染,useState 获取到都是最新的状态值,React 组件会记住每次最新的状态值

useEffect

上面我们分析触发组件重新渲染就可以发现,React 的函数组件没有具体的生命周期钩子

React 更希望我们把组件当作函数,而去关注函数的函数的副作用,而没有实例化过程的钩子

useEffect 就可以很好的帮助我们达到我们想要的效果:

  1. 处理组件第一次渲染时的回调,类似 Vue 中的 mounted

// 第二个参数传一个空数组,表示没有依赖,只会在第一次渲染时执行
useEffect(() => {
  alert('mounted');
}, [])
  1. 通过依赖变更触发的钩子函数,只要有一项依赖发生变化就执行,类似 Vue 中的 watch

function Comp({ title }) {
  const [count, setCount] = useState(0);
  // 第二个参数指定一个数组,放入你想监听的依赖:
  useEffect(() => {
    console.log('title or count has changed.')
  }, [title, count])
}

原则上,函数中用到的所有依赖都应该放进数组里

  1. 组件卸载时执行内部 return 的函数

import { useEffect } from "react"

const App = () => {

  useEffect(() => {
    const timerId = setInterval(() => {
      console.log('定时器在运行')
    }, 1000)

    return () => { // 用来清理副作用的事情
      clearInterval(timerId)
    }
  }, [])

  return <div>内部有定时器</div>
}

我们常见的副作用 1. 数据请求ajax发送 2. 手动修改dom 3. localstorage操作

自定义 Hooks

获取滚动距离y:

import { useState, useEffect } from "react"

export function useWindowScroll () {
  const [y, setY] = useState(0)

  useEffect(() => {
    const scrollHandler = () => {
      const h = document.documentElement.scrollTop
      setY(h)
    }
    window.addEventListener('scroll', scrollHandler)
    return () => window.removeEventListener('scroll', scrollHandler)
  })

  return [y]
}

使用:

const [y] = useWindowScroll()
return <div>{y}</div>
2023 Vue开发者的React入门

封装的 Hooks 名称也要用 use 开头(这是一个约束)

状态管理

React状态管理 有很多,入门可以暂时不考虑

或者已有项目使用什么再学习即可,和 Vuex 整体思路差不多

tic-tac-toe 井字棋游戏

最后我们跟着 React 官方文档实现一个井字棋游戏来巩固知识点

使用 Vite 创建项目

2023 Vue开发者的React入门
pnpm create vite react-tic-tac-toe --template react
cd react-tic-tac-toe
pnpm i
pnpm dev

👇 vite.config.js 非常简洁

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
})

👇 修改入口文件 main.jsx

import React, { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";

import App from "./App";

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

👇 util.js 计算当前棋局是否有获胜

// 计算当前棋局是否有获胜
export function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

👇 Square.jsx 正方形按钮组件

// 正方形按钮组件
export default function Square({ value, onSquareClick }) {
  return (
    <button className="square" onClick={onSquareClick}>
      {value}
    </button>
  );
}

👇 App.jsx

import { useState } from 'react';
import { calculateWinner } from './util.js'
import Square from './Square'

function Board({ xIsNext, squares, onPlay }) {
  function handleClick(i) {
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = 'X';
    } else {
      nextSquares[i] = 'O';
    }
    // 执行父组件的落子事件
    onPlay(nextSquares);
  }

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    // 胜利提示
    status = '获胜方是: ' + winner;
  } else {
    // 下一步提示
    status = 'Next player: ' + (xIsNext ? 'X' : 'O');
  }

  return (
    <>
      <div className="status">{status}</div>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
        <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
        <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
        <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
        <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
        <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
        <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
      </div>
    </>
  );
}

export default function Game() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [currentMove, setCurrentMove] = useState(0);
  const xIsNext = currentMove % 2 === 0;
  const currentSquares = history[currentMove];

  // 棋盘落子
  function handlePlay(nextSquares) {
    const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
    // 记录落子历史,用于恢复棋局
    setHistory(nextHistory);
    setCurrentMove(nextHistory.length - 1);
  }

  // 恢复棋局到第几步
  function jumpTo(nextMove) {
    setCurrentMove(nextMove);
  }

  // 历史落子列表按钮展示,用于点击恢复棋局
  const moves = history.map((squares, move) => {
    let description;
    if (move > 0) {
      description = 'Go to move #' + move;
    } else {
      description = 'Go to game start';
    }
    return (
      <li key={move}>
        <button onClick={() => jumpTo(move)}>{description}</button>
      </li>
    );
  });

  return (
    <div className="game">
      <div className="game-board">
        <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
      </div>
      <div className="game-info">
        <ol>{moves}</ol>
      </div>
    </div>
  );
}
2023 Vue开发者的React入门

深入学习任一前端框架都不容易,让我们一起加油吧!

参考资料

  • React 新文档- https://react.dev

  • React 中文文档(翻译中)- https://react.jscn.org

  • 给 Vue 开发的 React 上手指南- https://juejin.cn/post/6952545904087793678

  • 无缝切换?从Vue到React- https://zhuanlan.zhihu.com/p/609120596

  • How to Learn React in 2023- https://www.freecodecamp.org/news/how-to-learn-react-in-2023

想了解更多转转公司的业务实践,点击关注下方的公众号吧!文章来源地址https://www.toymoban.com/news/detail-451719.html

到了这里,关于2023 Vue开发者的React入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2023谷歌开发者大会直播大纲「终稿」

    听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,现任研发部门 CTO 。 荣誉: 2022年度博客之星Top4 、 博客专家认证、全栈领域优质创作者、新星计划导师 , “

    2024年02月10日
    浏览(50)
  • CodeGeeX荣获2023稀土开发者大会“年度最佳开发工具”奖项

    XDC 2023稀土开发者大会6月30日在北京成功举办,今年大会主题为“代码不止,掘金不停”。除了为开发者提供多达60场+的技术分享之外,针对开发者使用的工具也展开了一系列的专业评选,这也是每年大家非常期待的环节。 开发工具是每个开发者每天都会使用的产品,深度影

    2024年02月11日
    浏览(54)
  • 紧密联结玩家 | 2023 Google 游戏开发者峰会

    玩家的选择是对游戏莫大的认可,重视玩家反馈并和他们建立联系是您的游戏取得成功的关键。我们也在努力创造更多机会,让您的游戏从琳琅满目的列表中脱颖而出,帮助您吸引更多用户。 上篇内容我们介绍了帮助您优化游戏性能的几大功能更新,今天的内容我们将剖析大

    2023年04月26日
    浏览(57)
  • 2023最新 如何修改appstroe的开发者名称?

    1、输入账号密码登录 http://itunesconnect.apple.com 2、点击app 3、点击我的账户account 4、页面往下滑动,点击更新信息 5、点击提供更新信息 6、根据需要修改新的信息 Hello, I want to change the company name in Chinese, according to changed to “xxx”, English name is changeless。 你好,我想更改公司中文

    2024年02月07日
    浏览(45)
  • 2023 Google 开发者大会:Web平台新动向

    在前不久的 2023 Google 开发者大会中,谷歌提出了更加强大且开放的 Web,并且还可以可以简化开发工作并支持 AI。Google 资深开发技术推广工程师兼 Chrome 开发技术推广部主管 Paul Kinlan 在 2023 Google 开发者大会讲解了 Google 推出的新功能,包括在 Web 开发值得重点关注的升级与成

    2024年02月08日
    浏览(89)
  • 2023 年开发者必须知道的 6 个 AI 工具

    自Chat GPT发布以来,AI在各个领域都出现了令人惊艳的产品,在编程方面也是如此。这些由 AI 驱动的工具使用算法快速准确地生成代码,从而节省程序员的时间和精力。虽然目前AI写出来的代码还不能完全替代人类,但开发人员完全可以作为一种辅助的工具。 通过使用深度学

    2024年02月11日
    浏览(41)
  • 2023 Google 开发者大会 – AI 领域的技术更新

    Google 开发者大会是 Google 面向开发者和科技爱好者展示最新产品和平台的年度盛会。2023 Google 开发者大会 (Google I/O Connect | China) 为开发者提供丰富的学习资源,实践操作和现场演示,提供与谷歌专家互动、与其他开发者交流的契机,助力开发提效,释放团队创造力,简化工作

    2024年02月08日
    浏览(55)
  • 2023年苹果IOS开发者证书申请(已实测准确)

    苹果开发者官网:https://developer.apple.com/ 注册苹果账号apple id 开启双重认证,需在一台IOS手机/iPad操作 在App Store下载Apple Developer APP ,进行注册开发者账号 去Apple Developer应用填写申请资料 绑定支付宝或者微信支付苹果年费(¥688元/年) 请等待苹果审核后,根据邮件提示,点击

    2024年02月07日
    浏览(62)
  • FlashDuty Changelog 2023-09-21 | 自定义字段和开发者中心

    FlashDuty:一站式告警响应平台,前往此地址免费体验! FlashDuty 已支持接入大部分常见的告警系统,我们将推送内容中的大部分信息放到了 Lables 进行展示。尽管如此,我们用户还是会有一些扩展或定制性的需求,比如人工标记一个故障是否为误报。因此我们提供了 自定义字

    2024年02月08日
    浏览(40)
  • 华为开发者大会2023:云空间筑牢鸿蒙生态“云基因”

    8月4日,华为开发者大会2023在东莞·松山湖举办,众多开发者及合作伙伴共赴盛会,见证鸿蒙生态的最新进展。在本届大会的HarmonyOS应用开发(端云能力)分论坛上,华为Drive Kit生态架构技术总监官宣云空间服务升级,赋能开发者高效开发,为鸿蒙生态应用注入“云基因”。

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包