React 用一个简单案例体验一遍 React-dom React-router React-redux 全家桶
一、准备工作
本文略长,建议耐心读完,每一节的内容与上一节的内容存在关联,最好跟着案例过一遍,加深记忆。
1.1 创建项目
- 第一步,执行下面的命令来创建一个 React 项目。
npx create-react-app react-example
cd react-example
- 第二步,安装依赖,运行项目
yarn install 或 npm install
yarn start 或 npm run start
1.2 项目结构
如图:

1.3 初始化
将 src/index.js 的默认代码删掉,保留下面这部分。
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
const root = ReactDOM.createRoot(document.getElementById("root"));
const App = () => {return <div>Hello</div>
}
root.render(<App />);
现在项目看起来就像这样,一个简单的 Hello。

二、React 的基本用法
如果你还不熟悉 React 的基础语法,可以阅读我前面写的 React & 工作日常语法。
1.1 输出 Hello, world
第一步肯定是要先来句 Hello,world!
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';const root = ReactDOM.createRoot(document.getElementById("root"));
const App = () => {return <div>Hello, world!</div> // 改动点
}
root.render(<App />);

1.2 组件的使用
组件可以由函数或者类来进行创建,像上面的App函数就是一个组件,里面可以混合写 HTML & JS 代码,React 会自动帮我们解析这些语法,像这种写法就叫就JSX。
下面我将以函数的方式来定义组件作为案例,类组件在讲生命周期时做演示。
- 第一步,随便定义一个叫
List的组件,内容随便写,比如 Hi List
const List = () => {return <div>Hi List.</div>
}
- 第二步,引入
List,目前入口只有App,很明显只能放这里。
const App = () => {return <div>Hello, world! </List> </div>
}
效果:

1.3 组件嵌套组件
像
App组件嵌套List组件,我们管这叫父子组件,App 是父组件, List 是子组件,当 List 套上 Item 组件时,那 Item 的父组件就是 List,而祖父组件是 App, 以此类推。
现在我们来给 List 嵌套一个 Item 组件。
const List = () => {// 多行时要用 () 包裹return (<ul><Item/> // 引入</ul>)
}
const Item = () => {return <li>item1</li>
}
效果:

别忘了还可以写 JSX 的,现在试试用 Array.map 循环多个 Item 组件。
const List = () => {return (<ul>{[1, 2, 3, 4].map((num) => Item(num) )}</ul>)
}
const Item = (num) => {return <li key={num}>item{num}</li>
}
在看效果前思考下,上面代码具体会发生哪些变化?
- Item 函数组件多了个
num参数,我们用它来接受,并用{num}括号包括起来进行访问 <Item/>的调用方式变成Item(num),因为我们要将 num 值传递给 Item 函数,所以我们又发现了一个特性,在不传参的情况下直接声明<Item/>是会自动触发函数的。- 循环组件时,
key属性得带上且是唯一的。
效果:

1.3 组件绑定点击事件
干巴巴的列表,没有交互行为怎么能行呢,
现在我们就来定义一个事件,当点击某个 Item 时提示对应的 num 数值,代码如下:
const onClickItem = (num) => {alert(num);
}
const Item = (num) => {return <li key={num} onClick={() => onClickItem(num)}>item{num}</li>
}
解释:
- 点击事件用
onClick驼峰形式来表示,其它事件也是类似的,比如 onFocus, onMouse 等。 onClick={() => 函数}花括号返回一个箭头函数,函数里面就是返回我们定义的函数,后面点击时会触发。
不用怀疑语法是否有问题,连 JSX 语法都有了,你还在乎这个?
效果:

1.5 响应式数据
光弹窗没啥用啊,要不点击后直接变更 Item 的数据如何?
问题是… 怎么变更?直接将 num = xxx?熟悉 JS 的朋友应该知道,当 num 参数传递的是【基本类型】时只是一个副本,更改后对原来的 num 是无效的。
就算有效,你又如何将视图中的 num 也发生变化呢? 看来还是得借助 React 提供的语法了。
唉没办法,学吧~
-
第一步,先将原来的
[1,2,3,4]以useState提供的函数来定义并导出arr变量数组,如图:

