这篇文章所包含的内容如下,方便检索:
JSX
react如何setState
react进行事件绑定
react的生命周期
正文
react的JSX
什么是JSX
jsx是一种嵌入式的类XML的语法。它可以被转换成合法的JavaScript,其实就是一个JavaScript语法扩展。类似于模板语言,但它具有JavaScript的全部能力。JSX 最终会被编译为 React.createElement()函数调用,返回称为 “React 元素” 的普通 JavaScript 对象。
react 没有强迫大家一定要用JSX,但是我觉得确实用JSX会方便很多很多!直接上代码 ↓
const element = <h1>Hello, world</h1>;
等价于
var element = React.createElement("h1", null, "Hello, world");
// 在JSX中使用变量
let name = 'world'
const element = <h1>Hello, {name}</h1>;
// 在JSX中使用表达式
function a1() {
return <h1>Hello, {1 + 1}</h1>
}
// 在花括号{}里面不能使用直接使用if else语句
// 条件判断
function a2(isBol) {
if (isBol) {
return <h1>Hello, in..Bol</h1>
}
return <h1>Hello, {1 + 1}</h1>
}
function a3(name) {
return name && <h1>Hello, {name}</h1>
}
function a4(name) {
return name ? <h1>Hello, {name}</h1> : null
}
// 列表渲染1
function a5(arr) {
return (arr && arr.length > 0 &&
arr.map((item, idx) => {
const key = 'key:' + idx // 这里最好还是使用ID作为可以
// 在这里可以判断业务逻辑需要渲染啥内容
return <h1 key={key}>Hello, {item}</h1>
}))
}
// 列表渲染2
function a6(arr) {
const listItems = numbers.map((number, idx) =>
<li key={idx}>{number}</li>
);
return (
<ul>{listItems}</ul>
);
}
建议:使用map的时候一定要加上key,让react能够知道是哪些元素做了改变。最好用当前列表的独一无二的字符串来代替,比如ID,不建议用索引index,除非实在没其他数据。vue的v-for也有key,最后的道理都是一样的 即提高diff效率。如果有机会可以单独拿来聊一聊。
react的setState
现在我们需要创建另一个my-app-test02项目(或者直接拿第一天的项目复制一份),然后在其views下创建新文件夹StateDemo
,新建StateDemo.js
(这里改成jsx也行,看个人喜好以及IDE的支持度)以及StateDemo.scss
npm i -D node-sass sass-loader
我习惯使用scss这个css预处理器,大家也可以看个人喜好,使用比如less或者是Stylus
tips:node-sass太容易安装失败了,所以失败了大家别慌,一般可以切换淘宝镜像源解决,或者你有一个好的木第孑解决,当然大家自行百度吧 一般都有,我这边不详细说,如果真搞不了可以私聊我,这些相信对大家来说都是小问题。
好吧,居然出意外了,提示sass-loader期望的node-sass版本不对
,看起来应该是node-sass有更新然后loader那边还是旧的导致,问题不大,让我看下最近的版本更新如何:
npm uninstall -D node-sass 咱先把刚刚装好的删了,因为提示报错,如果你也遇到这样的 别慌,重新安装即可,当然没遇到最好哈
npm i -D node-sass@4.14.1
这个4.14.1
版本从何而来呢,其实是根据npm网上查看他的历史版本找到的
现在项目能够正常跑起来了,
cra
默认支持sassloader,所以大家不必再去配置了。现在的项目结构如下:
....
└── src
├── ...
├── views +
└── StateDemo+
├── StateDemo.scss +
└── StateDemo.js +
import React from 'react';
import './StateDemo.scss';
class StateDemo extends React.Component {
state = {
count: 0
}
render() {
return <div className="state-demo-container">
<button onClick={() => {
this.setState({
count: this.state.count + 1
})
}}>click-{this.state.count}</button>
</div>
}
}
export default StateDemo;
以上是一个简单的累加小demo,非常简单的逻辑,点击button,计数
count
加1
你可以能会有以下的问题:
className
JSX中为何用className代替class
,因为class
是关键字
react绑定事件
都是在on+大驼峰 比如 onClick onChange
react 事件你要在JSX语法里面传入一个函数作为事件处理
,而不是一个字符串
this.setState
是什么 为何是this.state.count
先说说为何是setState
来更新数据,其实这个真要说肯定要花长篇大论,我们这作为一个简单的入门,可以先理解他是如何是用的,以后有机会或许可以提一下。
setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。这是用于更新用户界面以响应事件处理器
和处理服务器数据
的主要方式
`setState(updater, [callback])`
updater可以是俩种形式:
一种为带形参的函数
即:`(state, props) => stateChange`
this.setState((state, props) => { // props后面会说,state即定义的state
return {counter: state.counter + 1};
});
另一种为对象类型
this.setState({count: 2})
this.setState({count: 2}, () => {
// 在这个回调中能拿到全新的quantity
console.log(this.state.count)
})
你可能会说 为何我不可以直接像vue那样this.用this.state.count = xxx来更新值,如果我们了解setState原理就知道,setState不仅仅只是修改state的值,他更重要的更难是触发React的更新机制进行diff,然后更新到真实的dom里。这里仅仅要求大家先掌握更新state的方法。
vue为何能够直接触发UI更新呢?因为vue在创建UI的时候已经将data数据收集并且进行重写(setter会去触发更新)。
setState
看起来是异步的,其实这个跟他的实现原理有关。所以才会有网上很多人说他啥时候是同步啥时候是异步。其他的可以看下别的大佬写的 《你真的了解setState吗?》
react事件的写法
下面我会介绍大家几种常用的写法
1.箭头函数写法
性能差,很简单,但是每次render都会重复创建函数
import React from 'react';
import './StateDemo.scss';
class StateDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
addCount () {
this.setState({
count: this.state.count + 1
}, () => {
console.log(this.state.count);
})
}
render() {
const {count} = this.state
return <div className="state-demo-container">
<button onClick={() => this.addCount()}>click-{count}</button>
</div>
}
}
2.官网推荐bind写法
官方推荐,但是麻烦
import React from 'react';
import './StateDemo.scss';
class StateDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
this.addCount = this.addCount.bind(this)
}
addCount () {
this.setState({
count: this.state.count + 1
}, () => {
console.log(this.state.count);
})
}
render() {
const {count} = this.state
return <div className="state-demo-container">
<button onClick={this.addCount}>click-{count}</button>
</div>
}
}
3.直接事件bind写法
每次render都要bind一次,性能不好,但不太影响
import React from 'react';
import './StateDemo.scss';
class StateDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
addCount () {
this.setState({
count: this.state.count + 1
}, () => {
console.log(this.state.count);
})
}
render() {
const {count} = this.state
return <div className="state-demo-container">
<button onClick={this.addCount.bind(this)}>click-{count}</button>
</div>
}
}
4.public class fields 语法
新ES6写法,建议用这种
import React from 'react';
import './StateDemo.scss';
class StateDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
addCount = () => {
this.setState({
count: this.state.count + 1
}, () => {
console.log(this.state.count);
})
}
render() {
const {count} = this.state
return <div className="state-demo-container">
<button onClick={this.addCount}>click-{count}</button>
</div>
}
}
上面介绍了四种常用的绑定事件方法,或许你会说,如果要传参咋办啊,接下来我一一道来。
事件传参写法↓
// 1、箭头函数
addCount (e, id) {
console.log(e)
console.log(id) // 123
}
<button onClick={(e) => this.addCount(e, 123)}>click-{count}</button>
// 2、官网推荐bind写法
addCount (e) {
console.log(e);
console.log(e.target.getAttribute('data-id'));
}
<button data-id={123} onClick={this.addCount}>click-{count}</button>
// 3、直接事件bind写法
addCount (id, e) { // 合成事件会作为后面一个参数被传入
console.log(e)
console.log(id) // 123
}
<button onClick={this.addCount.bind(this, 123)}>click-{count}</button>
// 4、public class fields 语法
addCount = (e) => {
console.log(e);
console.log(e.target.getAttribute('data-a'));
}
<button data-id={123} onClick={this.addCount}>click-{count}</button>
如果要带参的话,箭头函数以及直接bind事件都比较简单
react的生命周期
这里说的是指React.Component的生命周期
常用的生命周期如下:
- constructor(props)
- componentDidMount()
- componentDidUpdate(prevProps, prevState, snapshot)
- componentWillUnmount()
不常用的生命周期如下:
- shouldComponentUpdate(nextProps, nextState)
- static getDerivedStateFromProps(props, state)
- getSnapshotBeforeUpdate(prevProps, prevState)
- static getDerivedStateFromError(error)
- componentDidCatch(error, info)
具体使用方法咱下次再聊
项目demo我会上传到GitHub,大家有需要可自行download
参考链接:
jsx
react事件处理
react合成事件
npm node-sass
react lifecycle
GitHub-demo