一. JSX的语法
1.1. 事件绑定
1.1.1. this绑定
在事件执行后,我们可能需要获取当前类的对象中相关的属性,这个时候需要用到this
如果我们这里直接打印this,也会发现它是一个undefined
◼ 为什么是undefined呢?
原因是btnClick函数并不是我们主动调用的,而且当button发生改变时,React内部调用了btnClick函数;
而它内部调用时,并不知道要如何绑定正确的this;
◼ 如何解决this的问题呢?
方案一:bind给btnClick显示绑定this
方案二:使用 ES6 class fields 语法
方案三:事件监听时传入箭头函数(个人推荐)
const obj = {
foo: function() {
console.log('foo:' , this);
}
}
obj.foo()
const config = {
onClick: obj.foo.bind(obj) // onClick 的 this 指向的是 foo, 使用 bind 指向 obj
}
const click = config.onClick // onClick赋值给了 click,所以 click 指向的也是 foo
click() // 做了click的调用,这里的this的默认调用指向 window ,但是在 babel 模式下,this 指向 undefined
this 的四种绑定规则:
1. 默认绑定: 独立执行 foo()
2. 隐式绑定: 被一个对象执行 obj.foo() -> 此时 this 指向 obj
3. 显式绑定: call/apply/bind foo.call("aaa") ->String("aaa")
4. new 绑定: new foo() -> 创建一个对象,并且赋值给 this
btn1Click() {
// console.log(this); // 这里的 this 指向的是 undefined
this.setState({counter: this.state.counter + 1})
}
btn2Click = () => {
console.log("btn2Click:", this);
this.setState({counter: 1000})
}
btn3Click() {
console.log('btn3Click:', this);
this.setState({counter: 500})
}
// this.btn1Click 这里的this没有执行,所以不是隐式绑定
render() {
const {message, counter} = this.state
return (
<div>
{/*1. this的绑定方式一:bind 绑定*/}
<button onClick={this.btn1Click}>按钮1</button>
{/*2. this的绑定方式二:ES6 class filed*/}
<button onClick={this.btn2Click}>按钮2</button>
{/*3. this的绑定方法三:直接传入一个箭头函数(重要),当箭头函数被执行,就执行btn3Click,此时进行了一个隐式绑定,this指向的是 App*/}
<button onClick={()=>console.log("btn3Click")}>按钮3</button>
<button onClick={()=>this.btn3Click()}>按钮3</button>
<h1>当前计数: {counter}</h1>
</div>
)
}
1.1.2. 传递参数
-
event
-
btnClick(event) { console.log("btnClick", event, this ); } {/* 1.event 参数的传递*/} <button onClick={this.btnClick.bind(this)}>按钮1</button> <button onClick={(event)=> this.btnClick(event)}>按钮2</button>
-
-
额外的参数
-
btnClick(event, name, age) { console.log("btnClick", event, this ); console.log("name, age", name, age); } {/* 2.额外的参数传递*/} {/*不推荐在bind后面添加参数,因为还会向参数的最后一个形参中传递 event,参数不对应 推荐箭头函数传参,传递参数的时候数据更加清晰 */} <button onClick={this.btnClick.bind(this, 'cobe', 30)}>按钮3(不推荐)</button> <button onClick={(event)=> this.btnClick(event, 'cobe', 18)}>按钮3</button>
-
1.1.3 案例-电影列表选中
<script type="text/babel">
// 创建组件
class App extends React.Component {
constructor() {
super()
this.state = {
movies: ['大话西游', '星级穿越', '冰雪奇缘', '万里归途'],
currentIndex: 0
}
}
itemClick(index) {
// console.log('itemClick');
this.setState({currentIndex:index})
}
render() {
const {message, movies, currentIndex} = this.state
return (
<div>
<ul>
{movies.map((item, index) => {
return (
<li
class={currentIndex === index? 'active' : '' }
onClick={() => this.itemClick(index)}
>
{item}
</li>
)
})
}
</ul>
</div>
)
}
}
// 创建 root 根,渲染组件
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(<App/>)
</script>
babel官网:https://babeljs.io/repl/#?presets=react
1.2. jsx条件渲染
-
if判断
-
适合逻辑较多的情况
-
// 1.条件判断方式一:使用 if 进行条件判断 if(isReady) { showElement = <h1>开始比赛吧!</h1> } else { showElement = <h2>请提前做好准备!</h2> } return ( <div> {/* 1.方式一:根据条件给变量赋值不同的内容*/} {showElement} </div>
-
-
三元运算符
-
适合逻辑比较简单
-
<div>{ isReady ? <button>开始战斗!</button> : <h3>请立即做好准备</h3> }</div>
-
-
&&逻辑与
- 适合如果条件成立,渲染某一个组件;如果条件不成立,什么内容也不渲染;
-
-
friend: { name: 'kobe', saying: '凌晨四点钟的太阳' } {/* 3.方式三:逻辑与运算符*/} {/* 场景:当某一个值可能是 undefined 时,使用 &&进行条件判断*/} <div>{friend && <div>{friend.name + ' ' + friend.saying}</div> }</div>
-
-
v-show实现效果:主要是控制display属性是否为none
-
{/* 用 v-show */} <h2 style={{display: show? 'block':'none'}}>使用v-show通过display控制显示隐藏</h2>
-
1.3. jsx列表渲染
-
map高阶函数(重要)
-
filter:过滤掉一些内容
-
slice:截取数组中的一部分
-
key主要的作用是为了提高diff算法时的效率;
// 创建组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello",
students: [
{id: 1111, name: 'daming', score: 99},
{id: 1112, name: 'liming', score: 78},
{id: 1113, name: 'lingling', score: 110},
{id: 1114, name: 'funny', score: 100},
{id: 1115, name: 'lili', score: 140},
{id: 1116, name: 'bobo', score: 120},
]
}
}
render() {
const {message, students} = this.state
// 分数大于 100 的显示
const filterStudents = students.filter(item => {
return item.score > 100
})
// 分数大于100,且只展示两人的显示
// slice(start, end): [start, end).包含起始不包含最后的数
const sliceStudents = students.slice(0,2)
return (
<div>
<h2>学生列表数据</h2>
<div className="list">
{
students.filter(item => item.score>100).slice(0,2).map((item) => {
return (
<div className="item" key={item.id}>
<h1>学号: {item.id}</h1>
<h2>姓名: {item.name}</h2>
<h2>分数: {item.score}</h2>
</div>
)
})
}
</div>
</div>
)
}
}