前言
上一篇教程中我们学习到了react的state和生命周期,而这次,我们则要开始学习react中的事件处理和条件渲染,有可能还会涉及到列表渲染,说不定,谁知道呢,让我们开始吧
事件处理
react中的事件处理和原生js中的内联事件有点类似,不过区别是
React 事件的命名采用小驼峰式(camelCase),而不是纯小写。举个例子,原生中的onclick或onblur全都会变成onClick和onBlur的形式
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。这个意味着react不像原生js那样使用双引号字符串的形式接收处理函数,而是需要接收一个真正的处理函数,比如:不能再写onClick='fn'这样的形式,而需要改成onClick={fn}这样的形式
下面我们利用代码直观地了解并学习react中的事件处理是如何编写的
class App extends React.Component {
constructor(props) {
super(props);
this.state = { data: { name: 'lily', age: '18' } };
}
render() {
return <div>{this.showInfo()}</div>;
};
showInfo() {
console.log(this);
}
}
还记得上面这个组件吗?这是我们上一次遗留下的组件,今天要把它改造下。实现鼠标点击后把state内的值修改的效果。处理过程如下:
// 第一步修改render函数,令其返回一个可供我们点击的按钮
render() {
return <button>点击修改state</button>;
};
/*
第二步则是添加事件处理函数,react的添加方式和原生js的添加方式类似,都是内联加入,注意{}就是
jsx语法了,内部可以使用类似模板字符串的语法,区别就是在JSX内的变量不需要使用${}圈起
注意,由于我们需要访问类内的函数,因此需要通过this指针访问到整个类,才能通过作用域运算符.找
到changeState这个函数
*/
render() {
return <button onClick={this.changeState}>点击修改state</button>;
};
/*
第三步是我们需要添加可以展示信息的标签,这里有个注意点,react组件返回的只能有一个根节点
这意味着我们不可以在return语句内返回多个标签,比如这样:
return (
<p>信息</p>
<button>按钮</button>
)
而应该使用一个标签(任意)包裹你需要返回的全部dom元素,比如这样:
return (
<div>
<p>信息</p>
<button>按钮</button>
</div>
)
并且当返回嵌套dom元素时需要使用()将其包裹起来,顺便说一句,如果需要在jsx中添加注释,则
为这个写法:{/**/}
*/
然后剩下的就是编写我们的处理函数了
// changeState 函数的实现,因为是写在类里面,所以可以直接写函数名加上括号作为类内的方法
// 实现起来并不复杂,主要就是利用setState覆盖掉原本的state
changeState() {
this.setState({ data: { name: 'Alice', age: 21 } });
}
注:因为处理函数会丢失this指向,所以这里的this.serState是访问不到的,此时,有两种解决方法:
在构造函数内使用bind函数绑定this到类内的函数。通过修改this.changeState内的this指向从而使得类内this.setState得以成功访问
this.changeState = this.changeState.bind(this);
使用箭头函数定义处理函数。因为箭头函数没有自己的this指向,会自动把外层的this捕获过来并指向它,也可以理解为自动指向外层this
changeState = () => {
this.setState({ data: { name: 'Alice', age: 21 } });
}
推荐使用第二种方法,这样就不用在构造器内写多余的this绑定语句了。完整的App.js的代码如下:
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { data: { name: 'lily', age: '18' } };
}
render() {
return (
<div>
<p>名称:{ this.state.data.name }</p>
<p>年龄:{ this.state.data.age }</p>
<button onClick={this.changeState}>点击修改state</button>
</div>
)
};
changeState = () => {
this.setState({ data: { name: 'Alice', age: 21 } });
}
}
export default App;
条件渲染
react实现条件渲染有三种技术方案:
通过三元运算符
const flag = true;
function App() {
return (
<div>
{ flag ? <span>flag为true</span> : <p>flag为false</p>}
</div>
)
}
使用if...else
const flag = true;
function App() {
if (flag) {
return <div>flag为true</div>
} else {
return <div>flag为false</div>
}
}
利用逻辑运算符 && 或者 ||
const flag = true;
function App() {
return (
<div>
{ flag && <span>flag为true</span> }
{ flag || <span>flag为false</span>}
</div>
)
}
注:如果模板中有较为复杂的逻辑判断,建议将其抽离为一个函数
列表渲染
react一般是通过map函数循环数组并循环渲染元素,如下:
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { data: { name: 'lily', age: '18' } };
}
render() {
const student = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Lily' }
]
return (
<div>
{ student.map(stu => <li>{stu.name}</li>) }
</div>
)
};
}
export default App;
key值添加
和vue一样,react支持使用唯一的key值用来区分复数渲染的元素,这样能够提高react渲染效率
注:如果后续需要支持删除操作,建议不要使用数组下标作为key值,因为当数组被删除后,其下标值会被重排,由于react会参考key值进行diff操作,因此可能会在之后的渲染中出现未知的错误。并且,key值只存在于react内部,并不会被直接渲染到react中
尾声
这篇关于react的知识就写到这里了,下一篇会开始对react官网的表单的受控组件、状态提升、组合和继承以及react哲学进行讨论,感谢各位的支持