React(二) JSX中的this绑定问题;事件对象参数传递;条件渲染;列表渲染;JSX本质;购物车案例
文章目录
- 一、jsx事件绑定
- 1. 回顾this的绑定方式
- 2. jsx中的this绑定问题
- (1) 方式一:bind绑定
- (2) 方式二:使用 ES6 class fields 语法
- (3) 方式三:直接传入一个箭头函数(重要)
- 3.事件参数传递
- (1) 传递事件对象event
- (2) 传递其他参数
- 4. 事件绑定小案例
- 二、条件渲染
- 1. if-else、三元运算符,逻辑与&&
- 2. 模拟v-show的效果
- 三、列表渲染
- 四、JSX的本质
- 1. babel转译JSX
- 2. 虚拟DOM到真实DOM
- 五、购物车案例
- 1. 总价格与格式化
- 2. 商品数量+和-的操作
- 3. 删除
- 4. 无数据时给提示
一、jsx事件绑定
1. 回顾this的绑定方式
(绑定方式就是指this值的几种指向)
- 默认绑定。 函数独立执行
fun()
—此时this指向window - 隐式绑定。被一个对象调用指向
obj.foo()
—此时this指向obj - 显示绑定。通过call/apply/bind明确规定this的指向 —
foo.call('aaa')
- new绑定。 new Foo()—> 创建一个实例,this指向实例
仔细看下边这段代码,分析两次函数调用分别打印什么值
const obj = {name: "obj",foo: function () {console.log("foo:", this)}}obj.foo() // objconst config = {onClick: obj.foo}const click = config.onClick //这句话实际是click = obj.fooclick() // 等价于foo(), 独立执行,指向window(严格模式值为undefined)
若修改为
const config = {onClick: obj.foo.bind(obj)}const click = config.onClick //这句话实际是click = obj.fooclick() // 等价于obj.foo(), 打印出来的this指向obj
2. jsx中的this绑定问题
如之前所说,在这个类组件中,事件的处理函数需要对数据进行处理;
在严格模式下,构造函数与render里的this
指向实例对象,而类里的方法中的this值为undefined
。undefined.setState
会报错,所以需要处理this绑定问题
(1) 方式一:bind绑定
constructor() {super()this.state = {number: 0}// bind改变btnClick1 方法里this的指向this.btnClick1 = this.btnClick1.bind(this)}btnClick1 () {console.log('btn1', this);this.setState({number: this.state.number + 1})}render(){...<button onClick={this.btnClick1}>+1</button>...}
(2) 方式二:使用 ES6 class fields 语法
es6中,在类里可以省略constructor,直接给变量赋值,这就是class fileds。
class App extends React.Component {...// 给变量btn2Click 赋值一个箭头函数btn2Click = () => {console.log("btn2Click", this)this.setState({ number: 1000 })}render () {return (<div>{/* 2.this绑定方式二: ES6 class fields */}<button onClick={this.btn2Click}>按钮2</button></div>)}}
当调用箭头函数时,箭头函数没有自己的this,会向上层作用域查找,而上层作用域是类的作用域(App类),指向的则会是类的实例。
(3) 方式三:直接传入一个箭头函数(重要)
class App extends React.Component {...// 给变量btn2Click 赋值一个箭头函数btn3Click = () => {// 隐式绑定后,这里的this就是render函数里的this,就是当前对象实例console.log("btn3Click", this) this.setState({ number: 666})}render () {return (<div>{/* 3.this绑定方式三: 直接传入一个箭头函数 */}<button onClick={() => this.btn3Click()}>按钮3</button></div>)}}
当点击按钮时,onClick被触发,执行箭头函数。而在代码逻辑在btn3Click
里,所以箭头函数调用了btn3Click
,而在调用btn3Click
时,是this在调用,也就是一个对象调用了btn3Click
,即进行了隐式绑定。
3.事件参数传递
(1) 传递事件对象event
btnClick (event) {console.log("btnClick:", event, this)}render () {return (<div>{/*默认参数传递*/}<button onClick={this.btnClick}>按钮1</button><button onClick={this.btnClick.bind(this)}>按钮2</button><button onClick={() => this.btnClick()}>按钮3</button><button onClick={(event) => this.btnClick(event)}>按钮4</button></div>)}
点击按钮1:默认传递了事件对象event,this是undefined
点击按钮2:默认传递了事件对象event,this是组件实例
点击按钮3:调用了btnClick
函数,什么参数也没传。所以event是undefined;this是组件实例。
点击按钮4:传递了事件对象,所以event和this都有值
(2) 传递其他参数
在传递了事件对象的基础上,再传递其他参数
btnClick (event, name, age) {console.log("btnClick:", event, this)console.log("name,age:", name, age)
}
...
<button onClick={(event) => this.btnClick(event, 'tom', 18)}>按钮5</button>
4. 事件绑定小案例
二、条件渲染
vue中是通过指令来控制:比如v-if、v-show;
在React中,所有的条件判断都和普通的JavaScript代码一致
1. if-else、三元运算符,逻辑与&&
- if-else:条件判断语句,适合逻辑较多的情况
- 三元运算符:适合逻辑简单的情况
- 与运算符&&:适合于条件成立,则渲染组件;条件不成立,则什么也不渲染
this.state = {isReady: true,friend: {name: 'tom',desc: '很棒!'}}
render () {const { isReady, friend } = this.statelet showEle = null// 采用if判断是否生成页面内容if (isReady) {showEle = <h2>准备开始比赛! </h2>} else {showEle = <h2>请提前做好准备</h2>}return (<div>{/* 1.方式一: 根据条件给变量赋值不同的内容*/}{showEle}{/* 2.方式二: 三元运算符*/}{isReady ? <button>点击开始战斗</button> : <h2>赶紧准备!</h2>}{/* 3.方式三: &&逻辑运算,friend为空则不显示,有值则显示*/}{friend && <h2>{friend.name + ':' + friend.desc}</h2>}</div>)
}
2. 模拟v-show的效果
控制display属性是否为none;
需求:点击按钮,实现文字的隐藏与显示
btnClick () {this.setState({isShow: !this.state.isShow})}render () {const { msg, isShow } = this.statereturn (<div><button onClick={() => this.btnClick()}>切换</button>{/*逻辑与&&*/}{isShow && <h2>{msg}</h2>}{/*v-show的效果*/}<h2 style={{ display: isShow ? 'block' : 'none' }}>{msg}</h2></div >)}
采用了两种实现方式,加深一下对逻辑与&&的运用
三、列表渲染
React中没有像Vue模块语法中的v-for指令,React渲染列表就是采用JS里的一些方法对列表进行遍历或其他处理。
◼ 如何展示列表呢?
在React中,展示列表最多的方式就是使用数组的map高阶函数;
◼ 很多时候我们在展示一个数组中的数据之前,需要先对它进行一些处理:
比如过滤掉一些内容:filter函数
比如截取数组中的一部分内容:slice函数
注意:这里要注意map中这个返回标签的话,返回的东西要和return写在一行(比如这个括号),不然默认就return跳出去了,什么也不会渲染。(其他博主踩的坑)
案例:展示学生信息。
// 数据students: [{ id: 111, name: "why", score: 199 },{ id: 112, name: "kobe", score: 98 },{ id: 113, name: "james", score: 199 },{ id: 114, name: "curry", score: 188 },]
map函数展示
render () {const { students } = this.statereturn (<div>{students.map((item) => {return (<div className="item" key={item.id}><h2>学号: {item.id}</h2><h3>姓名: {item.name}</h3><h1>分数: {item.score}</h1></div>)})}</div>)}
展示分数大于100的学生:filter
render () {...const filterStus = students.filter((item) => item.score > 100)return (...filterStus.map((item) => {return (<div className="item" key={item.id}>...</div>)})...)
}
展示分数大于100的前两位学生:slice
return (<div>{filterStus.slice(0, 2).map((item) => {return (<div className="item" key={item.id}><h2>学号: {item.id}</h2><h3>姓名: {item.name}</h3><h1>分数: {item.score}</h1></div>)})}</div>)
其中key的唯一标识和vue中原理差不多。
四、JSX的本质
Jsx的本质是 React.createElement(type, config, ...children)
函数的语法糖。所有的jsx最终都会被转换成React.createElement
的函数调用。
先看这个函数的参数:
- 参数一:type
当前ReactElement的类型;
如果是标签元素,那么就使用字符串表示 “div”;
如果是组件元素,那么就直接使用组件的名称; - 参数二:config
所有jsx中的属性都在config中以对象的属性和值的形式存储;
比如传入className作为元素的class; - 参数三:children
存放在标签中的内容,以children数组的方式进行存储;
1. babel转译JSX
babel将JSX语句转换成React.createElement的函数,这个函数会创建element,element最终会形成元素树。每个元素就是虚拟DOM。
比如render函数里有这样一段JSX代码
<div><h2>{count}</h2><ul className='active'><li>我是li1</li><li>我是li2</li><li>我是li3</li></ul><button>按钮</button>
</div>
经babel转译,得到原生的React:
<script>/*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h2", null, count),/*#__PURE__*/React.createElement("ul", {className: "active"},/*#__PURE__*/React.createElement("li", null, "\u6211\u662Fli1"),/*#__PURE__*/React.createElement("li", null, "\u6211\u662Fli2")),/*#__PURE__*/React.createElement("button", null, "\u6309\u94AE"));
</script>
(因为版本问题,我自己没有转换成这样的原生React,原因见博客:jsx的转换)
不用babel的话,需要写原生的React(React.createElement
)来展示页面内容;所以JSX能够方便开发,是个语法糖,其本质就是在调用React.createElement
2. 虚拟DOM到真实DOM
(1) 、虚拟DOM的创建
React.createElement最终创建出来一个个ReactElement对象,这些对象则组成了一个JavaScript的对象树,而这个对象树就是虚拟DOM
查看ReactElement树结构(这就是虚拟DOM):
(2) 、虚拟DOM到真实DOM
流程是:
编写JSX代码
---------->经过babel转译,转成React.createElement函数的调用
--------->该函数调用生成ReactElement对象,形成虚拟DOM
--------->虚拟DOM经过渲染生成真实DOM,这个渲染的过程就是React做的。
(3) 、虚拟DOM的作用
主要的作用:
-
当更新数据时,不用将所有DOM重新渲染;新旧虚拟DOM对比,来快速决定哪些东西更新,哪些东西不用更新。
-
做跨平台应用程序。虚拟DOM的本质就是JS对象,下一步是要渲染到页面上,
- React可以将其渲染到Web应用的界面上(就是调用原生的
document.createElement
),将按钮渲染成网页的按钮button等。 - 也可以将其渲染到IOS/Android端,渲染成IOS/Android控件,将按钮渲染成移动端的UIButton控件。
- React可以将其渲染到Web应用的界面上(就是调用原生的
-
虚拟DOM帮助我们从命令式编程转到了声明式编程的模式。
你只需要告诉React希望让UI是什么状态; React来确保DOM和这些状态是匹配的;(也就是 你不需要直接进行DOM操作,不需要手动渲染。只需要写好状态(state的数据),写好页面结构即可。更改DOM,渲染的事交给React。)
五、购物车案例
实现以下这个页面及功能:
<script src="./data.js"></script><div id="root"></div><script type="text/babel">// 1. 定义类组件class App extends React.Component {// 1.1 构造函数constructor() {super()this.state = {books: books}}render () {const { books } = this.statereturn (<div><table><thead><tr><th>序号</th><th>书籍名称</th><th>出版日期</th><th>价格</th><th>购买数量</th><th>操作</th></tr></thead><tbody>{books.map((item, index) => {return (<tr key={index}><td>{index + 1}</td><td>{item.name}</td><td>{item.date}</td><td>{item.price}</td><td><button disabled>-</button>{item.count}<button>+</button></td><td><button>删除</button></td></tr>)})}</tbody></table><h2>总价格:¥311</h2></div>)}}// 2. 渲染类组件const root = ReactDOM.createRoot(document.querySelector('#root'))root.render(<App />)</script>
data.js里的数据为
const books = [{id: 1,name: '《算法导论》',date: '2006-9',price: 85.00,count: 1},{id: 2,name: '《UNIX编程艺术》',date: '2006-2',price: 59.00,count: 1}...
]
1. 总价格与格式化
(1)计算总价格:每本书的单价*数量,相加
方式一:for循环遍历计算
方式二:reduce函数
// 封装为函数getTotalPrice () {let totalPrice = this.state.books.reduce((preValue, current) => {return preValue + current.count * current.price}, 0)return totalPrice}
(2)格式化:
表格里显示价格的地方,格式都是¥xxx.xx
,因此可写个函数格式化
function formatPrice (price) {// toFixed,保留两位小数return '¥' + Number(price).toFixed(2)
}
// 应用:
//表格中价格一列
<td>{formatPrice(item.price)}</td>
//总价格
<h2>总价格:{formatPrice(this.getTotalPrice())}</h2>
2. 商品数量+和-的操作
// 加increment (index) {const newBooks = [...this.state.books]newBooks[index].count += 1this.setState({ books: newBooks })}// 减decrement (index) {const newBooks = [...this.state.books]newBooks[index].count += -1this.setState({ books: newBooks })}
可以看出,这两个操作十分相似,唯一的区别是对count的操作数不一样。所以可以进一步封装。
我们不能直接去修改state中的数据,我们要借助调用setState这个方法去修改,从而可以执行render函数更新页面。
React官方推荐的做法是使用一个新的变量浅拷贝原来的数据,然后修改结束之后把新的浅拷贝赋值给state中数据
// 商品数量变化,count为+1或-1changeCount (index, count) {const newBooks = [...this.state.books]newBooks[index].count += countthis.setState({books: newBooks})}
需要注意当数量小于或等于1时,减号按钮应该禁用。
3. 删除
数组中删除数据,用到splice
函数
// 处理删除removeItem (index) {const newBooks = [...this.state.books]// 删除数据newBooks.splice(index, 1)this.setState({ books: newBooks })}// 页面
<td><button onClick={() => this.removeItem(index)}>删除</button></td>
4. 无数据时给提示
考虑到条件渲染,当有数据时展示表格,无数据时隐藏表格。可将有数据与无数据时的页面结构封装到不同的函数里。
相关文章:

React(二) JSX中的this绑定问题;事件对象参数传递;条件渲染;列表渲染;JSX本质;购物车案例
文章目录 一、jsx事件绑定1. 回顾this的绑定方式2. jsx中的this绑定问题(1) 方式一:bind绑定(2) 方式二:使用 ES6 class fields 语法(3) 方式三:直接传入一个箭头函数(重要) 3.事件参数传递(1) 传递事件对象event(2) 传递其他参数 4. 事件绑定…...

前端开发攻略---取消已经发出但是还未响应的网络请求
目录 注意: 1、Axios实现 2、Fetch实现 3、XHR实现 注意: 当请求被取消时,只会本地停止处理此次请求,服务器仍然可能已经接收到了并处理了该请求。开发时应当及时和后端进行友好沟通。 1、Axios实现 <!DOCTYPE html> &…...

韩信走马分油c++
韩信走马分油c 题目算法代码 题目 把油桶里还剩下的10斤油平分,只有一个能装3斤的油葫芦和一个能装7斤的瓦罐。如何分。 算法 油壶编号0,1,2。不同倒法有:把油从0倒进0(本壶到本壶,无效)&…...

【Linux】Anaconda下载安装配置Pytorch安装配置(保姆级)
目录 Anaconda下载 Anaconda安装 conda init conda --v Conda 配置 conda 环境创建 conda info --envs conda list Pytorch安装配置 检验安装情况 检验是否可以使用GPU Anaconda下载 可以通过两种途径完成Anaconda安装包的下载 途径一:本地windows下…...

渗透测试导论
渗透测试的定义和目的 渗透测试(Penetration Testing)是一项安全演习,网络安全专家尝试查找和利用计算机系统中的漏洞。 模拟攻击的目的是识别攻击者可以利用的系统防御中的薄弱环节。 这就像银行雇用别人假装盗匪,让他们试图闯…...

鸿蒙学习笔记--搭建开发环境及Hello World
文章目录 一、概述二、开发工具下载安装2.1 下载开发工具DevEco Studio NEXT2.2 安装DevEco Studio 三、启动软件四、第一个应用Hello World4.1 创建应用4.2 创建模拟器4.3 开启Hyper-v功能4.4 启动虚拟机 剑子仙迹 诗号:何须剑道争锋?千人指,…...

【ArcGIS风暴】ArcGIS字段计算器公式汇总
在GIS数据处理中,ArcGIS的字段计算器是一个强大的工具,它可以帮助我们进行各种数值计算、文本处理和逻辑判断。本文将为您整合和分类介绍ArcGIS字段计算器中的常用公式,并通过实例说明它们的应用。 文章目录 一、数值计算类二、文本处理类三、日期和时间类四、逻辑判断类五、…...

探索秘境:如何使用智能体插件打造专属的小众旅游助手『小众旅游探险家』
文章目录 摘要引言智能体介绍和亮点展示介绍亮点展示 已发布智能体运行效果智能体创意想法创意想法创意实现路径拆解 如何制作智能体可能会遇到的几个问题快速调优指南总结未来展望 摘要 本文将详细介绍如何使用智能体平台开发一款名为“小众旅游探险家”的旅游智能体。通过这…...

机械臂力控方法概述(一)
目录 1. MoveIt 适用范围 2. 力控制框架与 MoveIt 的区别 3. 力控方法 3.1 直接力控制 (Direct Force Control) 3.2 间接力控制 (Indirect Force Control) 3.2.1 柔顺控制 (Compliant Control) 3.2.2 阻抗控制 (Impedance Control) 3.2.3 导纳控制 (Admittance Control…...

1971. 寻找图中是否存在路径
有一个具有 n 个顶点的 双向 图,其中每个顶点标记从 0 到 n - 1(包含 0 和 n - 1)。图中的边用一个二维整数数组 edges 表示,其中 edges[i] [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点对由 最多一条 边连接&#x…...

FLINK SQL语法(1)
DDL Flink SQL DDL(Data Definition Language)是Flink SQL中用于定义和管理数据结构和数据库对象的语法。以下是对Flink SQL DDL的详细解析: 一、创建数据库(CREATE DATABASE) 语法:CREATE DATABASE [IF…...

【Fargo】1:基于libuv的udp收发程序
开发UDP处理程序 我正在开发一个基于libuv的UDP发送/接收程序,区分发送端和接收端,设计自定义包数据结构,识别和处理丢包和乱序。 创建项目需求 用户正在要求一个使用libuv的C++程序,涉及UDP发送和接收,数据包包括序列号和时间戳,接收端需要检测丢包和乱序包。 撰写代…...

WebSocket介绍和入门案例
目录 一、WebSocket 详解1. 定义与特点:2. 工作原理:3. 应用场景: 二、入门案例 一、WebSocket 详解 1. 定义与特点: WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它允许客户端和服务器之间进行实时、双向的数据传…...

k8s集群版本升级
Kubernetes 集群版本升级是为了获得最新的功能、增强的安全性和性能改进。然而,升级过程需要谨慎进行,特别是在生产环境中。通常,Kubernetes 集群的版本升级应遵循逐步升级的策略,不建议直接跳过多个版本。 Kubernetes 版本升级的…...

XML 和 SimpleXML 简介
XML 和 SimpleXML 简介 XML(可扩展标记语言)是一种用于存储和传输数据的标记语言。它定义了一组规则,用于在文档中编码数据,以便人和机器都能理解。XML 的设计目标是既易于人类阅读,也易于机器解析。SimpleXML 是 PHP…...

MySQL 中 LIKE 语句的 `%` 和 `_` 以及 BLOB 和 TEXT 的详细解析和案例示范
1. LIKE 语句中的 % 和 _ 用法 1.1 % 通配符的用法 % 通配符代表零个或多个字符。它是 MySQL 中用于模糊匹配的强大工具之一,可以在任何字符的位置使用。 示例 1:查找以特定字符开头的记录 假设我们有一个电商订单系统的 orders 表,其中包…...

git clone卡在Receiving objects
git clone卡在Receiving objects 一直卡主 $ git clone gitxxx.git Cloning into xxx... remote: Enumerating objects: 75926, done. remote: Counting objects: 100% (18844/18844), done. remote: Compressing objects: 100% (6566/6566), done. Receiving objects: 60% (…...

vue+ant 弹窗可以拖动
通过自定义指令实现拖拽功能 在main.js里加入drag自定义指令 我自己测试时发现modal不管如何设置宽度,居中等,他的初始的left都为0,如果不设置好,容易出现点击后刚开始移动弹窗会偏移一段距离。 Vue.directive(drag, {bind(el)…...

(42)MATLAB中使用fftshift绘制以零为中心的功率谱
文章目录 前言一、MATLAB代码二、仿真结果画图 前言 在分析信号的频率分量时,将零频分量平移到频谱中心会很有帮助。本例给出绘制以零为中心的功率谱的方法。 一、MATLAB代码 代码如下: f 1; % 余弦波的振荡频率…...

Windows本地部署中文羊驼模型(Chinese-Alpaca-Pro-7B)(通俗易懂版)
最近由于项目原因需要部署大语言模型, 但碍于经济实力, 只能部署在笔记本电脑上部署量化模型, (电脑至少有16G运行内存),搜集了网上的相关部署资料仍然踩了不少坑,原因在于开源项目在不断更新,导致我们看了别人的教程仍…...

Web3的挑战与机遇:技术发展的现状分析
在Web3的世界中,去中心化和用户主权的理念正逐渐走向主流,推动了现有商业模式和技术生态系统的深刻变革。区块链技术及其核心应用之一——智能合约,正在促使这一转变的发生。智能合约的主要功能是通过自动化和预设协议执行,以减少…...

LangGraph - Hierarchical Agent Teams
本文翻译整理自 Hierarchical Agent Teams https://langchain-ai.github.io/langgraph/tutorials/multi_agent/hierarchical_agent_teams/ 文章目录 一、前言二、设置三、创建工具四、Helper Utilities五、定义代理 Team研究 Team文档写作Team 六、添加图层 一、前言 在前面的…...

2021-04-14 proteus中仿真时74HC245三态双向端口扩展输出
缘由proteus中仿真时74HC245输出时电平显示灰色(不确定电平状态)是为什么?-编程语言-CSDN问答 缘由C语言翻译单片机开关检测器-编程语言-CSDN问答 参考74ls245的工作原理及作用详解 - 电子发烧友网 参考74ls245_百度百科...

解决UNSPSC商品分类的层级不足的方法
《联合国标准产品和服务守则》(UNSPSC)是一个分层框架,旨在对产品和服务进行分类。其主要目标是通过提供统一的方法来对产品和服务进行分类,从而简化采购和供应链管理。 虽然 UNSPSC 有效地将产品分为各种商品类别,但…...

Pytest基于fixture的参数化及解决乱码问题
我们知道,Pytest是Python技术栈下进行自动化测试的主流测试框架。支持灵活的测试发现、执行策略,强大的Fixture夹具和丰富的插件支持。 除了通过pytest的parametrize标签进行参数化外,我们通过fixture的param参数也可以比较方便地实现参数化…...

使用excel.js(layui-excel)进行layui多级表头导出,根据单元格内容设置背景颜色,并将导出函数添加到toolbar
本段是菜狗子的碎碎念,解决办法请直接从第二段开始看。layui多级表头的导出,弄了两天才搞定,中途一度想放弃,还好坚持下来了。一开始用的是layui的toolbar里自带的那个导出,但是多级表头没有正常导出,单元格…...

Mysql 5.7 安装与卸载(非常详细)
一、环境介绍 操作系统:CentOS 7 MySQL:5.7 二、MySQL卸载 # 查看软件 rpm -qa|grep mysql # 卸载MySQL yum remove -y mysql mysql-libs mysql-common rm -rf /var/lib/mysql rm /etc/my.cnf 继续查看是否还有 MySQL 软件,有的话继续删…...

030 elasticsearch查询、聚合
文章目录 查询聚合查询RestHighLevelClientElasticsearchRestTemplat SpringData对ES客户端的封装:ElasticsearchRestTemplate SpringData对CRUD的封装:ElasticsearchRepository 原生ES客户端:RestHighLevelClient 查询 package com.xd.cube…...

前端工程启动工具
一些思考 在公司项目中,需要启一个新的前端工程(一个基于Webpack的React工程)。因为同一个项目中有其他的前端工程,我们最开始想的是参考另外一个工程的配置重启一个新的工程,但是又因为原来的工程用的库版本都比较老…...

游戏逆向基础-跳出游戏线程发包
附加游戏后下断点 bp ws2_32.send send函数断下后,可以看到数据地址每次都一样 可以说明这个游戏是线程发包,所以直接在数据窗口中转到这个地址,然后对这个地址下硬件写入断点。 下了硬件写入断点后可以一层一层往上面跟,确定写…...