【react框架】在写函数时的一些注意事项,虽然很零碎,但很重要

jsx是以回调的形式绑定事件

例子:

<button onClick={ this.showData }>点击</button> 

jsx绑定事件的时候是以回调的形式进行绑定。

怎么理解,就是当jsx解析的时候,会把{}里的内容作为日后click事件触发时执行的回调函数。

如果我们这样写onClick={ this.showData() },在jsx解析过程就直接执行了,会报错。


jsx绑定函数时使用匿名函数会有什么副作用

例如:

fn = () => {}
render() {
  return <div onClick={()=>{this.fn}}>
}

组件每次更新都不会使用缓存优化,每次都要定义一次匿名函数,并且执行。会给性能上带来一定量的损耗。


react事件和dom事件的区别

react dom上写的事件不是真实的事件,是叫做“合成事件“的东西来模拟的,通过捕获冒泡等机制把所有”事件“统一挂到react的root节点去实现事件本身。

这种合成事件,因为不依赖于具体的某项dom,所以可以做到跨平台(我猜应该是类似react的root节点一样,通过一个类似的聚合的东西去实现)。

总结

  • 为了更好的兼容性,跨平台;
  • 事件是通过事件委托方式处理的(委托给组件最外层的元素) ,为了的高效;
  • 事件会默认传递一个重写的参数event,可以通过target属性拿到绑定方法的对应dom对象等等;

关于函数this的指向

首先我们知道,在es6中class实例化后的对象是可以通过执行函数,通过函数的this拿到class上定义的属性的:

class Person {
  constructor(name, age) {
    this.name = name; // 意思是给类添加一个name属性,值为实例化后传进来的name
    this.age = age;
  }
  showName() {
    alert(this.name);
  }
}
let p1 = new Person("xiaoqiang", 123); // 实例化一个类
p1.showName(); // 正常拿到name

但是我们在jsx中绑定事件后,this的指向问题就出现了。

import React, { Component } from 'react'

export default class App extends Component {
    constructor() {
        super()
        this.str = '可以拿到吗'
    }

    state = {
        a: '1',
        b: '1'
    }
    noGoodThis() {
        console.log("this", this); // undefined
    }
    render() {
        return (
            <div onClick={this.noGoodThis}>点击</div>
        )
    }
}

这是为什么呢?

  1. 我们在jsx绑定的类中的方法,并不是像class类的实例去调用的,具体是怎么样调用的是react处理的。然后react并不会帮我们把这个函数内的this指向类实例,所以当函数通过this去获取类实例的一些方法或属性就会有问题。
  2. 类中的自定义方法默认开启了局部的严格模式,所以函数中的this为undefined

为了让内部的this指向正确,比较蠢的办法是,手动把函数的this指向实例对象。

export default class App extends Component {
    constructor() { // 构造器只会调用一次
        super()
        this.str = '可以拿到吗'
        this.noGoodThis = this.noGoodThis.bind(this); // 改变noGoodThis函数的指向
    }
    noGoodThis() { // 会被放在Acomponent的原型对象上,供实例使用
        console.log("this", this); // 正常拿到
    }
    render() { //render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
        return (
            <div onClick={this.noGoodThis}>点击</div>
        )
    }
}

当然这样去改写this很麻烦,用赋值语句的形式+箭头函数的方式就很方便。

使用箭头函数是为了onClick外部调用这个方法的时候,能通过this得到实例对象,箭头函数this指向自身环境;

export default class App extends Component {
    constructor() {
        super()
        this.str = '可以拿到吗'
    }
    noGoodThis = () => { // 这样this指向这个环境,就是实例化对象
        console.log("this", this);
    }
    render() {
        return (
            <div onClick={this.noGoodThis}>点击</div>
        )
    }
}

所以,以后在写类式组件中定义一个函数,要以箭头函数赋值的形式写。


如何阻止默认事件

在vue中模板会给我们提供一些修饰符,但在react需要使用"类似"原生的方法来阻止默认事件

export default class App extends Component {
  fn = (event) => {
    event.preventDefault() // 阻止默认事件
  }
}

它这个阻止默认事件的api应该是重写的,做了浏览器兼容处理。

好像在原生事件中阻止默认冒泡行为,也会阻止react合成事件的传播。


什么是高阶函数

满足以下其中一个条件的就是高阶函数:

  • 函数接收的参数是一个函数;
  • 函数返回的是个函数;

原生的高阶函数有:Promise、setTimeOut、很多数据类型的api等等;


函数柯里化(接收多个参数)

柯里化其实就是一个函数调用后,内部的返回函数对每个函数的入参进行统一处理的函数类型。函数柯里化可以解决jsx绑定函数时怎么传入多个参数问题:

export default class App extends Component {
    // ...
  fn = (xxx) => { // 这样就可以在jsx中以this.fn('xxx') 的参数的形式调用函数
    return (event)=>{ // 这个返回的函数变成了真正的回调,event为默认事件参数
      // 内部可对入参进行统一处理
    }
  }
}

一般不用柯里化的写法,可读性不高,用箭头函数代替:

<div onClick={ event => this.fn('a', event) }>点我</div>

啥?看不懂?其实就是{}里放了个函数,可以把event => this.fn('username', event)整体成是一个Fn,onChange={ Fn },然后react回调执行,就执行里面的this.fn('username', event)了。

这样函数就能接到多个参数:

export default class App extends Component {
  //...
  fn = (str, event)=>{
      console.log(str, event.target.value)
  }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值