南京网站建设公司大全,万网网站备案,能打开所有网址的浏览器,延庆网站建设师文章目录 一、jsx事件绑定1. 回顾this的绑定方式2. jsx中的this绑定问题(1) 方式一#xff1a;bind绑定(2) 方式二#xff1a;使用 ES6 class fields 语法(3) 方式三#xff1a;直接传入一个箭头函数(重要) 3.事件参数传递(1) 传递事件对象event(2) 传递其他参数 4. 事件绑定… 文章目录 一、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转译JSX2. 虚拟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指向obj2. 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/buttonbutton onClick{this.btnClick.bind(this)}按钮2/buttonbutton onClick{() this.btnClick()}按钮3/buttonbutton onClick{(event) this.btnClick(event)}按钮4/button/div)}点击按钮1默认传递了事件对象eventthis是undefined 点击按钮2默认传递了事件对象eventthis是组件实例 点击按钮3调用了btnClick函数什么参数也没传。所以event是undefinedthis是组件实例。 点击按钮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/button4. 事件绑定小案例
二、条件渲染
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 (divbutton 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 classNameitem key{item.id}h2学号: {item.id}/h2h3姓名: {item.name}/h3h1分数: {item.score}/h1/div)})}/div)}展示分数大于100的学生filter
render () {...const filterStus students.filter((item) item.score 100)return (...filterStus.map((item) {return (div classNameitem key{item.id}.../div)})...)
}展示分数大于100的前两位学生slice return (div{filterStus.slice(0, 2).map((item) {return (div classNameitem key{item.id}h2学号: {item.id}/h2h3姓名: {item.name}/h3h1分数: {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的函数这个函数会创建elementelement最终会形成元素树。每个元素就是虚拟DOM。
比如render函数里有这样一段JSX代码
divh2{count}/h2ul classNameactiveli我是li1/lili我是li2/lili我是li3/li/ulbutton按钮/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控件。 虚拟DOM帮助我们从命令式编程转到了声明式编程的模式。 你只需要告诉React希望让UI是什么状态 React来确保DOM和这些状态是匹配的(也就是 你不需要直接进行DOM操作不需要手动渲染。只需要写好状态(state的数据)写好页面结构即可。更改DOM渲染的事交给React。)
五、购物车案例
实现以下这个页面及功能 script src./data.js/scriptdiv idroot/divscript typetext/babel// 1. 定义类组件class App extends React.Component {// 1.1 构造函数constructor() {super()this.state {books: books}}render () {const { books } this.statereturn (divtabletheadtrth序号/thth书籍名称/thth出版日期/thth价格/thth购买数量/thth操作/th/tr/theadtbody{books.map((item, index) {return (tr key{index}td{index 1}/tdtd{item.name}/tdtd{item.date}/tdtd{item.price}/tdtdbutton disabled-/button{item.count}button/button/tdtdbutton删除/button/td/tr)})}/tbody/tableh2总价格311/h2/div)}}// 2. 渲染类组件const root ReactDOM.createRoot(document.querySelector(#root))root.render(App /)/scriptdata.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())}/h22. 商品数量和-的操作 // 加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 })}// 页面
tdbutton onClick{() this.removeItem(index)}删除/button/td4. 无数据时给提示
考虑到条件渲染当有数据时展示表格无数据时隐藏表格。可将有数据与无数据时的页面结构封装到不同的函数里。