React之常见问题

一、合成事件

合成事件是React 模拟原生dom事件所有能力的一个对象

1. 合成事件与原生事件的区别

// 原生事件,一般在componentDidMount中进行addEventListener绑定的事件
<button onclick="handleClick()">原生事件</button>

// React合成事件
const btn = <button onClick={this.handleClick}>原生事件</button>

(1)命名方式不同:原生事件命名为小写;合成事件命名采用小驼峰。

(2)事件处理函数写法不同:原生事件中函数为字符串;合成事件中则传入的是函数

(3)阻止默认行为的方式不同:原生函数返回false即可,合成事件使用 preventDefault()

<a onclick="return false">阻止原生事件</a>

const handleClick = e => {
    e.preventDefault();
}
const clickElement = <a onClick={handleClick}>阻止合成事件</a>

2. 合成事件的特点

        1. 合成事件以事件委托方式绑定在 document上,当触发事件冒泡到document对象时,再处理合成事件函数。所以混用合成事件、原生事件时,会先执行原生事件、再执行react事件、最后真正执行document上挂载的事件

        2. React使用对象池来管理合成事件对象的创建和销毁,这样减少了垃圾的生成和新对象内存的分配,大大提高了性能。【React17中已经不再使用事件池】

        3. preventDefault()停止合成事件的事件传播。

        4. 如果dom上绑定了过多的事件处理函数,整个页面响应以及内存占用都可能会受到影响,React为了避免这类dom滥用,同时屏蔽不同浏览器之间的事件机制差异,实现了一个中间层——SyntheticEvent。

二、Fiber架构

        在 react16 引入 Fiber 架构之前,react 会采用递归对比虚拟DOM树,找出需要变动的节点,然后同步更新它们。在这个计算虚拟dom的过程中,react 会一直占用浏览器资源,时间长了会导致页面出现卡顿,影响用户体验。

        Fiber 将渲染更新过程拆分为一个个子任务,通过合理的调度机制来调控时间,每次做完一部分任务就会查看是否还有剩余空间,有的话就继续执行,没有的话就挂起当前任务,将控制器交给主线程,降低页面卡顿的概率,提升页面交互体验。

三、事件绑定方式

        第1和第2种方法在每次render时都会生成新的方法实例,性能欠缺;使用构造函数中bind和定义阶段使用箭头函数,性能更好一些。

1.render中使用bind

class App extends React.Component {
    render() {
        return <div onClick={this.handleClick.bind(this)}>test</div>
    }
}

2.render中使用箭头函数

class App extends React.Component {
    render() {
        return <div onClick={e => this.handleClick(e)}>test</div>
    }
}

3.构造函数中bind

class App extends React.Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }
}

4.定义阶段使用箭头函数

class App extends React.Component {
    constructor(props) {
        super(props);
    }
    handleClick = () => {
        console.log(this);
    }
}

四、React 响应式原理

(react是一个响应式的框架,强调我们不要直接操作dom,应该关注数据,通过数据的变化,react会自动感知到数据的变化,自动的去生成dom)

        当数据变化时,React会根据diff算法计算出dom树变化的部分,然后自动同步到虚拟dom中,最后再批量更新到真实dom,从而实现了响应式设计。

五、render触发的时机

  • 执行setState就会执行render
  • useState会判断当前值是否发生改变,改变了才执行render
  • 父组件渲染,则子组件也会渲染

六、ref

1. ref是什么

        背景:在某些情况下,需要在props父传子这种典型数据流之外,强制修改子组件,这个四组件可能是一个React实例或dom元素,这时就可以使用ref。

        React支持一种特殊属性ref,使得我们可以访问render()方法中返回的组件实例(注意:不能在函数组件使用ref属性,因为函数组件没有实例),如果是渲染组件就返回的是组件实例、如果渲染dom就返回的是具体的dom节点,这样就可以保证在任何时间总是能拿到正确的实例。适用于:1)对dom元素的焦点控制、内容播放(2)触发强制动画(3)集成第三方dom库。

2. 使用方式        

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();  //创建ref
  }
  render() {
    // 方式1:传入对象,然后使用this.myRef.current获取该节点的引用
    return <div ref = {this.myRef} />;
    // 方式2:传入字符串,然后使用this.refs.myRef.innerHTML获取该dom节点的引用
    return <div ref="myRef" />
  }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值