效果还是与原来一样,这里就不贴图了。 -
第二步,在 arr 后面再声明一个
setArr函数,名字随便定义,但一般用 set 开头作为规范好点,表示用来变更 arr 数据的。
const List = () => {const [arr, setArr] = useState([1, 2, 3, 4])
// ...省略
- 第三步,触发
setArr函数,更改 arr 数组里的数据来达到我们想要的视图变更效果

由于setArr是在 List 函数组件里定义的,其它函数无法直接访问,得通过传参的方式带过去、一直传到 onClickItem 中,有点绕,将就一下吧,相信你不介意的(/逃)。
这里我们重点关注这一段代码:
setArr(state => {const arr = [...state];arr[1] = 1000;return arr;
})
当点击后,将 arr[1] 改为 1000,并将新的 arr 返回出去,效果如图:

你可能注意到,state 就是原先的 arr,然后我们用扩展符号将它拷贝一份到新的 arr 中,为什么要这样做呢?直接 state[1] = 1000 再 return 出去不行吗,多此一举嘛这不是。
是可以这样做,数据也会发生变化了,但视图不会发生变化,因为 React 明确规定:state 是不可变数据,你不能直接改变它,而是要用一份副本去改变。
为什么 state 要坚持不可变原则呢?官方也说了,当你要实现一个撤销&恢复的功能时就没辙了,或者说实现起来更复杂?React 这时要是还允许你去那岂不是有点不地道了,这不跟吃了上顿不考虑下顿的道理嘛。
小结:
- useState 可以声明响应式数据。
- state 数据不可变,要用副本代替,遵循不可变原则。
1.6 什么是钩子函数 Hook Function
其实我们已经用过钩子函数了,上面的 useState 就是一个钩子函数,React 内置了许多的钩子,比如 useEffect, useRef 等,这里就不一一介绍,只需明白以 use 为开头的均属于钩子函数即可。
我们也可以自定义钩子,问题来了,在什么样的场景下需要呢?里面写啥呢?
这个其实没有唯一答案,每个人对理解钩子的程度是不同的,导致有千千万万种类型的钩子。
我个人更喜欢将它归为处理脏活的一类函数,更通俗点来说,是用来处理响应式数据的,比如,有个奖品业务的功能模块,针对这个模块,可能有验证奖品配置的逻辑,那么我就会给这个奖品加上几个 hook 函数,以便后续方便调用。
const usePrize = () => {const verifyPrizeConfig = (state) => {// Do something ...}const resetPrizeConfig = (state) => {// Do something ...}return [verifyPrizeConfig,resetPrizeConfig,]
}
const [ verifyPrizeConfig ] = usePrize();
1.7 组件的生命周期
每个组件渲染时,React 会逐步按顺序触发一些内置函数,这些被称为”生命周期函数“,我们可以根据不同周期函数来做一些业务处理,比如我想在组件渲染前先请求接口得到数据。
这里需要注意,函数组件是没有命周期函数的,只有类组件才有,既然这样,我们将 App 这个组件变成类组件即可,其它保持不变,谁规定类组件里面就不能嵌套函数组件?
- 第一步,将 App 函数组件改为类组件,如下:
// 源 App 函数组件
// const App = () => {
// return <div>Hello, world! <List/> </div>
// }
// 新 APP 类组件
class App extends React.Component {constructor(props) {super(props);}render() {return <div>Hello, world! <List /> </div>}
}
- 第二步,添加生命周期函数,这里用最常见的
componentDidMount函数,表示组件第一次渲染时提前触发。
class App extends React.Component {// 省略componentDidMount() {// Do something...alert('Init')}
}

1.8 函数组件模拟生命周期
你可能想,这不公平,函数组件凭啥没有周期函数?别急,React 提供的钩子函数 useEffect 就派上用场了,该钩子完全可以模拟生命周期的三大核心函数:
componentDidMount() {} 组件第一次渲染时,就刚刚用到的
componentDidUpdate() {} 组件数据更新时(state 更新)
componentWillUnMount() {} 组件销毁时
使用方式也很简单,这里以 List 组件作为案例,不能忘记我们的老伙伴~
- 第一步,模拟
componentDidMount,如下:
import { useState, useEffect } from 'react';
const List = () => {const [arr, setArr] = useState([1, 2, 3, 4]);// 模拟 componentDidMountuseEffect(() => {alert('List init') });return (<ul>{arr.map((num) => Item(num, setArr) )}</ul>)
}

- 第二步,模拟
componentDidUpdate,在 useEffect 的第二个参数监听 state:
// ... 省略
const [arr, setArr] = useState([1, 2, 3, 4])useEffect(() => {alert('List init')}, [arr]) // componentDidUpdate
当点击更新数据时,这个函数就会再次触发,如图:


- 第三步,模拟
componentWillUnMount,在 useEffect 里面 return 一个函数即可。
const [arr, setArr] = useState([1, 2, 3, 4])useEffect(() => {alert('List init')return () => { // componentWillUnMountalert('List destroyed!');};}, [arr])
componentWillUnMount 什么时候触发呢?实际上,每当 state 更新时,组件会重新渲染一次,这属于销毁行为,因此当点击更新数据后,会先触发 componentWillUnMount ,再触发 componentDidUpdate 。
效果:



三、React-router-dom
1.1 什么是 React-router-dom
一个页面怎么够用呢,现在我们想要通过点击 item 进入另一个页面,且保持页面不刷新,这里便可以用 React 提供的插件 React-router-dom ,俗称路由来实现。
1.2 React-router-dom 和 React-router 版本的区别
React-router-dom 是基于 React-router 改造的新版本,现在大家常用的版本是 React-router-dom,
本案例将用 React-router-dom 来作为演示。
1.3 React-router-dom 的使用
- 第一步,下载 react-router-dom。
yarn add react-router-dom
- 第二步,在
src/index.js中引入。
import {createBrowserRouter,RouterProvider,
} from "react-router-dom";
- 第三步,将我们之前的 App 组件引入方式重新改造一下
// 旧代码
// root.render(<App />);
// 新代码
const router = createBrowserRouter([{path: "/",element: <App/>,},
]);root.render(<RouterProvider router={router} />);
现在效果和原来没区别,这里解释下步骤:
- 将原来 root.render 里的 App 替换成
RouterProvider组件 - 在
createBrowserRoute里面的element引入 App。 - path (
路由),当访问/根目录时才会渲染 App 组件。
- 第四步,新建
AppDetail组件并挂载到/detail路由上。
const AppDetail = () => {return <h1>Detail data</h1>
}
const router = createBrowserRouter([{path: "/",element: <App/>,},// 挂载到 /detail 路由{path: "/detail",element: <AppDetail/>,},
]);
- 第五步,访问
/detail看看效果

- 第六步,以点击跳转的方式访问
/detail,这里用到 router 提供的<Link>标签。
import {createBrowserRouter,RouterProvider,Link,
} from "react-router-dom";
const Item = (num, setArr) => {return (<li key={num} onClick={() => onClickItem(num, setArr)}><Link to='/detail'>item{num}</Link></li>)
}
效果:

react-router-dom 就这么简单,至于其它 API 的使用可以参考文档,这里不过多讲解。
四、React-redux
1.1 什么是 React-redux
React-redux 可以用来管理全局状态 state 的工具,使得组件之间可以访问同一份 state。
1.2 什么时候用 React-redux
当多个组件重复使用同一份 state 时就可以考虑用 redux 将它提升到全局中,以便于维护。
1.3 React-redux 下载&配置
- 第一步,下载
react-redux,这里官方还提供了一个工具包@reduxjs/toolkit,里面包含了 react-redux 所有功能以及内置一些其它功能,是官方极力推荐的,这两个一起下载。
yarn add react-redux @reduxjs/toolkit
- 第二步,在 src 下新建
store/index.js文件,负责管理全局 state,初始化内容如下:
// ./src/store/index.js
import { configureStore, createSlice } from '@reduxjs/toolkit'
const userSlice = createSlice({name: 'User', // name 必填的,当前作用域的标识符,可以理解为 nameSpace 命名空间,否则页面上无法正常展示。initialState: { // 声明 state 的地方},reducers: { // 声明 reducer 函数的地方}
});
// 将 store 导出去。
const store = configureStore({reducer: userSlice.reducer
})export default store;
- 第三步,在
src/index.js中引入store
import store from './store/index';
import { Provider } from 'react-redux'
root.render(<Provider store={store}><RouterProvider router={router} /></Provider>
);
解释:
- 从 store.js 中引入
store对象。 - 从 redux 中引入
Provider组件,并将原先的RouterProvider组件包裹起来。 - 将
store作为参数传递给Provider组件。
目前来讲,页面跟原来没有区别,但是现在我们多了 redux 的功能,何乐而不为呢。
1.4 什么是 Reducer
Reducer 与 Vuex 中的 mutations 差不多同一个意思,里面专门定义一些处理 state 的函数,reducer 主要接受一个 state 和一个 action ,根据这两个参数处理相关逻辑,然后返回新的 state (遵循前面所说的“不可变原则”)。
1.5 什么是 dispatch(action)
dispatch是用来调用 reducer 函数的。action是 dispatch 调用 reducer 函数时要传递的一个描述对象,好让 reducer 知道该干什么事。该描述对象总共就俩参数:type/payload,type 是调用 reducer 的函数名,payload 是我们要传参的数据,给 reducer 接受用的。
1.6 使用
理解 reducer/dispatch/action 三大核心概念之后,我们来开始使用:
- 第一步,在
initialState对象中定义全局响应式数据。
// 省略...
initialState: {// 新增user: {name: 'Jack',desc: 'Hello,world!'}
},
- 第二步,新建
User组件,该组件用来访问上面声明的响应式数据,并挂载到 App 和 AppDetail 中渲染,代码如下:
// ./src/index.js
// ...省略
import { Provider, useSelector } from 'react-redux'
// 新增
const User = () => {// 用 redux 提供的钩子来获取 stateconst user = useSelector(state => state.user); return (<div><span>{user.name}</span><span> says: {user.desc}</span></div>)
}
// ./src/index.js
// ...省略
class App extends React.Component {// ...省略render() {return (<div><User /> // 新增:挂载 User<List /> </div>)}
}
const AppDetail = () => {return (<h1>Detail data<User /> // 新增:挂载 User</h1>)
}
现在的效果:Jack says: Hello,world!

- 第三步,声明
reducer函数来变更 state 数据。
// .src/store/index.js
// ...省略
reducers: { // 声明 reducer 函数的地方// 新增changeUserInfo(state, action) {const { payload } = action;switch(payload.state) {case 'name':return {...state,user: {...state.user,name: '杰克',}}case 'desc':return {...state,user: {...state.user,desc: '你好,世界!',}}default:return state;}}}
changeUserInfo 函数解释:
- 根据 payload.state 即我们准备传参的数据来变更用户名 name 还是描述
desc - 遵循不破坏 state 原则,这里我们用扩展符来合并。
- 第四步,使用
dispatch(action)来触发 reducer,完成变更效果。
// ./src/index.js
import { Provider, useSelector, useDispatch } from 'react-redux'
const User = () => {const user = useSelector(state => state.user);const dispatch = useDispatch(); // 引入触发 reducer 的钩子return (<div><span>{user.name}</span><span> says: {user.desc}</span>// 以下是新增的<button onClick={() => dispatch({type: 'User/changeUserInfo',payload: {state: 'name'}})}>更换名字</button><button onClick={() => dispatch({type: 'User/changeUserInfo',payload: {state: 'desc'}})}>更换描述</button></div>)
}
现在来看看总体效果:

五、总结
不知不觉,我们已经用到了 React-dom & React-router& React-redux:
root.render( // react-dom<Provider store={store}> // react-redux<RouterProvider router={router} /> // react-router-dom</Provider>
);
恭喜你已成功入门 React 全家桶,剩下就交给实践的时间来帮助我们熟能生巧。
有问题欢迎指出!
完!
案例已放在 github 上
相关文章:
React 用一个简单案例体验一遍 React-dom React-router React-redux 全家桶
一、准备工作 本文略长,建议耐心读完,每一节的内容与上一节的内容存在关联,最好跟着案例过一遍,加深记忆。 1.1 创建项目 第一步,执行下面的命令来创建一个 React 项目。 npx create-react-app react-example cd rea…...
9. C#面向对象基础
一、C# 类 在 C# 中,类是引用类型的。类由成员属性和成员方法构成。我们可以动态创建类的实例(instance),这个实例也被称为对象(object),我们可以通过类和对象来设计程序。 1、类的定义 类的定…...
【MIT 6.S081】Lab2: system calls
本Lab包括两个简单系统调用的实现,进一步熟悉系统调用接口。 笔者用时约1.5h 概述 根据文档说明,当我们添加一个系统调用时,比如第一个任务是添加一个trace,需要进行以下操作: 首先将系统调用的原型添加到user/user…...
设计模式之单例模式~
设计模式包含很多,但与面试相关的设计模式是单例模式,单例模式的写法有好几种,我们主要学习这三种—饿汉式单例,懒汉式单例、登记式单例,这篇文章我们主要学习饿汉式单例 单例模式: 满足要点: 私有构造 …...
top终端详解
1.top命令行使用 2.top每行意义 3.补充 1.top命令行使用 top命令是一个常用的Linux系统命令,用于实时查看系统的运行状态和进程信息。下面是top命令的几个常用参数的含义: -d seconds:设置top命令的更新间隔时间,单位是秒。默认是…...
解决一个偶现的503 bug,花了俺不少时间
概述 在3月2日晚上,大概8点左右,本想打道回府,回家休息,突然被人在bug群了一下,说是管理后台,访问不了,界面上出现了: 503 service temporarily unavailable我赶紧尝试访问了一下,确…...
什么是栈,如何实现?
欢迎来到 Claffic 的博客 💞💞💞 “但有一枝堪比玉,何须九畹始征兰?” 前言: 栈是一种特殊的线性表,就像开盖的桶一样,从底部开始放数据,从顶部开始取数据,那么栈具体是…...
在我的MacBook上捣鼓ESP8266
周三是我们的篮球日,打篮球后总是会有些兴奋,然后就容易睡不着,额,睡不着就拿我的ESP8266开发板出来捣鼓一下。先下载编译工具链https://github.com/espressif/ESP8266_RTOS_SDK下载sdkgit clone https://github.com/espressif/ES…...
【深度强化学习】(8) iPPO 模型解析,附Pytorch完整代码
大家好,今天和各位分享一下多智能体深度强化学习算法 ippo,并基于 gym 环境完成一个小案例。完整代码可以从我的 GitHub 中获得:https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Model 1. 算法原理 多智能体的情形相比于单智…...
77.qt qml-QianWindow-V1版本界面讲解
上章介绍: 76.qt qml-QianWindow开源炫酷界面框架简介(支持白色暗黑渐变自定义控件均以适配) 界面如下所示: 代码结构如下所示:...
RHCE学习日记二
1、在 node1 主机上配置 chrony 时间服务器,将该主机作为时间服务器。 命令: vim /etc/chrony.conf 在文件位置添加命令: #Use public servers from the pool.ntp.org project. #Please consider joining the pool (https://www.pool.ntp.org…...
Dubbo原理简介
Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。 作为RPC:支持各种传输协议,如dubbo,hession,json,fastjson,底层采用mina,netty长连接…...
JavaSE基础总结
JDK与JRE JDK,全称Java Development Kit,Java开发工具包 JRE,全称Java Runntime Environment,Java运行环境 JDK包含后者JRE。 JDK也可以说是Java SDK(Software Development kit,软件开发工具包)…...
5G(NR)信道带宽和发射带宽---频率资源
前言 查看此文之前建议先看看这篇 5G(NR)频率资源划分_nr运营商频段划分_达帮主的博客-CSDN博客NR频率有上面几个划分 ,可以使用低于1GHz的频端,既可以使用高于30GHz高频端。使用频端高于30GHz那我们称之为高频或者毫米波。使用毫米波是5G网络区别于4G…...
基于Spring Boot的酒店管理系统
文章目录 项目介绍主要功能截图:登录首页房间类型酒店预约部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于Spring Boot的酒店管理系统…...
Ae:混合模式
Ae 中内置了 Ps 的渲染引擎,同样可在多处应用混合模式 Blending Mode。与 Ps 相比,除了两组图层通道相关的特定模式,其它的混合模式几乎是一模一样。相关快捷键:下一图层混合模式:Shift 上一图层混合模式:…...
JS中的变量
系列文章目录 前端系列文章——传送门 JavaScript系列文章——传送门 文章目录系列文章目录前言1、概念2、定义变量3、变量名的规则4、变量本质5、赋值6、常用操作前言 相对于青龙面板来说,变量就是你填入青龙的cookie,简称ck 在实际项目中࿰…...
Hadoop运行模块
二、Hadoop运行模式 1)Hadoop官方网站:http://hadoop.apache.org 2)Hadoop运行模式包括:本地模式、伪分布式模式以及完全分布式模式。 本地模式:单机运行,只是用来演示一下官方案例。生产环境不用。伪分…...
Web自动化——前端基础知识(二)
1. Web前端开发三要素 web前端开发三要素 什么是HTMl? Html是超文本标记语言,是用来描述网页的一种标记语言HTML是一种标签规则的形式将内容呈现在浏览器中可以以任意编辑器创建,其文件扩展名为.html或.htm保存即可 什么是CSS?…...
NAS系列 硬件组装
转自我的博客文章https://blognas.hwb0307.com/nas/3260,内容更新仅在个人博客可见。欢迎关注! 前言 之前我在《NAS系列 硬件选择》里讲述了自己为了升级NAS如何选配硬件。本节我大概说一些我的新NAS硬件组装的注意事项。到目前为止,我只装过…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
对象回调初步研究
_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...
Axure Rp 11 安装、汉化、授权
Axure Rp 11 安装、汉化、授权 1、前言2、汉化2.1、汉化文件下载2.2、windows汉化流程2.3、 macOs汉化流程 3、授权 1、前言 Axure Rp 11官方下载链接:https://www.axure.com/downloadthanks 2、汉化 2.1、汉化文件下载 链接: https://pan.baidu.com/s/18Clf…...
