React(二):jsx事件绑定、条件渲染、列表渲染、jsx的本质、购物车案例
React(二)
-
- 一、jsx事件绑定
-
- 1. this的绑定方式
- 2. jsx中绑定this的三种方式
- 3. 事件对象和传参
-
- (1)事件对象怎么传
- (2)其他参数怎么传?
- 二、条件渲染
-
- 1. 直接if-else
- 2. 三元表达式
- 3. 利用逻辑中断
- 4. 案例练习
- 5. 模拟v-show的实现
- 三、列表渲染
- 四、jsx的本质
-
- 1. babel如何转换
- 2. 虚拟DOM的生成
- 五、购物车案例
-
- 1. 总价的计算
- 2. 点击加号和减号
- 3. 删除某行数据
- 4. 没有数据时给用户提示
一、jsx事件绑定
1. this的绑定方式
1、默认绑定,独立执行:fun()
,一般绑定window,严格模式下undefined
2、隐式绑定:被一个对象执行:obj.fun() => obj
3、显式绑定:call / apply / bind,fun.bind('aaa) => String('aaa')
4、new绑定:new Fun()
,创建一个实例,this指向实例
还是之前的一些知识点,看一下下面的代码:
const obj = {foo: () => {console.log(this);}
}
const obj2 = {onclick : obj.foo
}
obj2.onclick(); //window
这种情况我们是把obj里面的方法赋值给了另一个变量,这样我们调用的话相当于进行了默认绑定,如果上面这段不好理解,那么看看下面的:
const obj = {foo: () => {console.log(this);}
}
let fun = obj.foo
fun(); //window
2. jsx中绑定this的三种方式
以下面这段代码为例:
1、显式绑定this
,之前我们了解的都是直接把函数的地址给到点击事件,但是由于es6中的函数默认开启严格模式,this指向undefined,需要手动利用bind改变this指向
2、利用箭头函数找到this。fun2
可以以一个变量的形式保存一个箭头函数(在es6中可以省略constructor
直接给变量赋值)。如果我们把一个箭头函数的地址绑定给点击事件,那么就不会有this
指向问题。(箭头函数没有自己的this
,会向上层作用域查找,而上层作用域是类的作用域,指向的当然是类的实例)
3、目前最常用的,直接写箭头函数,点击时触发一个箭头函数的回调,箭头函数可以调用另外一个函数,这样的话就是一个隐式绑定(this.fun3(),那么fun3里的this当然指向的也是类的实例),解决了this指向的问题。
class App extends React.Component {constructor() {super();this.state = {count: 0,}}fun1() {console.log(this);}fun2 = () => {console.log(this);}fun3() {console.log(this);}render() {let { count } = this.state;return (<div>{/*1.显式绑定this*/}<h2 onClick={this.fun1.bind(this)}>fun1</h2>{/*2.利用箭头函数找到this*/}<h2 onClick={this.fun2}>fun2</h2>{/*3.直接写箭头函数,箭头函数调用回调*/}<h2 onClick={() => console.log(this)}>fun3</h2><h2 onClick={() => this.fun3()}>fun4</h2></div>)}
}
root.render(<App />);
3. 事件对象和传参
(1)事件对象怎么传
让我们分别看一下这2个绑定事件的按钮:
- 按钮1:通过bind绑定this,这样的话会默认传一个事件对象event过去,直接就能输出
- 按钮2:通过箭头函数的话,需要手动传参数过去,默认传的就是event
const root = ReactDOM.createRoot(document.querySelector('#root'));
class App extends React.Component {btnClick(e) {console.log('e', e);}render() {return (<div><button onClick={this.btnClick.bind(this)}>点击奥里给</button><button onClick={(e) => this.btnClick(e)}>箭头函数</button></div>)}
}
root.render(<App />);
(2)其他参数怎么传?
同样是两种方法,看一下下面两个按钮:
- 按钮1:通过bind绑定this,传入参数,这里有个大坑,那就是bind后面传的两个参数,传过去会默认放在前两个参数位置,事件对象e就会放在第三个位置,接的时候就是
('zzy', 18, 事件对象)
,这样的话参数就会比较乱,就成了e对应zzy了,这可不行。 - 按钮2:使用箭头函数传递其他参数,这样的话参数不会乱,比较合适,按顺序传,按顺序接就欧了。但是这里要注意一个问题,就是这个事件对象的参数,如果
箭头函数没有传e
,那么就不用接收e,形参和实参一一对应就行了;而如果用上面那个按钮1,会自动传事件对象e,这个时候如果传了其他参数,会默认放在参数前几位,事件对象放最后(上面提到了)。
const root = ReactDOM.createRoot(document.querySelector('#root'));
class App extends React.Component {btnClick(e, name, age) {console.log('e', e);console.log('name', name);console.log('age', age);}render() {return (<div><button onClick={this.btnClick.bind(this, 'zzy', 18)}>bind传参</button><button onClick={(e) => this.btnClick(e, 'zzy',