全屏玩英雄联盟退出全屏的时候 其他后台软件一有响应,游戏自动退出全屏,比如qq的小购物车提示,其他软件弹窗等

&img src=&/v2-868e0e1c8ae49fadfd79a5_b.png& data-rawwidth=&1097& data-rawheight=&606& class=&origin_image zh-lightbox-thumb& width=&1097& data-original=&/v2-868e0e1c8ae49fadfd79a5_r.png&&&p&在职场中,各行各业都会接触PPT,但并不是每个人都会PPT。&/p&&p&为什么PPT大神做一份20多页PPT只需要几个小时,而小白却需要花一两周的时间,这里就涉及到一个效率问题。&/p&&p&在PPT中,有许多技巧,其中个别技巧是大部分人都不知道的,我称之为为颠覆认知的PPT神技。&/p&&p&掌握这些技巧,你的PPT制作效率将完胜你的同事们。&/p&&p&&br&&/p&&p&&b&1、高效的SmartArt&/b&&/p&&p&&br&&/p&&p&这是office软件自带的,也是PowerPoint软件中最好用的一个功能。&/p&&p&SmartArt相当于一个图表的模板,通过它,可以直接插入各种逻辑图表、图形。我们通常看到的很多优秀的PPT图表,就是通过它制作的。&/p&&img src=&/v2-7050e3f5_b.jpg& data-rawwidth=&1280& data-rawheight=&720& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&/v2-7050e3f5_r.jpg&&&p&&br&&/p&&p&插入方法很简单,直接在插入菜单栏下,选择【SmartArt】,就可以跳出一个窗口,我们选择想要的图表类型就可以了,总共有8类,177个图表。&/p&&p&&br&&/p&&img src=&/v2-b8c5aea52eb269bcfb7f326_b.png& data-rawwidth=&849& data-rawheight=&473& class=&origin_image zh-lightbox-thumb& width=&849& data-original=&/v2-b8c5aea52eb269bcfb7f326_r.png&&&p&&br&&/p&&p&我相信很多人都知道SmartArt的这个功能,但SmartArt仅仅如此吗?如果如此,利兄我就不会说是颠覆认知了。&/p&&p&&b&SmartArt还有以下两个隐藏技能&/b&&/p&&p&&br&&/p&&p&&b&文本一键转图形&/b&&/p&&p&我们在制作PPT的时候,通常都是先录入文本,然后在对文本进行美化,该用图表用图表,该换颜色换颜色。&/p&&p&比如,我们拿到下面这样一页PPT,想将正文部分进行图形化设计。通常的做法都是先插入各种形状,或者插入SmartArt图形,然后进行文本的填充。&/p&&p&&br&&/p&&img src=&/v2-4aee5dacf1b8efcbc92500_b.png& data-rawwidth=&1067& data-rawheight=&599& class=&origin_image zh-lightbox-thumb& width=&1067& data-original=&/v2-4aee5dacf1b8efcbc92500_r.png&&&p&很多人不知道,其实文本可以一键转化为SmartArt图形。&/p&&p&具体操作非常简单,直接将鼠标放在文本框内,然后右键,选择【转换为SmartArt】,选择想要的图表类型,就可以轻松实现。&/p&&p&&br&&/p&&img src=&/v2-9b8e86c566_b.jpg& data-rawwidth=&1195& data-rawheight=&711& data-thumbnail=&/v2-9b8e86c566_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1195& data-original=&/v2-9b8e86c566_r.gif&&&p&&br&&/p&&p&&b&图片一键排版&/b&&/p&&p&在制作PPT时,经常需要对图片进行排版,有时候图片非常多,排版起来就非常的慢。&/p&&p&其实SmartArt还隐藏着一个技能,就是图片的一键排版。我们可以快速的将一堆无须杂乱的图片,排版成有序、美观的PPT。&/p&&p&&br&&/p&&img src=&/v2-ca6f408ac97f2e02f113801_b.png& data-rawwidth=&806& data-rawheight=&452& class=&origin_image zh-lightbox-thumb& width=&806& data-original=&/v2-ca6f408ac97f2e02f113801_r.png&&&p&&br&&/p&&p&&br&&/p&&img src=&/v2-12939c2ecc681fd4f0fb8c_b.png& data-rawwidth=&801& data-rawheight=&450& class=&origin_image zh-lightbox-thumb& width=&801& data-original=&/v2-12939c2ecc681fd4f0fb8c_r.png&&&p&&br&&/p&&p&具体的操作,也非常简单,直接全选所有图片,然后找到【格式】菜单,这里要用到【图片版式】这个选项,里面有很多图片排版的类型。&/p&&p&&br&&/p&&img src=&/v2-dd5d4d337e765_b.jpg& data-rawwidth=&1195& data-rawheight=&717& data-thumbnail=&/v2-dd5d4d337e765_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1195& data-original=&/v2-dd5d4d337e765_r.gif&&&p&&br&&/p&&p&&b&2、神奇的F4&/b&&/p&&p&在office中,F4是一个神一样的存在,只要掌握了它,你的办公效率将会得到飞速的提升。&/p&&p&F4是一个快捷键,这个快捷键的意思就是重复上一步的操作。比如我们上一步输入了“利兄”两个字,那么按F4,就会持续的复制这两个字。&/p&&p&&br&&/p&&img src=&/v2-92cbfd7ce08ab02cd72ba4e53f366ddc_b.jpg& data-rawwidth=&666& data-rawheight=&225& data-thumbnail=&/v2-92cbfd7ce08ab02cd72ba4e53f366ddc_b.jpg& class=&origin_image zh-lightbox-thumb& width=&666& data-original=&/v2-92cbfd7ce08ab02cd72ba4e53f366ddc_r.gif&&&p&&br&&/p&&p&F4在PPT中的用法非常广泛&/p&&p&&b&首先,它相当于一个对齐工具&/b&&/p&&p&用F4复制的图形,与原图形是对齐的。&/p&&p&比如,如果我想生成4个圆,而且要保证圆之间横向对齐,间距相等,该怎么做?&/p&&p&首先,我们可以先画一个圆角矩形&/p&&p&然后,同时按住Ctrl+Shift,横向拖动鼠标复制出一个圆&/p&&p&最后,按一下F4,就会等间距复制一个圆,再按一下F4,又会等距复制出一个圆。&/p&&p&&br&&/p&&img src=&/v2-67cab7b5d6e3e9ef94a9_b.jpg& data-rawwidth=&1191& data-rawheight=&714& data-thumbnail=&/v2-67cab7b5d6e3e9ef94a9_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1191& data-original=&/v2-67cab7b5d6e3e9ef94a9_r.gif&&&p&&br&&/p&&p&&b&其次,它相当于一个格式刷&/b&&/p&&p&什么意思呢?&/p&&p&用F4,我们不仅复制出一个图形,还可以复制上一步动作中的格式样式。比如改变形状颜色。&/p&&p&&br&&/p&&img src=&/v2-eb074bebcde038_b.jpg& data-rawwidth=&1192& data-rawheight=&723& data-thumbnail=&/v2-eb074bebcde038_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1192& data-original=&/v2-eb074bebcde038_r.gif&&&p&&br&&/p&&p&同样的道理在文字中也一样,比如我们写好一个PPT,想突出一些关键的信息,我们就可以用F4进行快速的格式刷。&/p&&p&如果我们要将傅园慧个人简介中的关键信息标红,该怎么做呢?&/p&&p&我们可以先将其中的“浙江杭州”改为橘红色~然后挨个选中其它的关键信息,按一下F4,就可以了~&/p&&p&&br&&/p&&img src=&/v2-42d6cd96f0b3b208e9ad_b.jpg& data-rawwidth=&865& data-rawheight=&493& data-thumbnail=&/v2-42d6cd96f0b3b208e9ad_b.jpg& class=&origin_image zh-lightbox-thumb& width=&865& data-original=&/v2-42d6cd96f0b3b208e9ad_r.gif&&&p&&br&&/p&&p&&b&再次,它相当于一个表格工具&/b&&/p&&p&F4在不仅可以快速处理文本和形状,它还可以处理表格,比如增加表格的行数,合并单元格,更改颜色等等。&/p&&p&案例:我们要将下面的表格增加了6行,该怎么做呢?&/p&&p&做法非常简单,我们可以先下方插入一行,然后按5下F4,就可以了~&/p&&p&&br&&/p&&img src=&/v2-91c71c24c0bf965adfef_b.jpg& data-rawwidth=&866& data-rawheight=&488& data-thumbnail=&/v2-91c71c24c0bf965adfef_b.jpg& class=&origin_image zh-lightbox-thumb& width=&866& data-original=&/v2-91c71c24c0bf965adfef_r.gif&&&p&&br&&/p&&p&&br&&/p&&p&&b&3、好玩的布尔运算&/b&&/p&&p&布尔运算是office2010以上版本才有的功能,指的是形状之间的联合、组合、拆分、相交、减除。在PowerPoint软件中,我们称之为合并形状工具。&/p&&p&&br&&/p&&img src=&/v2-6479cfb191e2ce7da30f69cdd31fd492_b.png& data-rawwidth=&840& data-rawheight=&397& class=&origin_image zh-lightbox-thumb& width=&840& data-original=&/v2-6479cfb191e2ce7da30f69cdd31fd492_r.png&&&p&&br&&/p&&p&通过两个以上形状的布尔运算,我们可以得到新的形状。那么,接下来我们具体来看一看,布尔运算在PPT中的实际应用。&/p&&p&&b&镂空文字&/b&&/p&&p&镂空字就是把文字和形状进行一个组合预算,让形状中的文字呈现出一种被掏空的形态。&/p&&p&具体可以看一下效果图,你就明白了!&/p&&p&&br&&/p&&img src=&/v2-e0bea2f4bceb710a0f8f4bc8bf935dad_b.png& data-rawwidth=&881& data-rawheight=&478& class=&origin_image zh-lightbox-thumb& width=&881& data-original=&/v2-e0bea2f4bceb710a0f8f4bc8bf935dad_r.png&&&p&&br&&/p&&p&&b&具体做法:&/b&&/p&&p&第一步:首先插入一张图片做背景,然后插入形状——矩形,插入文本框输入“具体文字”,并移动到适合的位置。&/p&&p&第二步:先选中矩形,再选中文字,注意这里选中的先后顺序很重要。&/p&&p&第三步:点击绘图工具—格式—合并形状—组合,就可以得到下图中的镂空效果。&/p&&p&&br&&/p&&img src=&/v2-ed65326eae9d041c61c6ca2b2c2d2690_b.jpg& data-rawwidth=&1192& data-rawheight=&719& data-thumbnail=&/v2-ed65326eae9d041c61c6ca2b2c2d2690_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1192& data-original=&/v2-ed65326eae9d041c61c6ca2b2c2d2690_r.gif&&&p&&br&&/p&&p&&b&质感文字&/b&&/p&&p&质感文字就是将文字和背景图片进行一个相交运算,让图片背景呈现在文字内部的一种效果。&/p&&p&具体可以看一下效果图!&/p&&p&&br&&/p&&img src=&/v2-07f244f2e713b40c6b2e1b7ff497cfac_b.png& data-rawwidth=&845& data-rawheight=&475& class=&origin_image zh-lightbox-thumb& width=&845& data-original=&/v2-07f244f2e713b40c6b2e1b7ff497cfac_r.png&&&p&&br&&/p&&p&&br&&/p&&p&&b&具体做法:&/b&&/p&&p&第一步:首先插入一张有质感的背景图片,然后插入文本,并移动到适合的位置。&/p&&p&第二步:先选中背景图片,再选中文字,注意这里选中的先后顺序很重要。&/p&&p&第三步:点击绘图工具—格式—合并形状—相交,就可以得到上图中的质感文字。&/p&&p&&br&&/p&&img src=&/v2-f825da3dde5a1c0b209ac_b.jpg& data-rawwidth=&1199& data-rawheight=&717& data-thumbnail=&/v2-f825da3dde5a1c0b209ac_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1199& data-original=&/v2-f825da3dde5a1c0b209ac_r.gif&&&p&&br&&/p&&p&&br&&/p&&p&&b&图片裁剪&/b&&/p&&p&有时候,我们插入的图片素材并不能直接拿来用,这个时候就需要对图片进行一个裁剪。&/p&&p&提到裁剪大家可能想到了PPT自带的裁剪工具,但是PPT自带的裁剪功能又十分有限。&/p&&p&其实,PPT中最好用的裁剪功能就是布尔运算了。&/p&&p&具体可以看一下效果图!&/p&&p&原图片是长宽高不一样的图片。&/p&&p&&br&&/p&&img src=&/v2-82f3da4738264dca32ba76_b.png& data-rawwidth=&848& data-rawheight=&476& class=&origin_image zh-lightbox-thumb& width=&848& data-original=&/v2-82f3da4738264dca32ba76_r.png&&&p&&br&&/p&&p&&br&&/p&&p&通过图片和形状的剪除运算得到的效果图。&/p&&p&&br&&/p&&img src=&/v2-fd238fdec8_b.png& data-rawwidth=&850& data-rawheight=&472& class=&origin_image zh-lightbox-thumb& width=&850& data-original=&/v2-fd238fdec8_r.png&&&p&&br&&/p&&p&&b&具体做法:&/b&&/p&&p&第一步:插入4张人物图片,再在插入4个圆,然后将圆摆放在图片中的合适位置。&/p&&p&第二步:先选中其中一张图片,再选中圆,注意这里选中的先后顺序很重要。&/p&&p&第三步:点击绘图工具—格式—合并形状—相交,就可以得到上图的效果。&/p&&p&&br&&/p&&img src=&/v2-b650f9c5a10fe79a7acef23a4c3badcd_b.jpg& data-rawwidth=&1199& data-rawheight=&719& data-thumbnail=&/v2-b650f9c5a10fe79a7acef23a4c3badcd_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1199& data-original=&/v2-b650f9c5a10fe79a7acef23a4c3badcd_r.gif&&&p&&br&&/p&&p&&br&&/p&&p&今天的内容就到这里,下期见。&/p&&p&互动:你认为,还有哪些比较好用的PPT技巧?&/p&&p&&br&&/p&&p&&b&- END -&/b&&/p&&p&本文首发公众号【利兄日志】,转载请联系公众号授权。&/p&&p&&br&&/p&&p&利兄日志(yingxiaoxinren),关于个人成长的公众号,只写有品质的干货文章,推荐有料的学习课程,内容关于效率提升,运营,幻灯片演示,欢迎关注,与15万学员共同成长。&/p&&p&公众号回复【商务训练营】,即可加入PPT训练营&/p&&p&&br&&/p&&img src=&/v2-65c28ca5a2f185a70e39523dfa1375a2_b.jpg& data-rawwidth=&600& data-rawheight=&358& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&/v2-65c28ca5a2f185a70e39523dfa1375a2_r.jpg&&
在职场中,各行各业都会接触PPT,但并不是每个人都会PPT。为什么PPT大神做一份20多页PPT只需要几个小时,而小白却需要花一两周的时间,这里就涉及到一个效率问题。在PPT中,有许多技巧,其中个别技巧是大部分人都不知道的,我称之为为颠覆认知的PPT神技。掌…
&b&在此声明一下,只是想通过技术角度去评价框架,并无意去指责或者去嘲讽其它框架,如某些言论表达得不恰当,请私我,我可删除。对于无意义的漫骂或指责,表示不接受也不回复。&/b&&br&&br&关于React的问题,我有几点要说:&br&&br&1、React确实存在组件嵌套的性能问题,但是可以通过Redux去解耦以达到目的&br&2、对于引入immutable / reselect 对于大部分并不是必需品,组件粒度越细,state使用得越少,需要引入shouldComponentUpdate的情况越少,其实在项目中真正有用到它们的有多少呢?&br&3、React的中大型项目上的应用并不是太大的问题,国内有Ant.design已经在大量的蚂蚁金融平台和或各类内部平台上使用,尽管Vue也有,但只是实验版本,也并没有再去升级。 在国外:faceBook算大型应用吗?它本身已经就应用了React 16 Alpha 版本,以身试坑,这样算得上 React 在大型应用上有问题吗?&br&4、React是有门槛的,确实没有Mv**那么快让人容易接受,需要有一定的JS基础和开发经验。&br&5、对于理解Redux,有些人需要些更多的时间去理解,有些人却能够在短时间快速掌握,同样是在中小型应用中,确实是有些繁琐,可是我们同样可以通过Redux-Actions去简化这些繁琐。最简的Redux-actions写法如下:&br&&br&Action:&br&&div class=&highlight&&&pre&&code class=&language-text&&let increment = createAction('INCREMENT', amount =& amount);
&/code&&/pre&&/div&Reducer&br&&div class=&highlight&&&pre&&code class=&language-text&&const reducer = handleActions({
[increment]: (state, action) =& ({
counter: state.counter + action.payload
}, { counter: 0 });
&/code&&/pre&&/div&&br&1、action.playload = amount&br&2、state.counter 来自于 store.counter &br&&br&注: 在中小型应用中,这么写法,算很复杂吗?难以理解吗?推荐您往下读读我对Redux的理解。&br&&br&&br&&b&再一次题外话:很认可Vue本身带来高效率的开发和很低的学习曲线,并认可作者的努力,也觉得Vue未来能够给大家带来更多优秀的特性,但是我们不能够忽略Vue及Mvvm本身存在的问题,同时也是希望我的分享能够给大家带来个人对框架的体验。&/b&&br&&br&&br&我是从0.12版本开始使用Vue的,大概使用7个月+吧。开发的项目本身更多的是通过自定义控件,让用户更快的构建自己的游戏管理,已经接入了数十款游戏,游戏本身给公司带来的收入达到数亿计。我不敢妄自菲薄称该项目是大型项目,仅仅只是一个中小型级别的项目,我来说说在这项目中使用Vue带给我的体验。&br&&br&&b&1、Vue确实简单,文档非常清晰亲民,&/b&可是API数量太多,数次遇到的问题都是因为对API的不熟悉,同时概念太多,尽管完成了项目,但是很多地方逻辑处理得不是很让人舒服&br&&br&2、翻开代码,我依然看到我不成熟地使用&b&inherit&/b&特性所导致继承组件带来更多无意义的变量,常常因为一个变量的变化,常常影响子组件的属性,直到API官网出现了最佳实践,方知自己错误的实践。&br&&br&3、满屏的的v-mode / $watch / $on / $emit / $dispatch / $set / this.var 让我们调试问题变得更复杂,因为我不知道究竟断点该断在哪个位置,还是在视图才能够更快的找出问题,因为我一开始觉得使用它们是更轻松、更舒服的方式。我相信作者也敏锐的发现了这个问题,把$dispatch在2.0给移除掉了。&br&&br&4、更为神奇的是,我在文本框以及它的父组件使用v-model时,发现输入中文,发现中英文同时出现文本框里,我发现这个问题是在于我使用0.12.6 之后的版本才会出现,而0.12.6本身并不会有这样的问题,当然最后我使用了 v-on keyup 来解决了。我相信是我的使用姿势不太正确。&br&&br&5、pnent / Vue.Extend / ViewModel 它们的 options 重叠相同的部分太多,在项目中每个人都有自己喜欢使用的方式,假如不合理使用,可能导致,各种data不合理的出现在不同的位置。&br&&br&Vue确实是一个优秀的新秀,使用它,你并不需要担心有比较严重的bug或者性能问题,但是你仍然要担心的是在大量的删改API情况下,我如何从0.12迁移到1.x,2.0, 我有想过,我被1.x那些优异的API所感到新奇和惊喜,但是大量地使用 &b&inherit &/b&导致更新起来逻辑调整更困难了。&br&&br&相信作者对于JSX,还是有一定相法的,不然也不会去在2.0引入JSX。而恰恰地,存在一个问题,框架本身带来的可选项太多,我们如何快速的识别它们带来的副作用,让我们如何提供更优雅的方式去使用框架。那么同样的问题也存在了,究竟我们是选择JSX 还是 template呢?&br&&br&&b&而Vue 2.0删改了哪些API呢?我很无聊地去数了下,大概有30+的API,我例举下些可能大家可能曾经会用到的部分API:&/b&&br&&br&Vue:&b&(删除)&/b&&br&Vue.elementDirective
/ Vue.partial / options.replace / &br&&br&生命周期:&b&(更名)&/b&&br&init =& beforeCreate&br&ready =& mounted ? &br&compiled =& mounted? &br&&br&&b&options&/b&&b&(删除)&/b&&br&partial / elementDirectives / events &br&&br&&b&Dom(删除)&/b&&br&vm. $els / vm.$set / vm.$get / vm.$delete / vm.$dispatch / vm.$boradcast&br&vm.$appendTo / vm.$before / vm.$after / vm.$remove&br&&br&&b&Directive&/b&&b&(删除)&/b&&br&v-ref / v-el &br&&b&&br&我们相信作者删除它们是为了简化API的负担,可是这些API,是否又能够轻松的从项目中迁移呢?特别是DOM,相信大家自有定论。&/b&&br&&br&同时React也存在,使用它周围哪些库更轻松更简便更合理地开发呢?可幸好,它们是可选项,而 Redux也仅有2K代码量,想要重新实现它带来的思想是一件很轻松的事。&br&&br&使用React,让我感受到组件本身带来强内聚,搭积木式的组装体验,通过 render 函数更直观的看到 DOM 结构,这也是为什么我使用 React 的原因。&br&&br&我并不排斥任何新框架,新事物,对于任何框架我很欣赏也很钦佩框架作者的技术能力,但是我仍然不想忽视框架本身存在的问题,&b&因为没有完美的框架,只有适合的应用场景,选择自己更适合的,不是吗? &/b&&br&&br&&br&====================================&br&题主乱带节奏,带偏一帮老司机飚车飚错了方向,我就我有限的经验聊聊React解决什么痛点,以及我们为什么需要它吧。&br&&br&在此之前,我先做个声明:&br&&br&&b&框架都是为了提供某类开发场景而生的,性能只是加分项,再厉害的框架也牛不过原生撸码!&/b&&br&&br&&br&现在主流的框架&b&(主要以React/Vue/Angular为背景)都主要以有限数据状态机来解决复杂的交互应用场景、编写可控可复用的代码以及开发效率问题。而它们所谓的繁琐是相对于应用场景和人的。&/b&&br&&br&题主说到React繁琐,指的是他并没有理解&b&Flux/ReFlux/Redux&/b&为什么要撸那么多代码来实现原来仅仅只需要$.ajax就可以实现的数据交换以及组件间通讯问题。&br&&br&其实我恰恰认为它们(&b&Flux/ReFlux/Redux)&/b&并没有 优雅地解决数据交换以及组件间通讯(不喜勿喷),在我的项目中我已经拒绝再去使用它们,那样React变得更轻量了?&br&&br&可我们依然要面临组件间通讯繁琐的问题:&br&&br&1、通过父组件通过给子组件传递函数到Props,重绘父组件达到更新兄弟或兄弟的子孙组件达到目的。但是,&b&重绘父组件会导致其所有无需更新子组件重绘,同时可能导致被动更新的子组件某些与props有关联的state 被更新(state丢失)。只能通过ShouldComponentUpdate 者&/b&&b&componentWillReceiveProps去解决此类问题。&/b&&b&对于孙子以下的组件更新更加繁琐及麻烦。&/b&&br&&br&2、通过一个中转容器去解决跨组件通讯问题(例如EventEmit/Redux等),但EventEmit却没有更好地解决数据与视图分离,以及Event本身带来的闭包、隐含逻辑依赖关系和时序问题(通俗的说,项目大了,不同对象的不同的事件名称、参数和调用关系变得很乱)需要有一个很合理的解决方案。&br&&br&而我们,只不过想把&b&某些个数据&/b&发送到指定的&b&组件&/b&里执行。而我认为吸取Event/Redux等的经验。我们可以这么做:&br&&br&1、提供一个数据容器,所有数据都直接发送到该容器,这样我们可以轻松做到Redux的可预测和可回溯。&br&2、关联组件所需的数据到该数据容器。&br&&b&3、约束数据发送时,接收组件的父级及子级不允许被更新(很多人在做组件设计时,父组件接收数据A的KEY1,KEY2,而自己接收数据A的KEY2和KEY3,这样是错误的设计,应该把接收数据A的KEY1,KEY2的内容拆成一个子组件接收)&/b&&br&&br&等等,这不是和Redux差不多吗?&br&&br&&br&&b&NO, NO, NO, NO,请耐心听我说完。&/b&&br&&br&&br&&b&差异在于:&/b&&br&&br&&br&1、我们只发送数据,不需要定义ActionType等等&br&&br&&br&&b&dispatch({ key1, key2})&/b&&br&&br&&b&dispatch({ key1, key2}, reducer)&/b&&br&&br&&br&&b&注:reducer是可选项。&/b&&br&&br&&br&这样我们便可以很轻松地,将它们封装起来&br&&br&&br&&b&dispatchUser = paramter =& {&br&
// promise.all(login, xx).then(..)&br&
fetch(json).then(..)&/b&&br&&b&
// dispatch(json, state =& object.assign({}, state, json))&br&&/b&&b&dispatch(json)&/b&&b&&br&}&/b&&br&&br&&br&&br&&br&2、配置接收数据的组件&br&&b&&br&connect( state =& ({ key1, key2 })(componentA)&br&&br&class componentA {&br&
getStore(state) {&br&
this.setState( { key1: state.key })&br&
}&br&}&/b&&br&&br&&br&&b&注:假如你想默认直接更新,稍微包装一下就实现自动setState。&/b&&br&&br&&br&具体代码我最近还在开撸了,撸好了,再告诉大家。&br&&br&&b&当然使用Redux,可以借助Redux-Actions去简化我们的实现。具体可看:&a href=&///?target=https%3A///acdlite/redux-actions& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - acdlite/redux-actions: Flux Standard Action utilities for Redux.&i class=&icon-external&&&/i&&/a&&/b&&br&&br&选择React:&br&&br&1、我们可以使用最简单的JSX方式去封装我们的组件,我们只需要关注我们需要接收什么数据,以及展现什么内容, &Component A={} B={} /& 多么直观啊&br&&br&2、只要熟练JS,就能够很轻松实现绝大多数模板语法的内容&br&&br&3、因为API足够少,我们有更灵活的发挥空间&br&&br&4、开发环境下,足够丰富的错误提醒&br&&br&5、React版本迭代迁移,工作量并不大,有迁移提醒,API删改少量且迁移成本低&br&&br&6、不会引入大量的概念到React库里,保持纯净,其它周边库都是可选项。&br&&br&也有人质疑JSX,写起来不是那么的好看和直观,其实写多了,你会逐步体验到它带来的好处。例如分支判断可以拆个无状态组件等等。&br&&br&未来可能会有更多优秀的框架,但目前,选择React仍旧是一个不错的选择,不排斥Vue,但是 API 不断的删改,引入的概念这么多,如何根据这些概念给出一个最佳实践到项目中到团队中呢?这又是一个新的问题&br&&br&&b&题外话:&/b&&br&&br&
假如您只是一个营销类的推广页面,仅仅只有轮播、几个文本框的表单的极浅交互,我还是推荐大伙使用原生 / zepto / jQuery之流。&br&&br&
假如您很在意体积,计较网络环境(2G/3G)等,可以使用服务器端渲染或者无阻塞UI(即添加占位符),使用带有GZIP的CDN,React各类库绝对能够在100K以内,假如超过,建议您使用按需加载。我相信您的服务器应该会添加有304/ETAG之类的缓存。&br&&br&
对于中大型项目,React确实是优良之选,当然也可以尝试Vue去迭代中小型项目。&br&&br&=====================================================================&br&做为一个在从Angular到Vue, 最后选择React,并有实际项目经验的人告诉你。React我们需要它。&br&&br&&b&框架都只是为了开发效率和良好地组织项目代码,并不完全是为性能而生!&/b&&br&&b&框架都只是为了开发效率和良好地组织项目代码,并不完全是为性能而生!&br&框架都只是为了开发效率和良好地组织项目代码,并不完全是为性能而生!&/b&&br&&br&&b&对于只会Copy/Paste的人,很好奇,他如何很好的维护那粪池?&br&&/b&&br&&b&Angular1.x 那些丑陋的特性&/b&,其实可以用ES6 或者 Typescript 进行二次语法包装,一样能够写得很漂亮的,隐藏很多让人无奈的细节。具体可以看:&a href=&///?target=https%3A///ulfryk/angular-typescript& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - ulfryk/angular-typescript: TypeScript 1.7 annotations (decorators) for AngularJS 1.x&i class=&icon-external&&&/i&&/a&&br&&br&这些仅仅只是有限的包装,你可能还需要包装更多更多的特性,不过这样真的好吗?&br&&br&&b&Angular 2.0.0 rc.4 &/b&(目前确认的最新版本) 已经酝酿了一年多了,语法几乎完全脱离了1.x版本。它似乎要把目前主流框架和特性都要集合到一块,如vdom、rxjs、typescript等等,源码模块引入了rollup去打包框架代码,业务代码依然是webpack。 然后我们默默地打开一下它的API文档,数百个API指令(请容许我夸张地虚报了个数字),如此大而全的框架,让人唏嘘不已。依然延续了1.x的繁琐复杂的语法,当然我们不能否认它们的一锅端设计,只不过适用的场景实在是有局限性,Ionic2这个Hybird端的老搭旧已经率先同步了。&br&&br&尽管Typescript强健了我的代码,提升了我的开发效率;&br&尽管Rx革新了我的数据流,完美地封装我代码中那些不完美的代码逻辑&br&&br&但是... 我依然没有办法再去学习这几百个API。&br&&br&&b&Vue相当不错,从一开始是一个简化版的Angular1.x&/b&,一年内从0.x 一直 飚升到 2.x ,作者一人撑起了80%+的生态,几乎覆盖现在主流的特性和小库。性能一直号称业界姣姣者。&br&&br&等等,我们好像忽略了什么?&br&&br&Vue 1.x 到 2.x 开始阉割大量API和模板语法。让一直追随他的小粉丝的我,开始懵笔了,我的Vue项目已经开始准备1.3,1.4的功能开发了,而我却只能使用0.x 看着别人快乐地用着1.x, 2.x 撸啊撸。&br&&br&看着作者愉快地将某些个模板、某些个生命周期、某些个事件等等语法一而三,再而三地不断地改啊改啊的,还能愉快地跟得上这股风么?&br&&br&与此同时Vue开始在2.x引入JSX的语法, 开始有点走Angular2小邪路,对于某些新人来说,我开心地时候想用JSX,不开心地时候,我喜欢用Template语法。这样的可选项是否合适呢&br&&br&不得不说,Vue的生态、文档、性能等等各方面都都是业界的姣姣者,只可惜Vue只适合中小型项目的开发,已经开发够快,够稳定,概念够新,适合快速迭代的项目,但是对于中大型项目需要的是稳定....&br&&br&修正一下,有人说vue2.x哪里支持JSX,先晒晒作者微博上的图(侵删):&br&&br&&img src=&/f6e266da5c9beff_b.jpg& data-rawwidth=&440& data-rawheight=&714& class=&origin_image zh-lightbox-thumb& width=&440& data-original=&/f6e266da5c9beff_r.jpg&&&br&看完上图是不是感觉和React相似度已经60%+了?当然还有*.ponent,是否作者是考虑让用户安稳的过渡到JSX?还是维护JSX和Template呢?那么最佳实践是什么呢?&br&&br&&br&&b&React 是唯一一个让我真正体验到编写代码快感和舒适感。(尽管在此之前我很排斥JSX)&/b&&br&&br&简约的语法,轻量的API,组织代码时的稳健,时时刻刻让我爽到溜起....&br&&br&怎么简约轻量?可以看这里多个主流框架的语法对比:&a href=&///?target=http%3A//jeffcarp.github.io/frontend-hyperpolyglot/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Front-end Hyperpolyglot&i class=&icon-external&&&/i&&/a&&br&&br&稳定的API,每次升级都是在强化和优化,相当少少少少量的API更新,即将废弃的语法,都会有警告提示,让我们更快的升级架构。&br&&br&flux/reflux/redux 不仅仅只能用在React,也能用在Vue/Angular等等框架,仅仅只是一个数据流思想,您选择性地使用。 &br&&br&其实概念很清晰,举个Apple云很简单的例子来形容Redux:&br&&br&我们的设备(Iphone/Ipad/Mac)的照片、文档等信息,都发送到云端。而我们关联云端的设备,当云端有数据更新,就会自动更新到有关联的设备或应用里。&br&&br&而我们所说的Action 就是我们点击数据发送云端的指令;&br&&br&而我们所说的Reducer就是接口,我们需要上传照片和文档,都需要转化到 成云端可以接收的数据格式。比如图片,需要转成二进制等等。&br&&br&而云端就是我们所说的Store,存储了数据,很自然的,我们可以在云端查看数据上传历史,还原某一条数据历史等等,当然更多可以想像的功能,都可以在云端实现。&br&&br&而我们需要实现React-Redux / Vue-Redux / Angular-Reudx 等等给到给到各个设备接收数据。&br&&br&例如React的Connect,代码连接到云端接收数据并更新到组件。&br&&br&&b&React/Redux并不是没有坑:&/b&&br&&br&1、setState 大量数据时(如700多条的列表),会有点点卡顿,当然我们可以通过优化得到解决&br&2、父组件更新某个子组件数据时,需要父组件重新组织,会导致其它子组件重新组装,虽然有vdom,但是这样显得不那么人性化。而且某个子组件内部有某些个state需要保持时,会丢失。需要shouldComponentUpdate..,当然你可以把组件的数据state=》子组件的props设计得更浅一些,至多2-3层,使用 redux,只connect具体需要更新数据的组件,粒度越细越好,保证单个state只更新到一个组件,这样还能带来易组装的好处。当然粒度越细,自然代码量也上来了,你也可以采用 stateless(无状态)组件去简化代码。各中取舍,取决于您的设计。&br&3、React-Redux经常在更新时,会产生过渡使用的问题,比如说父组件和子组件都connect,结果会导致第2点所说的状态丢失和重复render问题,还会有数据穿透的问题,因为connect只比较一层state。这时引入immutable能够带来较好的效果,不过个人认为完全没有这必要。已经有大量大神使用Event的方式去解决此类问题。而我,正在考虑撸个类似于Redux的方案。&br&&br&总得来说,你需要React,它并不复杂,而是你听到的噪声太多。&br&&br&对于大型项目,推荐 Webpac 2 来构建业务代码, Rollup 来打包你的小轮子。使用Rx优化你的数据流。Typescript强健你的代码,提升你的开发效率(头一周可能会有些痛苦)。但在此之后的收益是非常高的&br&&br&对于中小型项目,推荐React/Redux/React-Router来构建你的代码&br&&br&不要担心体积,因为CDN都有GZIP,能够压到原体积最高22%比例。&br&不要担心打包慢,因为通过优化 webpack,开发环境全量打包能快到 5秒, 生产环境能快到12秒。(vendor 5m 业务代码2m多)&br&不要担心噪声多,正因为如此,你的提升才会变得更快。&br&不要担心性能问题,因为90%+的场景下,你并不需要考虑性能问题。&br&不要开发效率问题,前人种树,后人乘凉的感受,会让你更舒适。&br&&br&不要说React复杂,因为比起Angular、Vue要简单些。只不过没有更好的最佳实践和文档,所以你迷失了。&br&&br&React 有 Flux/Reflux /Redux ,你只需要选择 Redux,Vue也同样有Vuex&br&React 需要 webpack / es6 等, Vue也同样需要webpack / es6,只是有它有 Vue-cli架手脚,但是React也有各种boilerplate。&br&比如:&a href=&///?target=https%3A///mxstbr/react-boilerplate& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - mxstbr/react-boilerplate: A highly scalable, offline-first foundation with the best developer experience and a focus on performance and best practices.&i class=&icon-external&&&/i&&/a&&br&&br&再比如最新的 webpack 2 / React hot Loader 3 boilerplate:
&a href=&///?target=https%3A///ctrlplusb/react-universally& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - ctrlplusb/react-universally: An ultra low dependency node v6 universal react boilerplate with an amazing dev experience.&i class=&icon-external&&&/i&&/a&&br&&br&&br&请Vue/Angular粉不要骂我,我就照我的经历说,有什么说得不对,还望纠正。
在此声明一下,只是想通过技术角度去评价框架,并无意去指责或者去嘲讽其它框架,如某些言论表达得不恰当,请私我,我可删除。对于无意义的漫骂或指责,表示不接受也不回复。 关于React的问题,我有几点要说: 1、React确实存在组件嵌套的性能问题,但是可…
&p&本来只想提醒一下然后顺便介绍一下 Tagged Template,没想到引起了一起圣战,我真的不是故意的。。。&/p&&p&==============以下正文==============&/p&&br&&p&前段时间&a href=&/?target=https%3A//xieranmaya.github.io/fe-training/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&上课&i class=&icon-external&&&/i&&/a&的时候,用到了 ES6 的模板字符串,大概写了下面这样一段代码:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&c&/span& &span class=&o&&=&/span& &span class=&mi&&5&/span&
&span class=&kd&&var&/span& &span class=&nx&&factor&/span& &span class=&o&&=&/span& &span class=&mi&&30&/span&
&span class=&nx&&card&/span&&span class=&p&&.&/span&&span class=&nx&&style&/span&&span class=&p&&.&/span&&span class=&nx&&transform&/span& &span class=&o&&=&/span& &span class=&sb&&`perspective(1000px) rotateX(&/span&&span class=&si&&${&/span&&span class=&o&&-&/span&&span class=&nx&&c&/span&&span class=&o&&/&/span&&span class=&nx&&factor&/span&&span class=&si&&}&/span&&span class=&sb&&deg)`&/span&
&/code&&/pre&&/div&&p&因为赋值字符串比较复杂,为了方便,我就用了 ES6 里的模板字符串。&/p&&p&然而有一会儿我又想不给这个属性赋这个字符串,同时又想调试的时候方便的查看这个字符串以确认我是不是拼错了,于是我把代码改成了下面这样:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&c&/span& &span class=&o&&=&/span& &span class=&mi&&5&/span&
&span class=&kd&&var&/span& &span class=&nx&&factor&/span& &span class=&o&&=&/span& &span class=&mi&&30&/span&
&span class=&nx&&card&/span&&span class=&p&&.&/span&&span class=&nx&&style&/span&&span class=&p&&.&/span&&span class=&nx&&transform&/span& &span class=&o&&=&/span&
&span class=&sb&&`perspective(1000px) rotateX(&/span&&span class=&si&&${&/span&&span class=&o&&-&/span&&span class=&nx&&c&/span&&span class=&o&&/&/span&&span class=&nx&&factor&/span&&span class=&si&&}&/span&&span class=&sb&&deg)`&/span&
&/code&&/pre&&/div&&p&注意区别,即让 card.style.transform = 独自成一行,然后我视情况把这一行给注释掉,这样就可以在不赋值的同时又可以在调试的时候选中下面一行的模板字符串然后 hover 上去看到字符串的值,就像下面这个图里一样&/p&&img src=&/v2-15a0663cee1b8a2f64f28_b.png& data-rawwidth=&605& data-rawheight=&294& class=&origin_image zh-lightbox-thumb& width=&605& data-original=&/v2-15a0663cee1b8a2f64f28_r.png&&&p&然而在我把等号那一行注释掉的时候,代码竟然报错了,而且错误很奇怪:TypeError: 30 is not a function.&/p&&p&唉嘿?30 为什么会被当函数调用?&/p&&p&我一开始以为是注释那一行的问题,然后就把注释的那一行整个删掉了,然而错误还是会出现(很显然啊)。&/p&&p&然后我尝试给模板字符串那一行加上一个前置分号,这下错误就没有了。&/p&&p&于是乎问题明白了:其实是这两行被连在一起执行了。可是问题还没完,为什么连在一起执行会把前面一行的 30 当成函数呢?既然如此,那我就把 30 改成一个函数,看看函数会接收到什么参数好了,于是我把代码改成下面这样:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&x&/span& &span class=&o&&=&/span& &span class=&mi&&42&/span&
&span class=&kd&&var&/span& &span class=&nx&&f&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&arguments&/span&&span class=&p&&)&/span&
&span class=&p&&}&/span&
&span class=&sb&&`foo&/span&&span class=&si&&${&/span&&span class=&nx&&x&/span&&span class=&si&&}&/span&&span class=&sb&&bar\\`&/span&
&/code&&/pre&&/div&&p&控制台确实 log 出了一个 arguments 对象,说明函数确实被调用了,打出的参数中,第一个实参是一个数组,内容为 ['foo', 'bar'],第二个是 x 的值,即 8。&/p&&p&进一步展开第一个参数的内容,看到它虽然是一个数组,但还有额外的一个 raw 属性,依然指向一个数组,也是 ['foo', 'bar']。&/p&&p&(看到 raw 让我想起了 Python 里的原始字符串。)&/p&&p&即函数 f 是以如下形式被调用的:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&firstArg&/span& &span class=&o&&=&/span& &span class=&p&&[&/span&&span class=&s1&&'foo'&/span&&span class=&p&&,&/span& &span class=&s1&&'bar'&/span&&span class=&p&&]&/span&
&span class=&nx&&firstArg&/span&&span class=&p&&.&/span&&span class=&nx&&raw&/span& &span class=&o&&=&/span& &span class=&p&&[&/span&&span class=&s1&&'foo'&/span&&span class=&p&&,&/span& &span class=&s1&&'bar'&/span&&span class=&p&&]&/span&
&span class=&nx&&f&/span&&span class=&p&&(&/span&&span class=&nx&&firstArg&/span&&span class=&p&&,&/span& &span class=&mi&&8&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&如下图所示:&/p&&img src=&/v2-af1c24c69fc1a1257dbb402_b.png& data-rawwidth=&517& data-rawheight=&735& class=&origin_image zh-lightbox-thumb& width=&517& data-original=&/v2-af1c24c69fc1a1257dbb402_r.png&&&br&&p&什么情况,为什么把函数跟模板字符串连着写会让函数运行?而且还会给函数传入了特定的参数,这肯定是 ES6 中新的语法!而且这几句代码的执行结果也不是最后一句表达式的值,而是 undefined。而且 raw 数组里为什么会显示两个反斜杠,这其中必有蹊跷。&/p&&p&(另外这让我想起了 2010 年左右的时候,字符串后面紧跟一个正则表达式相当用调用字符串上的 match 方法并传入那个紧跟着的正则表达式,但后来这个语法又不能用了。我一直很奇怪到底是什么情况,有机会我一定要问一下贺老师,谁帮我爱特一下~~)&/p&&p&去年看《Understanding ES6》时,隐约记得 ES6 中增加了一个类似 Python 的 r'foobar' 这样的字符串表达方式,可以让字符串的内容就为书写时的内容而忽略转义。好像是这么书写:“raw反引号foobar反引号”(反引号没有全角的,只能用文字替代了)。&/p&&p&于是我决定查文档。&/p&&p&最终在 Understanding ES6 中翻出了相应的&a href=&/?target=https%3A///understandinges6/read%23leanpub-auto-template-literals& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&章节&i class=&icon-external&&&/i&&/a&(这时我才想起来,去年读《Understanding ES6》的时候,这本书还没写完,当时并没有这一节):&/p&&p&& A &em&template tag&/em& performs a transformation on the template literal and returns the final string value.&/p&&p&原来,在一个函数后面紧跟一个模板字符串是 ES6 中的新语法,叫做“tagged template”,形如以下(其中 tag 是一个函数):&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&tag&/span&&span class=&sb&&`the string&/span&&span class=&si&&${&/span&&span class=&nx&&a&/span&&span class=&si&&}&/span&&span class=&sb&& to&/span&&span class=&si&&${&/span&&span class=&nx&&b&/span&&span class=&si&&}&/span&&span class=&sb&& be tagged`&/span&
&/code&&/pre&&/div&&p&如果这么写,模板字符串并不会直接被插值,而是会被拆成各个部分然后把各个部分按一定形式传给这个 tag 的函数。而根据 ASI 的规则,文章开头的代码中,并不会在函数与模板字符串之间插入一个分号,而模板字符串的前面的表达式总会被认为是一个函数,这就导致如果模板字符串的左边不是函数的话,就会报 TypeError 错误。&/p&&p&所以最终的结论就是:原来需要加分号的 5 种情况(+,-,[,(,/)又加了一种,即模板字符串如果出现在行首,其(即反引号:“`”)前面也要加上分号(或者在其前一行的末尾加上分号)&/p&&p&为了确认这一点,我用 Babel 分别编译了下面两段代码:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&a&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(){}&/span&
&span class=&sb&&`foobar`&/span&
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&a&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(){};&/span&
&span class=&sb&&`foobar`&/span&&span class=&p&&;&/span&
&/code&&/pre&&/div&&p&得到的结果分别如下(注意分号):&/p&&img src=&/v2-3626cbbaf20ce713e1baea80_b.png& data-rawwidth=&951& data-rawheight=&765& class=&origin_image zh-lightbox-thumb& width=&951& data-original=&/v2-3626cbbaf20ce713e1baea80_r.png&&&img src=&/v2-14f8553cfb0a76bd82777_b.png& data-rawwidth=&951& data-rawheight=&765& class=&origin_image zh-lightbox-thumb& width=&951& data-original=&/v2-14f8553cfb0a76bd82777_r.png&&&br&&p&说明,这两种情况确实会被引擎理解为不一样的语义。&/p&&p&下面,来解释一下 Tagged Template 的用法吧,随便 YY 了一下发现这玩意可以玩出很多花样。&/p&&p&首先,Tag 函数的第一个参数是一个数组,数组的各项是模板字符串的被插值符号分成的各个部分,各部分的内容是已经转义过后的值。同时,这第一个数组参数还有一个 raw 属性,也是个数组,它的各项也是模板字符串的各部分,但是,是未被转义的内容,即反斜杠会被保留!Tag 函数从第二个参数开始,分别是每个插值部分表达式的计算结果。Tag 函数的返回值会做为这个 Tagged Template 的结果。&/p&&p&举个例子:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&a&/span& &span class=&o&&=&/span& &span class=&mi&&2&/span&
&span class=&kd&&var&/span& &span class=&nx&&b&/span& &span class=&o&&=&/span& &span class=&mi&&4&/span&
&span class=&kd&&function&/span& &span class=&nx&&t&/span&&span class=&p&&(){&/span&
&span class=&p&&}&/span&
&span class=&nx&&t&/span&&span class=&sb&&`abc\\def&/span&&span class=&si&&${&/span&&span class=&nx&&a&/span&&span class=&si&&}&/span&&span class=&sb&&foo&/span&&span class=&err&&\&/span&&span class=&sb&&nbar&/span&&span class=&si&&${&/span&&span class=&nx&&a&/span&&span class=&o&&*&/span&&span class=&nx&&b&/span&&span class=&si&&}&/span&&span class=&sb&&`&/span&
&/code&&/pre&&/div&&p&在上例中,tag 函数 t 将会接收到 3 个参数,第一个为一个数组,第二个为 2,即表达式 a 的计算结果,第三个为 8,即表达式 a * b 的计算结果。&/p&&p&而第一个参数指向的数组有两项,内容为【abc\def】(注意反斜杠为字符串内容的一部分)和【foo回车bar】而这个数组有一个raw属性,其值为【abc\\def】和【foo\nbar】,注意全角引号内所看到的即为字符串的内容,反斜杠部分被保留下来了(因为知乎专栏的编辑器也会转义,所以我用了全角斜杠表示)。&/p&&p&那么,这玩意儿能怎么玩呢?&/p&&p&首先,如果你有一个函数接收一个字符串做为参数,那么写成 tagged string 是可以变的很简单的,因为使用 tagged string 你可以拿到字符串转义之前的内容:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&raw&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&parts&/span&&span class=&p&&){&/span&
&span class=&k&&return&/span& &span class=&nx&&parts&/span&&span class=&p&&.&/span&&span class=&nx&&raw&/span&&span class=&p&&.&/span&&span class=&nx&&join&/span&&span class=&p&&(&/span&&span class=&s1&&''&/span&&span class=&p&&)&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&上面的 raw 函数没有处理插值的情况,会忽略掉所有插值的部分。其实 String 上已经有了一个这样功能的函数了:【String.raw反引号\\\\反引号】将得到内容为 4 个反斜杠的字符串,并且能够处理插值的情况。&/p&&p&使用正则表达式构造函数创建正则对象就可以这么写了:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&new RegExp(String.raw`\d+`, 'gi')
&/code&&/pre&&/div&&p&而不用像以前需要多重转义:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&k&&new&/span& &span class=&nb&&RegExp&/span&&span class=&p&&(&/span&&span class=&s1&&'\\d+'&/span&&span class=&p&&,&/span& &span class=&s1&&'gi'&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&当然,上面的写法好像有点脱裤子放屁,因为在JS里可以写成正则直接量。但如果你想要通过字符串来创建其它的对象,则使用这种写法会简便很多。&/p&&p&然而需要注意的是 String.raw\\\ 是不行的,因为这么写的话最后一个反引号在写的时候就被反斜杠转义了,会报语法错误,所以反斜杠连续出现的时候必须出现偶数次。&/p&&p&另一点,模板字符串的插值部分是可以继续出现模板字符串的,只要嵌套正确,是不会报语法错误并且也没有歧义的:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&s&/span& &span class=&o&&=&/span& &span class=&sb&&`&/span&
&span class=&sb&&
&div&&/span&
&span class=&sb&&
&/span&&span class=&si&&${&/span&
&span class=&sb&&`abc`&/span& &span class=&o&&+&/span& &span class=&sb&&`def`&/span&
&span class=&si&&}&/span&&span class=&sb&&&/span&
&span class=&sb&&
&/div&&/span&
&span class=&sb&&`&/span&
&/code&&/pre&&/div&&p&那么它还可以有什么玩法呢?&/p&&p&比如说可以在 js 里更方便的表达 html,加上合适的语法高亮,是可以很简洁的,此处只谈脑洞,不考虑可行性:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&function&/span& &span class=&nx&&p&/span&&span class=&p&&(&/span&&span class=&nx&&literals&/span&&span class=&p&&){&/span&
&span class=&c1&&//此处实现忽略&/span&
&span class=&p&&}&/span&
&span class=&kd&&function&/span& &span class=&nx&&a&/span&&span class=&p&&(&/span&&span class=&nx&&literials&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&s1&&'&a&'&/span& &span class=&o&&+&/span& &span class=&nx&&literials&/span&&span class=&p&&.&/span&&span class=&nx&&join&/span&&span class=&p&&(&/span&&span class=&s1&&''&/span&&span class=&p&&)&/span& &span class=&o&&+&/span& &span class=&s1&&'&/a&'&/span&
&span class=&p&&}&/span&
&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&body&/span&&span class=&p&&.&/span&&span class=&nx&&innerHTML&/span& &span class=&o&&=&/span& &span class=&nx&&p&/span&&span class=&sb&&`&/span&
&span class=&sb&&The quick brown fox &/span&&span class=&si&&${&/span&&span class=&nx&&a&/span&&span class=&sb&&`jumps`&/span&&span class=&si&&}&/span&&span class=&sb&& over the lazy dog.&/span&
&span class=&sb&&`&/span&
&/code&&/pre&&/div&&p&从使用上讲,你可以把一对反引号当成是以另一种形式的函数调用,然后我们又可以方便的拿到代码中书写的值(转义和非转义的),理论上甚至可以做到不编译就实现 React 的 jsx 语法(性能当然不如编译好了,但性能和可行性暂且不论):&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&Button&/span& &span class=&o&&=&/span& &span class=&nx&&React&/span&&span class=&p&&.&/span&&span class=&nx&&CreateClass&/span&&span class=&p&&()&/span&
&span class=&kd&&var&/span& &span class=&nx&&btnText&/span& &span class=&o&&=&/span& &span class=&s1&&'提交'&/span&
&span class=&c1&&//注意下面一行的模板字符串会先与左边的 render 函数结合&/span&
&span class=&c1&&//所以 to 函数是 render 返回的对象上的方法。&/span&
&span class=&c1&&//另外 to 方法是我 YY 出来的&/span&
&span class=&nx&&ReactDOM&/span&&span class=&p&&.&/span&&span class=&nx&&render&/span&&span class=&sb&&`&Button text=&/span&&span class=&si&&${&/span&&span class=&nx&&btnText&/span&&span class=&si&&}&/span&&span class=&sb&&/&`&/span&&span class=&p&&.&/span&&span class=&nx&&to&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&body&/span&&span class=&p&&)&/span&
&span class=&c1&&//你可能会认为这上面这种写法跟下面没什么区别&/span&
&span class=&c1&&//那请考虑一下下面的代码如何拿到当前作用域内的 btnText 变量的值&/span&
&span class=&nx&&ReactDOM&/span&&span class=&p&&.&/span&&span class=&nx&&render&/span&&span class=&p&&(&/span&&span class=&s1&&'&Button text={btnText}/&'&/span&&span class=&p&&).&/span&&span class=&nx&&to&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&body&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&总之,可以很方便的实现自己的 DSL。&/p&&p&以后有脑洞了我再补上来~&/p&&p&最后,虽然需要写分号的情况多了一种,但这种也像其它几个符号一样,并不常见,所以也不用太在意,只要在出现问题的时候知道是怎么回事就好。&/p&
本来只想提醒一下然后顺便介绍一下 Tagged Template,没想到引起了一起圣战,我真的不是故意的。。。==============以下正文============== 前段时间的时候,用到了 ES6 的模板字符串,大概写了下面这样一段代码:var c = 5
var factor = 30
card.style…
&blockquote&&p&React.js 作为前端框架的后起之秀,却在2015年携着虚拟 DOM,组件化,单向数据流等利器,给前端 UI 构建掀起了一波声势浩大的函数式新潮流。新鲜出炉的一篇 React.js 最佳实践,基本涵盖了所有的 React.js 生态周边,可用于实践参考。文章不仅表明了 Flux 经常被滥用的观点,也推荐开发者使用 Redux 作为 JavaScript 的可预测状态容器,并且提出保持状态扁平化和使用 Immutable.js 等数据处理解决方案。与此同时,也从高阶组件,组件测试以及组件级别热重载等方面提供了建议,当然也涉及了 Webpack,HTTP 2,使用 ES2015 乃至 Linters 等代码层面的建议。&/p&&/blockquote&&br&&br&不得不吐槽知乎编辑器的渣渣功能,更佳阅读效果,可以到我的博客看&b&双语版:&a href=&///?target=http%3A///-React.js-Best-Practices-for-2016& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【译】展望2016,React.js 最佳实践 (中英对照版)&i class=&icon-external&&&/i&&/a&&/b&&br&&br&&img src=&/69f338a90e10d8ee033390_b.png& data-rawwidth=&1440& data-rawheight=&775& class=&origin_image zh-lightbox-thumb& width=&1440& data-original=&/69f338a90e10d8ee033390_r.png&&&br&------&br&&br&&b&&br&【译】展望2016,React.js 最佳实践&/b&&p&原文地址:&&a href=&///?target=https%3A///react-js-best-practices-for-2016/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&React.js Best Practices for 2016&i class=&icon-external&&&/i&&/a&&&/p&&br&&p&过去的2015年,&strong&&a href=&///?target=http%3A//a%2520javascript%2520library%2520for%2520building%2520user%2520interfaces/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&React&i class=&icon-external&&&/i&&/a&&/strong& 在全世界范围都是一派欣欣向荣的景象,开发者会议无一不热衷于这个话题。在过去一年中发生了很多重要的里程碑事件,更多详情可以查看我们关于 &a href=&///?target=https%3A///react-in-2015/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&React in 2015&i class=&icon-external&&&/i&&/a& 的总结。&/p&&br&&p&在新的2016年里,最有趣的问题来了:&strong&我们该如何开发一个应用&/strong&,有什么推荐使用的库?&/p&&blockquote&&p&作为一名长时间使用 React.js 的开发者来说,我对这个问题有自己的答案以及最佳实践,但也有可能你不会完全认同。我也非常乐于倾听你的想法和观点:请留言以便讨论。&/p&&/blockquote&&img src=&/be3fde2bd364b1b66375e7a_b.png& data-rawwidth=&600& data-rawheight=&167& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&/be3fde2bd364b1b66375e7a_r.png&&&br&&p&如果你才刚刚开始学习 React.js,可以查看我们的 &a href=&/question//answer/The%20React.js%20Way:%20Getting%20Started%20Tutorial& class=&internal&&React.js 教程&/a&,或者 Pete Hunt 所写的 &a href=&/question//answer/GitHub%20-%20petehunt/react-howto:%20Your%20guide%20to%20the%20(sometimes%20overwhelming!& class=&internal&&React howto&/a& React ecosystem.)。&/p&&br&&b&数据处理&/b&&br&&br&&p&在 React.js 应用中处理数据轻而易举,与此同时亦充满挑战。这是因为你可以通过各种方式将属性数据传递给 React 组件,并从中构建渲染树;然而这种方式也并非那么显而易见,到底该如何更新视图。2015之初诞生了很多不同 Flux 库,并不断产出了更加实用的响应式方案。&/p&&br&&p&让我们看看现在的情况:&/p&&br&&br&&b&Flux&/b&&br&&br&&i&根据我们的经验,Flux 经常被滥用,(这意味着大家总是在不需要的时候就用上它)。&/i&&br&&p&Flux 提供了一种非常清晰的方式来存储和更新应用状态,并且只会在必要的时候才触发页面渲染。&/p&&p&Flux 致力于&strong&应用的全局状态管理&/strong&,比如:管理已登录用户状态,路由状态,或者是活跃账户状态,但若是用来管理临时数据或者本地数据,瞬间就变成了痛苦。&/p&&br&&p&我们不推荐使用 Flux 来管理路由相关的数据,比如 /items/:itemId。而只是获取路由数据并存储在组件的 state 之中。在这种情况下,它会在组件消失之后一起被销毁。&/p&&br&&p&&em&如果你想了解更多关于 Flux 的信息,&a href=&///?target=http%3A//the%2520evolution%2520of%2520flux%2520frameworks/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&The Evolution of Flux Frameworks&i class=&icon-external&&&/i&&/a& 非常值得一读。&/em&&/p&&br&&br&&b&使用 Redux&/b&&blockquote&&p&Redux 是一个 &i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i& 应用的可预测状态容器。&/p&&/blockquote&&br&&p&如果你觉得需要 Flux 或者一种类似的解决方案,你应该了解一下 &a href=&/question//answer/GitHub%20-%20reactjs/redux:%20Predictable%20state%20container%20for%20JavaScript%20apps& class=&internal&&redux&/a&,以及学习 &a href=&///?target=https%3A///dan_abramov& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Dan Abramov&i class=&icon-external&&&/i&&/a& 的&a href=&///?target=http%3A//getting%2520started%2520with%2520redux/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Getting started with redux&i class=&icon-external&&&/i&&/a& 课程,这能够迅速提高你的开发技能。&/p&&blockquote&&p&Redux 延续并改进了 Flux 的思想,并从 Elm 架构中取经,规避了 Flux 的复杂度。(译者注:Elm 是一门面向 Web 的函数式编程语言,致力于改善客户端 Web 编程体验。)&/p&&/blockquote&&br&&b&保持状态扁平化 &/b&&br&&p&API 经常会返回嵌套资源。这在 Flux 或基于 Redux 的架构中处理起来会非常困难。我们推荐使用 &a href=&/question//answer/GitHub%20-%20gaearon/normalizr:%20Normalizes%20nested%20JSON%20according%20to%20a%20schema& class=&internal&&normalizr&/a& 之类的库将数据进行扁平化处理,&strong&保持状态尽可能地扁平化&/strong&。&/p&&br&&p&示意:&/p&&div class=&highlight&&&pre&&code class=&language-text&&const data = normalize(response, arrayOf(schema.user))
state = _.merge(state, data.entities)
&/code&&/pre&&/div&&p&&em&(我们使用 &a href=&///?target=http%3A//isomorphic-fetch/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&isomorphic-fetch&i class=&icon-external&&&/i&&/a& 来与 APIs 进行交互)&/em&&/p&&br&&br&&b&使用 immutable 状态&/b&&blockquote&&p&共享的可变性状态乃万恶之源。 —— &em&Pete Hunt, React.js Conf 2015&/em&&/p&&/blockquote&&img src=&/adf2f172e2c48_b.png& data-rawwidth=&629& data-rawheight=&187& class=&origin_image zh-lightbox-thumb& width=&629& data-original=&/adf2f172e2c48_r.png&&&br&&p&&a href=&///?target=http%3A//immutable%2520object/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不可变对象&i class=&icon-external&&&/i&&/a&是一种在创建之后就不可修改的对象。不可变对象可以让我们免于痛楚,并通过引用级别的比对检查来&strong&改善渲染性能&/strong& 。比如说在 shouldComponentUpdate 中:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span class=&nx&&shouldComponentUpdate&/span&&span class=&p&&(&/span&&span class=&nx&&nexProps&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// instead of object deep comparsion&/span&
&span class=&k&&return&/span& &span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&props&/span&&span class=&p&&.&/span&&span class=&nx&&immutableFoo&/span& &span class=&o&&!==&/span& &span class=&nx&&nexProps&/span&&span class=&p&&.&/span&&span class=&nx&&immutableFoo&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&br&&p&&strong&如何在 &i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i& 中实现不可变呢?&/strong&&/p&&br&&p&最痛苦的方式就是小心为之,示例代码如下,你需要在单元测试中通过 &a href=&///?target=http%3A//deep-freeze-node/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&deep-freeze-node&i class=&icon-external&&&/i&&/a& 来反复验证。(在修改之前冻结,并在结束后验证结果。)&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span class=&k&&return&/span& &span class=&p&&{&/span&
&span class=&p&&...&/span&&span class=&nx&&state&/span&&span class=&p&&,&/span&
&span class=&nx&&foo&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&nx&&arr1&/span&&span class=&p&&.&/span&&span class=&nx&&concat&/span&&span class=&p&&(&/span&&span class=&nx&&arr2&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&br&&p&相信我,这是最平淡无奇的例子了。更简单也更自然的方式就是使用 &a href=&///?target=http%3A//immutable.js/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Immutable.js&i class=&icon-external&&&/i&&/a&。&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&import { fromJS } from 'immutable'
const state = fromJS({ bar: 'biz' })
const newState = foo.set('bar', 'baz')
&/code&&/pre&&/div&&br&&p&Immutable.js 非常之快,背后理念也异常漂亮。哪怕你并不想使用它,我也推荐阅读这个由 &a href=&///?target=https%3A///leeb& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Lee Byron&i class=&icon-external&&&/i&&/a& 所制作的视频 &a href=&///?target=https%3A///watch%3Fv%3DI7IdS-PbEgI& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Immutable Data and React&i class=&icon-external&&&/i&&/a&。视频对于 Immutable.js 的工作原理有着非常深刻的讲解。&/p&&br&&b&观察式与响应式方案&/b&&br&&br&&p&如果你不喜欢 Flux/Redux 或者只是想要更加 reactive,不要失望!这儿有很多其他数据处理的解决方案。这就有一个相关库的简要列表供你参考:&/p&&ul&&li&&a href=&///?target=http%3A//cycle.js/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&cycle.js&i class=&icon-external&&&/i&&/a&&em&(“A functional and reactive &/em&&i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&em& framework for cleaner code”)&/em&&/li&&li&&a href=&/question//answer/GitHub%20-%20fdecampredon/rx-flux:%20The%20Flux%20architecture%20with%20RxJS& class=&internal&&rx-flux&/a&&em&(“The Flux architecture with RxJS”)&/em&&/li&&li&&a href=&/question//answer/GitHub%20-%20acdlite/redux-rx:%20RxJS%20utilities%20for%20Redux.& class=&internal&&redux-rx&/a&&em&(“RxJS utilities for Redux.”)&/em&&/li&&li&&a href=&///?target=http%3A//why%2520mobservable/%3F& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&mobservable&i class=&icon-external&&&/i&&/a&&em&(“Observable data. Reactive functions. Simple code.”)&/em&&/li&&/ul&&b&&br&&br&路由 &/b&&br&&p&几乎所有的客户端应用都或多或少需要使用路由。如果你在浏览器中使用 React.js,你就会在挑选库的时候碰到这个分歧点。我们的选择是出自优秀的 &a href=&///?target=http%3A//xn--rackt%github-s2a/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&rackt&i class=&icon-external&&&/i&&/a& 社区的 &a href=&/question//answer/GitHub%20-%20reactjs/react-router:%20A%20complete%20routing%20solution%20for%20React.js& class=&internal&&react-router&/a&。Racket 给 React.js 的拥簇者带来了很多高质量资源。&/p&&br&&p&你可以查看他们的&a href=&///?target=http%3A//react-router/docs%2520at%2520master%%25B7%2520reactjs/react-router%%25B7%2520GitHub& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&文档&i class=&icon-external&&&/i&&/a&以便于集成 react-router,但是更重要的是:如果你使用 Flux/Redux,我们建议你将路由状态和你的 store 或全局状态&strong&保持同步&/strong&。&/p&&br&&p&同步的路由状态可以帮助你对 Flux/Redux 的 Actions 所提供的路由行为有所控制,并且能够在组件中读取路由状态和参数。&/p&&br&&p&Redux 用户可以通过 &a href=&/question//answer/GitHub%20-%20reactjs/react-router-redux:%20Ruthlessly%20simple%20bindings%20to%20keep%20react-router%20and%20redux%20in%20sync& class=&internal&&redux-simple-router&/a& 这个库轻松实现它。&/p&&br&&br&&b&代码分割,惰性加载&/b&&br&&br&&p&只有一小部分 webpack 用户知道应用代码是可以分割的,将 bundler 的输出拆分成多个 &em&&i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/em& 块:&/p&&div class=&highlight&&&pre&&code class=&language-text&&require.ensure([], () =& {
const Profile = require('./Profile.js')
this.setState({
currentComponent: Profile
&/code&&/pre&&/div&&br&&p&这在大型应用中会非常有用,因为在每次部署之后,用户浏览器就&strong&没有必要下载那些很少用到的代码&/strong&,比如 profile 页面。&/p&&br&&p&更多代码块将导致更多 HTTP 请求 —— 但是使用 &a href=&///?target=http%3A//http/2%2520Frequently%2520Asked%2520Questions& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&HTTP/2 multiplexed&i class=&icon-external&&&/i&&/a& 的话就不成问题。结合 &a href=&///?target=http%3A//optimizing%2520caching/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&chunk hashing&i class=&icon-external&&&/i&&/a&,你也可以在代码改变之后优化缓存命中率。(译者注:终端用户访问加速节点时,如果该节点有缓存住了要被访问的数据时就叫做命中,如果没有的话需要回原服务器获取,就是没有命中。)&/p&&br&&p&react-router 的下个版本就将在代码分割这方面提供更多帮助。&/p&&br&&p&想要了解 react-router 的未来走向,可以查看 &a href=&///?target=https%3A///ryanflorence& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Ryan Florence&i class=&icon-external&&&/i&&/a& 所写的这篇博文: &a href=&///?target=https%3A///%40ryanflorence/welcome-to-future-of-web-application-delivery-f%23.vuf3e1nqi& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Welcome to Future of Web Application Delivery&i class=&icon-external&&&/i&&/a&。&/p&&b&&br&&br&组件 &/b&&br&&p&大部分人都对 JSX 存有怨言。首先,你需要知道的是这在 React 中并不是必须的。在最后,JSX 都会通过 Babel 被编译成 &em&&i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/em&。你可以直接编写 &em&&i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/em& 来替代 JSX,但是在处理 HTML 的时候使用 JSX 会感觉更加自然。&/p&&br&&p&特别是对于不懂技术的人来说,他们依然可以理解和修改必要的部分。&/p&&blockquote&&p&JSX 是一种与 XML 类似的 &em&&i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/em& 语法扩展。你可以通过一个简单的 JSX 语法转换器来编译 React。 —— &a href=&///?target=http%3A//jsx%2520in%2520depth/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&JSX in depth&i class=&icon-external&&&/i&&/a&&/p&&/blockquote&&p&如果你想要了解更多关于 JSX 的信息,可以查看 &a href=&///?target=http%3A//jsx%2520looks%2520like%2520an%2520abomination%%25A2%25E2%2582%25AC%25E2%20javascript%2520scene/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&JSX Looks Like An Abomination - But it’s Good for You&i class=&icon-external&&&/i&&/a& 这篇文章。&/p&&br&&br&&b&使用 Class&/b&&br&&br&&p&React 和 ES2015 的 Class 语法搭配完美。&/p&&div class=&highlight&&&pre&&code class=&language-text&&class HelloMessage ponent {
render() {
return &div&Hello {this.props.name}&/div&
&/code&&/pre&&/div&&br&&p&我们喜欢&a href=&/question//answer/Structuring%20React%20Applications:%20Higher-Order%20Components& class=&internal&&高阶组件&/a&更胜于 mixins,所以对于我们来说,保留 createClass 就更像一个语法问题而不是技术问题。我们相信使用 createClass 而不是 ponent 绝对无可厚非,反之亦然。&/p&&br&&br&&b&属性类型&/b&&br&&br&&p&如果你在2016年依然没有检查 properties,那么你应该从现在开始做起,这将为你节省大量时间,相信我。&/p&&div class=&highlight&&&pre&&code class=&language-text&&MyComponent.propTypes = {
isLoading: PropTypes.bool.isRequired,
items: ImmutablePropTypes.listOf(
ImmutablePropTypes.contains({
name: PropTypes.string.isRequired,
).isRequired
&/code&&/pre&&/div&&br&&p&当然,验证 Immutable.js 所编写的 properties 也是可能的,可以使用&a href=&///?target=http%3A//react-immutable-proptypes/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&react-immutable-proptypes&i class=&icon-external&&&/i&&/a&。&/p&&br&&br&&b&高阶组件 &/b&&br&&p&目前来说,&a href=&///?target=http%3A//mixins%2520are%2520dead.%2520long%2520live%2520composition/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&mixins 已死&i class=&icon-external&&&/i&&/a&,而且在 ES6 Class 组件中已经不再被支持,我们应当寻找不同的替代方案。&/p&&br&&p&&strong&那什么是高阶组件呢?&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&PassData({ foo: 'bar' })(MyComponent)
&/code&&/pre&&/div&&br&&p&本质上来说,你可以由原始组件创造一个新的组件并且扩展它的行为。你可以在多种情况下使用它,比如授权:requireAuth({ role: 'admin' })(MyComponent) &em&(检查上层组件中的用户,若是未登录则需要重定向)&/em&,或者是连接你的组件和 Flux/Redux 仓库。&/p&&br&&p&在RisingStack,我们也将数据获取和类似 Controller 的逻辑分割成高阶组件,并保持视图层尽可能简单。&/p&&br&&b&测试&/b&&br&&br&&p&在开发周期中,维持测试的高覆盖率是非常重要的一部分。幸运的是, React.js 社区诞生了很多优秀的库可以帮助我们达到这一点。&/p&&br&&br&&b&组件测试&/b&&br&&br&&p&我们最喜爱的库之一是由 AirBnb 所开发的 &a href=&/question//answer/GitHub%20-%20airbnb/enzyme:%20JavaScript%20Testing%20utilities%20for%20React& class=&internal&&enzyme&/a&,可用于组件测试。非常神奇的是,它的浅渲染特性可以对组件的逻辑及其渲染输出进行测试。尽管它还不能替代你的 selenium 测试,但是将前端测试提升到了一个新的水平。&/p&&div class=&highlight&&&pre&&code class=&language-text&&it('simulates click events', () =& {
const onButtonClick = sinon.spy()
const wrapper = shallow(
&Foo onButtonClick={onButtonClick} /&
wrapper.find('button').simulate('click')
expect(onButtonClick.calledOnce).to.be.true
&/code&&/pre&&/div&&br&&p&看起来就非常简洁,不是么?你在使用 chai 作为测试断言库嘛?相信你会喜欢 &a href=&/question//answer/GitHub%20-%20producthunt/chai-enzyme:%20Chai.js%20assertions%20and%20convenience%20functions%20for%20testing%20React%20Components%20with%20enzyme& class=&internal&&chai-enyzime&/a& 的!&/p&&br&&br&&b&Redux 测试&/b&&br&&br&&p&&strong&测试一个 reducer&/strong& 非常简单,它响应新到来的 actions,并且将原来的状态进行更新:&/p&&div class=&highlight&&&pre&&code class=&language-text&&it('should set token', () =& {
const nextState = reducer(undefined, {
type: USER_SET_TOKEN,
token: 'my-token'
// immutable.js state output
expect(nextState.toJS()).to.be.eql({
token: 'my-token'
&/code&&/pre&&/div&&br&&p&&strong&测试 actions&/strong& 也很简单,但是异步 actions 就不太一样了。对于测试异步的 Redux actions 来说,我们推荐使用 &a href=&///?target=http%3A//redux-mock-store/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&redux-mock-store&i class=&icon-external&&&/i&&/a&,非常有帮助。&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&it('should dispatch action', (done) =& {
const getState = {}
const action = { type: 'ADD_TODO' }
const expectedActions = [action]
const store = mockStore(getState, expectedActions, done)
store.dispatch(action)
&/code&&/pre&&/div&&br&&p&更深度地了解 &a href=&///?target=http%3A//rackt.org/redux/docs/recipes/WritingTests.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&redux 测试&i class=&icon-external&&&/i&&/a&,可以查看官方文档。&/p&&br&&b&使用 npm&/b&&br&&br&&p&虽然 React.js 并不依赖代码打包工具就可以很好地工作,但我们还是推荐使用 &a href=&///?target=http%3A//webpack%2520module%2520bundler/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Webpack&i class=&icon-external&&&/i&&/a& 或者 &a href=&///?target=http%3A//browserify/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Browserify&i class=&icon-external&&&/i&&/a& 来发挥 &a href=&///?target=http%3A//npm/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&npm&i class=&icon-external&&&/i&&/a& 的能力。Npm 上满是高质量的 React.js 包,还可以帮你非常优雅地管理依赖。&/p&&br&&p&&em&(请不要忘记复用你自己的组件,这是一种绝佳的代码优化方式。)&/em&&/p&&br&&br&&b&Bundle 大小&/b&&br&&br&&p&这本身不是一个 React 相关的问题,但是大多数人都在打包他们的 React 应用,所以我认为提到这点很重要。当你打包源代码的时候,时刻警惕打包后的文件大小。为了&strong&保持体积最小化&/strong&,你应该考虑如何 require/import 依赖。&/p&&br&&p&对比以下代码片段,这两种不同的方式对输出的影响区别巨大:&/p&&div class=&highlight&&&pre&&code class=&language-text&&import { concat, sortBy, map, sample } from 'lodash'
import concat from 'lodash/concat';
import sortBy from 'lodash/sortBy';
import map from 'lodash/map';
import sample from 'lodash/sample';
&/code&&/pre&&/div&&br&&p&可以查看这篇文章 &a href=&///?target=http%3A//reduce%2520your%2520bundle.js%2520file%2520size%2520by%2520doing%2520this%2520one%2520thing/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Reduce Your bundle.js File Size By Doing This One Thing&i class=&icon-external&&&/i&&/a& 获取更多详情。&/p&&p&我们也喜欢将代码分离出至少 vendors.js 和 app.js 两个文件,因为 vendors 相对于我们的代码库来说更新不是那么频繁。&/p&&br&&p&将输出文件名称进行哈希化处理 &em&(Webpack 中的 chunk hash)&/em&,并使用长缓存,我们可以大大减少用户需要下载的代码大小。结合惰性加载,优化效果可想而知。&/p&&br&&p&如果你还不太熟悉 Webpack,可以查看这本优秀的 &a href=&///?target=http%3A//introduction/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&React webpack 手册&i class=&icon-external&&&/i&&/a&。&/p&&br&&br&&b&组件级别热重载&/b&&br&&br&&p&如果你曾经使用过热加载来编写单页面应用,当你在处理某些与状态相关的事情时,可能你就会明白当你在编辑器中点击保存,整个页面就重新加载了是多么令人讨厌。这样子就不得不重新点击一遍应用,重复如此会令人抓狂的。&/p&&br&&p&通过 React,在重载组件的同时&strong&保持组件状态&/strong&已经成为可能 —— 耶,从此不再痛苦!(没有蛀牙!)&/p&&br&&p&关于如何搭建热重载,可以参考 &a href=&/question//answer/GitHub%20-%20gaearon/react-transform-boilerplate:%20A%20new%20Webpack%20boilerplate%20with%20hot%20reloading%20React%20components,%20and%20error%20handling%20on%20module%20and%20component%20level.& class=&internal&&react-transform-boilerplate&/a&。&/p&&b&&br&&br&使用ES2015&/b&&br&&br&&p&前面有提到过,我们可以在 React.js 组件中使用 JSX,然后使用&a href=&///?target=http%3A//babel%%%25B7%2520the%2520compiler%2520for%2520writing%2520next%2520generation%2520javascript/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Babel.js&i class=&icon-external&&&/i&&/a&进行编译。&/p&&p&其实 Babel 的能力远不止如此,它也可以让我们现在就可以给浏览器编写 ES6/ES2015 代码。在 RisingStack,我们在服务器端和客户端都使用了 ES2015 特性,这都已经在最新的 LTS Node.js 版本中被实现了。&/p&&br&&img src=&/b7a6ddeafc51_b.png& data-rawwidth=&400& data-rawheight=&277& class=&content_image& width=&400&&&br&&b&Linters&/b&&br&&br&&p&或许你已经给你的 &em&&i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/em& 代码制定了代码规范,但是你知道也有用于 React 的代码规范了吗?我们强烈推荐挑选一个并开始遵循它。&/p&&br&&p&在 RisingStack,我们也将 linters 强制运行在 CI 系统上,git push 亦然。可以试试 &a href=&///?target=http%3A//pre-push/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&pre-push&i class=&icon-external&&&/i&&/a& 或者 &a href=&///?target=http%3A//pre-commit/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&pre-commit&i class=&icon-external&&&/i&&/a&。&/p&&br&&p&我们使用标准的 &em&&i&&i&&i&&i&&i&&i&&i&&i&&i&&i&JavaScript&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/i&&/em& 代码风格,并使用了 &a href=&///?target=http%3A//eslint-plugin-react/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&eslint-plugin-react&i class=&icon-external&&&/i&&/a&对 React.js 代码进行规范 。&/p&&p&&em&(就是,我们不再使用分号。)&/em&&/p&&br&&br&&b&GraphQL 和 Relay&/b&&br&&br&&p&GraphQL 和 Relay 相对而言属于新技术,在 RisingStack,目前我们还没有在产品环境中使用它们,暂时保持关注。&/p&&br&&p&我们曾经写过一个 Relay 的 MongoDB ORM库,叫做 &a href=&/question//answer/GitHub%20-%20RisingStack/graffiti:%20Node.js%20GraphQL%20ORM& class=&internal&&graffiti&/a&,可以使用已有的 mongoose 模型直接创建一个 GraphQL 服务器。&/p&&br&&p&如果你想要学习这些新技术,我们建议你可以找来玩一玩。&/p&&br&&br&&b&尽情享用这些 React.js 最佳实践&/b&&br&&br&&p&有些突出的技术和库其实跟 React.j}

我要回帖

更多关于 英雄联盟退出全屏 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信