react入门与实战(二):JSX及react的生命周期(上)

这篇文章所包含的内容如下,方便检索:
JSX
react如何setState
react进行事件绑定
react的生命周期

正文

react的JSX

什么是JSX

jsx是一种嵌入式的类XML的语法。它可以被转换成合法的JavaScript,其实就是一个JavaScript语法扩展。类似于模板语言,但它具有JavaScript的全部能力。JSX 最终会被编译为 React.createElement()函数调用,返回称为 “React 元素” 的普通 JavaScript 对象。

react 没有强迫大家一定要用JSX,但是我觉得确实用JSX会方便很多很多!直接上代码 ↓

const element = 

Hello, world

; 等价于 var element = React.createElement("h1", null, "Hello, world"); // 在JSX中使用变量 let name = 'world' const element =

Hello, {name}

; // 在JSX中使用表达式 function a1() { return

Hello, {1 + 1}

} // 在花括号{}里面不能使用直接使用if else语句 // 条件判断 function a2(isBol) { if (isBol) { return

Hello, in..Bol

} return

Hello, {1 + 1}

} function a3(name) { return name &&

Hello, {name}

} function a4(name) { return name ?

Hello, {name}

: null } // 列表渲染1 function a5(arr) { return (arr && arr.length > 0 && arr.map((item, idx) => { const key = 'key:' + idx // 这里最好还是使用ID作为可以 // 在这里可以判断业务逻辑需要渲染啥内容 return

Hello, {item}

})) }
// 列表渲染2
function a6(arr) {
  const listItems = numbers.map((number, idx) =>
    
  • {number}
  • ); return (
      {listItems}
    ); }

    建议:使用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 咱先把刚刚装好的删了,因为提示报错,如果你也遇到这样的 别慌,重新安装即可,当然没遇到最好哈

    提示node-sass跟sass-loader版本不匹配导致

    npm i -D [email protected]
    这个4.14.1版本从何而来呢,其实是根据npm网上查看他的历史版本找到的

    查看npm的node-sass历史版本

    现在项目能够正常跑起来了,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 
    } } 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 
    } }

    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 
    } }

    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 
    } }

    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 
    } }

    上面介绍了四种常用的绑定事件方法,或许你会说,如果要传参咋办啊,接下来我一一道来。

    e表示合成事件,React 根据 W3C 规范来定义这些合成事件,所以你不需要担心跨浏览器的兼容性问题。

    事件传参写法↓

    // 1、箭头函数
    addCount (e, id) {
       console.log(e)
       console.log(id) // 123 
    }
    
    
    // 2、官网推荐bind写法
    addCount (e) { 
      console.log(e);
      console.log(e.target.getAttribute('data-id'));
    }
    
    
    // 3、直接事件bind写法
    addCount (id, e) { // 合成事件会作为后面一个参数被传入
      console.log(e)
      console.log(id) // 123 
    }
    
    
    // 4、public class fields 语法
    addCount = (e) => {
      console.log(e);
      console.log(e.target.getAttribute('data-a'));
    }
    
    

    如果要带参的话,箭头函数以及直接bind事件都比较简单

    react的生命周期

    这里说的是指React.Component的生命周期

    生命周期图

    常用的生命周期如下

    1. constructor(props)
    2. componentDidMount()
    3. componentDidUpdate(prevProps, prevState, snapshot)
    4. componentWillUnmount()

    不常用的生命周期如下

    1. shouldComponentUpdate(nextProps, nextState)
    2. static getDerivedStateFromProps(props, state)
    3. getSnapshotBeforeUpdate(prevProps, prevState)
    4. static getDerivedStateFromError(error)
    5. componentDidCatch(error, info)

    具体使用方法咱下次再聊

    项目demo我会上传到GitHub,大家有需要可自行download


    参考链接:
    jsx
    react事件处理
    react合成事件
    npm node-sass
    react lifecycle
    GitHub-demo

    你可能感兴趣的:(react入门与实战(二):JSX及react的生命周期(上))