每日质量NPM包事件绑定_bindme(详解React的this)

news/2024/7/24 1:40:09 标签: react, 前端

一、bindme

官方定义: is a helper to bind a list of methods to an object reference

理解: 因为 不推荐在render()里构建函数 ,作者就用了6行代码封装了函数绑定事件的代码.

bindme的npm包实际上由6行ES5代码组成,但是确实方便了很多.这个包值得一用

二、用法

代替箭头函数和多层bind

有时候我们并不会直接在创建事件的时候 bind ,而是统一在constructor上绑定事件,如果一个模块大起来,就会出现好几十行绑定事件的代码,用 bindme 可以很好解决.例如

//原写法
this.clickEvent1 = this.clickEvent1.bind(this)
this.clickEvent2 = this.clickEvent2.bind(this)
this.clickEvent3 = this.clickEvent3.bind(this)
this.clickEvent4 = this.clickEvent4.bind(this)
this.clickEvent5 = this.clickEvent5.bind(this)

//bindme写法
bindme(this, 'clickEvent1', 'clickEvent2', 'clickEvent3', 'clickEvent4', 'clickEvent5')/pre>

又好看又方便

也可以在 super 构建实例的时候绑定

bindme(super(props),
    'clickEvent1',
    'clickEvent2',
    'clickEvent3',
    'clickEvent4',
    'clickEvent5',
)

就是这么简单的用法, 我们可以看看它的源码转换成ES6是怎么样的

const bindme = (self, ...funcs) => {
  funcs.forEach(func => {
    if (self[func]) {
      self[func] = self[func].bind(self)
    } else {
      console.error(`Method ${func} is not defined`)
    }
  })
}

其实也就是收集所有的事件,再统一bind,如果不存在的抛出异常.我们在平时也会经常封装一些类似这些小的便捷操作

结合React

import React,{ PureComponent } from 'react'

import bindme from 'bindme'
import './style.css'
export default class BindmeComp extends PureComponent{
    constructor(props){
        bindme(super(props),
            'bindmeOnMouseOver'
        )

        this.initClickMode = this.initClickMode.bind(this)

        bindme(this, 'bindmeFirClickMode', 'bindmeSecClickMode')
    }

    noThisClickMode(){
        console.log('未绑定this事件 =========>', this)
    }

    initClickMode(){
        console.log('普通bind事件 ===========>', this)
    }

    arrowClickMode = () => {
        console.log('箭头函数bind事件 ===========>', this)
    }

    bindmeFirClickMode(){
        console.log('bindme事件1 ===========>', this)
    }

    bindmeSecClickMode(){
        console.log('bindme事件2 ===========>', this)
    }

    bindmeOnMouseOver(){
        console.log('bindme事件3 ===========>', this)
    }

    render(){
        return(
            <div>
                <div className="list">
                    <span>未绑定this事件</span>
                    <button onClick={ this.noThisClickMode }>点击</button>
                </div>
                <div className="list">
                    <span>普通bind事件</span>
                    <button onClick={ this.initClickMode }>点击</button>
                </div>
                <div className="list">
                    <span>箭头函数事件</span>
                    <button onClick={ this.arrowClickMode}>点击</button>
                </div>
                <div className="list">
                    <span>bindme</span>
                    <button onClick={ this.bindmeFirClickMode }>点击</button>
                </div>
                <div className="list">
                    <span>bindme2</span>
                    <button onClick={ this.bindmeSecClickMode } >点击</button>
                </div>

                <div className="list">
                    <span>bindme3</span>
                    <button onMouseOver={ this.bindmeOnMouseOver } >滑过</button>
                </div>
            </div>
        )
    }
}

上面基本覆盖了常用的事件绑定情况.我们看看都会输出什么?

可以看到,除了第一个this为undefined外,其他都是正常绑定在了组件上

扩展一下React的this

我们先从我们最熟悉js的 this 说起;

面试官经常会问,什么是this?this指向什么?

一般来说:

谁调用该 function ,该函数的this就指向这个调用方

有一个特殊的情况,ES6的箭头函数,也是面试官特别喜欢的一个东西(但它确实好用),由于箭头函数不存在this,所以它的this是由上一层继承而来的.所以可以得出结论 箭头函数的this始终指向构造时的对象,而不是使用时的对象

另外箭头函数还有一些不同于普通函数的特性,比如: 不可以当作构造函数使用,即不可以 new . 不可以使用 arguments 属性等等

总结一句话就是:

普通函数this是动态的,而箭头函数的this是静态的

我们细说一下React的this.

因为React组件是通过 class 构造的,所以组件里的所有属性,所有方法都可以通过this来获取,例如我们经常使用的属性state.就可以通过 this.state.xxx 获取

