专栏名称: OSC开源社区
OSChina 开源中国 官方微信账号
目录
相关文章推荐
程序员小灰  ·  小灰的DeepSeek星球,马上涨价! ·  昨天  
OSC开源社区  ·  Gitee开源MCP ... ·  3 天前  
程序员的那些事  ·  3 个“芯片镖客”犯了 28 ... ·  4 天前  
程序员的那些事  ·  字节跳动:辞退 353 人,追刑责 39 人 ·  5 天前  
程序员的那些事  ·  董事长刺死CTO(2):董事长早已写好复仇名 ... ·  4 天前  
51好读  ›  专栏  ›  OSC开源社区

我的 react 组件化开发道路(三) 懒惰+执着,驱动产品的完善

OSC开源社区  · 公众号  · 程序员  · 2017-01-11 08:24

正文


程序猿注定是懒惰的,当然,这里的懒惰,并不是指生活中的懒惰,而是指在产品开发中寻求各种便捷的手段来让自己开发的更加高效,产品更加完美。


细数从开始着手写react至今已经近两个月时间了,虽然其中估计有一半时间忙工作上的事忙成狗,但是react的学习,还是犹如海绵吸水一般,获益匪浅,从一脸懵逼,到豁然开朗,再到各种踩坑、填坑中徘徊,跑得快,也应该抽空回顾下,沉淀自己,所以今天想说的,并不是各种组件的开发流程,而是在组件开发过程中遇到的坑以及解决方案。


具体项目地址: https://git.oschina.net/meichao/React-webpack


事件冒泡之坑


碰到这个问题,是在写下拉框组件的时候碰到的,问题描述:

这是完成的下拉框组件,当点击按钮时,下拉框的内容显示出来,当用户点击除了按钮部分,点击body的任何区域都会让下拉框消失(当然此时点击按钮部分也会让下拉框消失,因为此时下拉框已经出现了的),逻辑理清楚了,那么整体思路就是:需要在document.body绑定click事件,然后在按钮上绑定一个click事件,并且阻止冒泡到document.body上即可了,具体代码如下:


ComponentTool是自己写的一个工具类,bind,则为对应的元素绑定相应事件,最后是回调,unbind这刚好相反,解绑事件,然而测试的时候发现,事件还是冒泡上来了,查看元素的DOM事件可以看到:


这就有必要去看下react的事件机制了:React并不会真正的绑定事件到每一个具体的元素上,而是采用事件代理的模式:在根节点document上为每种事件添加唯一的Listener,然后通过事件的target找到真实的触发元素。这样从触发元素到顶层节点之间的所有节点如果有绑定这个事件,React都会触发对应的事件处理函数。这就是所谓的React模拟事件系统。而body是document的一个子元素,那么触发绑定在body上的事件就正常了,那么我们需要做的就是将事件绑定到document上去即可,更改了代码之后,会发现,然而并没有什么卵用,效果如下:


click还是冒泡上来了,这就头大了,难道我的冒泡没用?are you kidding me?好吧,又得得捋,stopPropagation函数只屏蔽冒泡,并不屏蔽自身的事件,这不是闹么,不过诧异的是,居然查到了stopImmediatePropagation这样的一个函数(原谅我先前的无知),stopImmediatePropagation会在调用对应的回调函数之后屏蔽对应元素对应事件所有回调函数的调用,并且禁止冒泡,OK,就它了,用起来!


报错,我的天,把event打印出来看看:


由于react代理事件的原因,这里我们得到的event仅仅是一个合成事件对象,它的主要属性如下:


想要获取浏览器事件的详情,则可以查看合成对象中的nativeEvent值:


可以看到,event.nativeEvent此时对应的是MouseEvent,即鼠标事件,代码修改为:

成功阻止事件的冒泡并且阻止了默认行为,组件能正常使用。一个简单的阻止冒泡的事件绑定,扯出了如此多的知识点~~~~。


路由资源使用require.ensure按需加载之坑


我们常规的路由设置是类似这样的(当然,其实我一开始也是这样的):


这样当我们在使用webpack这些打包工具的时候,会把所有资源一起打包进来,如果子页面很多的话,而我们的首屏却只是一个简单的页面,那么一个仅仅用到一点点资源的首屏,却要在一开始的时候去加载所有的资源,必然会卡,这对于追求首屏极致响应的前端而言,是深恶痛绝的,那么这个时候我们就可以使用require.ensure来对路由资源进行按需加载,只有当我点击某个子页面的时候,才会去加载跟这个子页面相关的资源,首屏只需要加载那些必须的资源即可,让我们来进行相应的配置:


这里做了几个简单的配置项,然后在我们的react-router引入即可,如下:


这里的route资源,就是上一张图的配置输出,因为在require.ensure中未指定每个路由资源的名字,会由其自动创建,而我们需要在webpack中设置chunkFilename:


设置完成,让我们把项目跑起来试试:







请到「今天看啥」查看全文