diff --git a/source/_posts/React.md b/source/_posts/React.md index 4cc30a7..2a3cc72 100644 --- a/source/_posts/React.md +++ b/source/_posts/React.md @@ -4,6 +4,434 @@ date: 2025-07-23 15:56:46 tags: --- +# Vue 转 React 指南 + +## JSX + +先介绍 React 唯一的一个语法糖:JSX。 + +理解 JSX 语法并不困难,简单记住一句话,遇到 `{}` 符号内部解析为 JS 代码,遇到成对的 `<>` 符号内部解析为 HTML 代码。 + +当你写下这个 React 组件时: + +```jsx +import React from 'react'; + +function MyComponent(props) { + return
{props.hello}
+} +``` + +最终会被自动工具翻译成: + +```jsx +import React from 'react'; + +function MyComponent(props) { + return React.createElement('div', null, props.hello); +} +``` + +React 就是通过这个小小语法糖,实现在 JS 里面写 HTML,可能有小伙伴会说 HTML 与 JS 分离不是更好吗?责职分明,混合只会更乱。但当你体验到代码自动提示,自动检查,以及调试时精确定位到一行代码的好处时,就清楚 React 和 Vue 的差距了。 + +## 文本插值 + +**vue种采用双括号** + +```vue +Message: {{ msg }} +``` + +**react采用单括号** + +```jsx +function MyComponent(props) { + let msg = 'XXX' + return
{ msg }
+} +``` + +## Attribute 绑定 + +**vue中 想要响应式地绑定一个 attribute,应该使用 `v-bind` 指令** + +```vue +
+
+``` + +**react中,使用单引号,或者使用单括号包裹表示动态绑定** + +```jsx +function App () { + let tmpID = '12' + return ( +
+
id
+
id
+
+ ); +} +``` + +动态绑定多值: + +```jsx +function App () { + let tmpObject = { + id: 13, + className: 'wrapper' + } + return ( +
+
id
+
+ ); +} + +即: + +
id
+``` + +## 参数 Arguments + +**某些指令会需要一个“参数”,Vue在指令名后通过一个冒号隔开做标识。例如用 `v-bind` 指令** + +```vue + ... + + + ... +``` + +**React中则没有指令一说,而是采用如下方式:** + +```jsx +// href跳转 +function App () { + let tmpURL = 'https://www.XXXXXXXX' + return ( +
+ +
+ ); +} +``` + +## 使用 JS 表达式 + +**React 遇到 `{}` 符号内部解析为 JS 代码** + +```jsx +function App () { + let tmpString = '--'; + return ( +
+
{1 + 1}
+
{'a' + 'b'}
+
{`1${tmpString}1`}
+
+ ); +} +``` + +即: + +```html +
2
+
ab
+
1--1
+``` + +## 事件处理 + +**Vue中绑定事件处理:** + +```vue + + +``` + +**React可以通过在组件中声明 事件处理 函数来响应事件** + +React中点击事件使用小驼峰形式:onClick + +在标签上写函数: + +```jsx +function App () { + return ( +
+
alert('点击出现弹框')}>按钮
+
+ ); +} +``` + +提前声明函数: + +```jsx +function App () { + function myFun () { + alert('点击出现弹框') + } + return ( +
+
按钮
+
+ ); +} +``` + +注意,`onClick={handleClick}` 的结尾没有小括号!不要 **调用** 事件处理函数:你只需 **传递给事件** 即可。当用户点击按钮时,React 会调用你的事件处理函数。 + +函数传参: + +```jsx +function App () { + function myFun (str) { + alert(str) + } + return ( +
+
myFun('点击出现弹框')}>按钮
+
+ ); +} +``` + +## 动态参数 + +**Vue在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对方括号内:** + +```vue + ... + + + ... +``` + +举例来说,如果你的组件实例有一个数据属性 `attributeName`,其值为 `"href"`,那么这个绑定就等价于 `v-bind:href`。 + +**React 也可以通过动态参数绑定** + +```jsx +function App () { + const obj = { + onClick: () => alert('点击出现弹框'), + // ...还可以写更多事件 + } + return ( +
+
按钮
+
+ ); +} +``` + +## 修饰符 Modifiers + +vue 修饰符是以点开头的特殊后缀 + +表明指令需要以一些特殊的方式被绑定。例如 `.prevent` 修饰符会告知 `v-on` 指令对触发的事件调用 `event.preventDefault()`: + +```vue +
...
+``` + +React 则是依靠于JS基础 + +```jsx +function App () { + function onSubmit(e){ + e.preventDefault(); + e.stopPropagation(); + } + return ( +
+
+ +
+
+ ); +} +``` + +## 响应式 + +**为了实现视图更新,VUE中响应式是一个重要的概念** + +**而 React 中并没有响应式这个概念,要实现视图更新,需要在 React 引入 `useState`** + +通常,你会希望你的组件 “记住” 一些信息并展示出来。例如,也许你想计算一个按钮被点击的次数。要做到这一点,你需要在你的组件中添加 **state**。 + +首先,从 React 引入 `useState`: + +```jsx +import { useState } from 'react'; +``` + +现在你可以在你的组件中声明一个 **state 变量**: + +```jsx +function MyButton() { + const [count, setCount] = useState(0); + // ... +``` + +你将从 `useState` 中获得两样东西:当前的 state(`count`),以及用于更新它的函数(`setCount`)。你可以给它们起任何名字,但按照惯例,需要像这样 `[something, setSomething]` 为它们命名。 + +第一次显示按钮时,`count` 的值为 `0`,因为你把 `0` 传给了 `useState()`。当你想改变 state 时,调用 `setCount()` 并将新的值传递给它。点击该按钮计数器将递增: + +```jsx +function MyButton() { + const [count, setCount] = useState(0); + function handleClick() { + setCount(count + 1); + } + + return ( + + ); +} +``` + +React 将再次调用你的组件函数。这次,`count` 会变成 `1`。接着,变成 `2`。以此类推。 + +如果你多次渲染同一个组件,每个组件都会拥有自己的 state。你可以尝试点击不同的按钮: + +## 计算属性 + +Vue中使用 computed 来实现计算属性(缓存计算的结果) + +**React 在组件的顶层调用 `useMemo` 来缓存每次重新渲染都需要计算的结果** + +```jsx +import { useState } from 'react'; +import { useMemo } from 'react'; + +function App () { + const [user] = useState({ firstname: 'a', lastname: 'b' }) + + const fullname = useMemo(() => { + return user.firstname + user.lastname; + }, [user.firstname, user.lastname]) + + return ( +
+ {fullname} +
+ ); +} +``` + +**useMemo(calculateValue, dependencies)** + +参数 + +- `calculateValue`:要缓存计算值的函数。它应该是一个没有任何参数的纯函数,并且可以返回任意类型。React 将会在首次渲染时调用该函数;在之后的渲染中,如果 `dependencies` 没有发生变化,React 将直接返回相同值。否则,将会再次调用 `calculateValue` 并返回最新结果,然后缓存该结果以便下次重复使用。 +- `dependencies`:所有在 `calculateValue` 函数中使用的响应式变量组成的数组。响应式变量包括 props、state 和所有你直接在组件中定义的变量和函数。如果你在代码检查工具中 [配置了 React](https://react.docschina.org/learn/editor-setup#linting),它将会确保每一个响应式数据都被正确地定义为依赖项。依赖项数组的长度必须是固定的并且必须写成 `[dep1, dep2, dep3]` 这种形式。React 使用 [`Object.is`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/is) 将每个依赖项与其之前的值进行比较。 + +## 绑定 HTML class + +数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式。因为 `class` 和 `style` 都是 attribute + +Vue中可以给 `:class` (`v-bind:class` 的缩写) 传递一个对象来动态切换 class: + +```vue +
+``` + +上面的语法表示 `active` 是否存在取决于数据属性 `isActive` 的真假值。 + +React实现方式基于js语法,其实有多种实现方式,列举三元运算符方式如下: + +```jsx +function App () { + let showColor = false + return ( + // 现有box-show、box-hide两个class样式 +
+ ); +} +``` + +## 语法糖转换 + +习惯 Vue 的同学都知道很多语法糖,比如 `v-if`、`v-for`、`v-bind`、`v-on` 等,相比 Vue,React 只有一个语法糖,那就是 jsx/tsx。`v-if` 这些功能在 React 上都是通过原生 javascript 实现的,慢慢你会发现,其实你学的不是 React,而是 Javascipt,React 赋予你通过 js 完整控制组件的能力,这部分明显比 Vue 的语法糖更加灵活,糖太多容易引来虫子(Bug) + +条件渲染 + +vue 中写法是这样: + +```vue +
+