所以我们只需要保证this永远指向该构造对象(组件)即可,所以我们一般不会通过function来创建函数(会使得this动态指向调用function的对象), 并且:

React组件类的方法没有默认绑定this到组件实例,需要手动绑定。

所以就衍生出了绑定this的方法;常用的有四种,我们一般会使用在constructor里面bind

//优先级最高
constructor(props){
    super(props);

    this.handleEvent = this.handleEvent.bind(this)
}

这种和直接在构建事件中绑定很像对吧?

<input onChange={this.handleEvent.bind(this)} />

原理虽然是一样的,但是性能却差了一大截.为什么?

我们知道只要 state 值改变了,就会导致render重新渲染,如果直接在创建事件绑定,那每一次渲染的时候都需要重新绑定一次,会大大降低性能.相反,只要在构造的时候绑定,无论渲染多少次,绑定都还是一次

此外还有比较常用的箭头函数绑定法和 :: 绑定法

前面也介绍了箭头函数this的知识,所以在React出现也是蛮高的

handleEvent = () => {
    ...
}

<input onChange={this.handleEvent} /></pre>

:: 虽然也可以绑定this,但是因为不能传参数,所以不经常使用

handleEvent = () => {
    ...
}

<input onChange={::this.handleEvent} />

总结

如果你觉得不错,或者发现文章中的错误,或者有更好的建议,欢迎评论或进前端全栈群交流讨论,866109386。
(PS:内有大牛分享 css webpack node vue angular react 面试 等等的资源)


http://www.niftyadmin.cn/n/1301343.html

相关文章

微信小程序与小游戏的api能否互相调用的总结

最近一直疑惑&#xff0c;小游戏项目能调用小程序的api吗&#xff1f; 再反过来&#xff0c;小程序项目能调用小游戏里的api吗&#xff1f; 对于这个问题&#xff0c;刚开始的想法是&#xff1a; 小程序相当于前端html&#xff08;以下称html&#xff09;&#xff0c;小游戏相…

TortoiseGit界面化工具下载、git使用总结

使用git前&#xff0c;大家应该了解的几个关于git的概念。 Workspace(工作区)&#xff1a;也就是我们文件系统中的文件或文件夹 Index / Stage(暂存区)&#xff1a;也就是我们执行git add命令后文件所在的位置(当然&#xff0c;我们的工作区的内容都还在&#xff0c;只是把工…

浅析 React / Vue 跨端渲染原理与实现

当下的前端同学对 React 与 Vue 的组件化开发想必不会陌生&#xff0c;RN 与 Weex 的跨界也常为我们所津津乐道。UI 框架在实现这样的跨端渲染时需要做哪些工作&#xff0c;其技术方案能否借鉴乃至应用到我们自己的项目中呢&#xff1f;这就是本文所希望分享的主题。 概念简介…

CocosCreator小游戏项目的远程资源管理总结

现在微信小游戏的项目资源包大小已经由4M改成了8M&#xff0c;为的就是适应小游戏越来越丰富的玩法。 但是&#xff0c;就算有8M也是不足以做大部分游戏的&#xff0c;因为项目中的图片资源就有很多了&#xff0c;绝大部分游戏的资源&#xff08;除了代码&#xff09;都在10M以…

前端面试之手写一个bind方法

bind 函数对于写react的人来说并不陌生。哦&#xff01;是的&#xff0c;没错我的朋友&#xff0c;它的一个用处就是用来改变函数this指向的。如果细究一下bind的实现&#xff0c;发现里面还是有不少东西的&#xff0c;我们今天展开讨论一下。 在说bind之前呢&#xff0c;我们…

angularjs传递图片的前后端代码解析

最近工作中有用到&#xff0c;和大家分享下前后端代码&#xff1a; html部分第一个id用于文件返回参数&#xff0c;第二个是绑定onchange事件Ctrl部分var file $(#wenjianfjian2)[0].files[0];新建一个FormData对象&#xff08;文件和数据一起使用表单提交方式&#xff09;&am…

Vue篇之vue 使用Jade模板写html,stylus写css

日常工作都是使用vue开发页面和webApp,写的多了就想偷懒简化各种书写方式&#xff0c;所以使用了jade写html&#xff0c;stylus写css&#xff0c;省了很多的步骤和提高了效率。 安装包&#xff1a; // 安装jade包 npm install jade jade-loader --save-dev // 如果使用vue-cl…

CocosCreator SpriteAtlas小结

对于SpriteAtlas这个组件类&#xff0c;其实它的方法不多&#xff0c;用法也不多&#xff0c;但是有一个比较有用的功能&#xff0c;在此总结一下SpriteAtlas的这个功能。 SpriteAtlas&#xff0c;表示的是一个图集&#xff0c;个人觉得比较好的是它的getSpriteFrame方法。 比…