Vue is awesome!

+

else

+
+``` + +在 React 函数组件中,只需使用 js 三目运算符语法即可完成条件渲染的功能。或者使用 && 逻辑,记住下面一句话就能过理解了: + +> 遇到 `{}` 符号内部解析为 JS 代码,遇到成对的 `<>` 符号内部解析为 HTML 代码 + +```jsx +function App () { + const ishow = false + return ( +
+ {ishow ?
awesome
:
else
} + {ishow &&

React!

} +
+ ); +} +``` + +## 列表渲染 + +Vue中通过v-for进行列表渲染 + +**React 通过 js 的数组语法 map,将数据对象映射为 DOM 对象**。只需学会 js,无需记住各种指令,如果要做列表过滤,直接使用 `items.filter(...).map(...)` 链式调用即可,语法上更加灵活,如果为了提高渲染性能,使用 useMemo 进行优化即可,类似 Vue 的 computed。 + +```jsx +function App () { + const arr = [{ message: 'react' }, { message: 'JS' }] + return ( +
+ {arr.map((items, index) =>
  • {items.message}
  • )} +
    + ); +} +``` + +## 侦听器 + +Vue中使用 watch监听数据变化,触发回调 + +React中可以使用 useEffect 实现 + +```jsx +function App () { + const [user, setUser] = useState({ + firstname: 'a', + lastname: 'b' + }) + useEffect(() => { + console.log("1111") + }, [user.firstname]) + return ( +
    + +
    + ); +} +``` + + + # 父子组件传递事件 ## 子组件是模态框,确定按钮需要增加loading状态