微信群聊天记录-03-28

#1

手动转发, 消息顺序乱了, 图片丢失了… 弱备份…


学了一天callbag,写了一个redux-callbag,个人感觉比redux-saga/redux-observable要好用多了,30行代码而已,大家可以玩玩试试 https://github.com/janryWang/redux-callbag

玩一玩挺好的,生产环境目前建议慎用,callbag 需要经过更多试炼,找到一个好的,融入当前流行技术栈的方式~

看到每天都有这个 今天来试一下

吹一波 callbag

知乎 | callbag 和 rxjs 有什么区别?

工业聚 的回答,已获得了 0 个赞同

@工业聚 为什么我看不到你的回答……

知乎自己的问题大概

callbag 有希望成为下一个 jquery/lodash 性质的东西,配合 pipeline operator,改变 js 里的编程风格

React 又添加一个新钩子 getSnapshotBeforeUpdat

谁给取的

异步模式那个名字简直了

后面要找时间,投入 vue 的怀抱。我的同事们都很喜欢 vue 的设计

react 越发复杂,快要失去当初让人喜欢的简单直接

之前 react 的优势是,可以用 js 的能力,比 template 表达能力更强

但 render props,portal, call-return, suspend 等等,不断地损害上述目标

jsx 本来是为了降低开发者的认知成本,让他们可以用熟悉的 html/xml-style 写 UI 组件

那么,换语言(reasonml,wasm,elm),或者换模式(template),可能是更好的选择

jsx 比 template 本就牺牲了跟 html 的相似程度和简洁美观,想要换来更强大的表达能力,如果这个能力不够强大,或者在 JS 里用起来不够好

需要增加 N 个事物

但发展到现在,仿佛在告诉我们:其实给你 js 的全部能力,也无法表达你想要的效果

而且不需要记住很多 directive 写法

dan 是写了,我也让同事看了,他今天才跟我说终于知道了,是他一直误解了(可他已经写了快两年多的 React 了)

这种可读性很高雅

还好可以经过一层封装和约束,把那些复杂的东西消除或者隐匿,不然真的没法让普通开发者使用

Dan 不是写了篇文章专门讲这三者的关系吗

react 变成了庞然而怪异的东西
再配合 redux 里对 immutable-data 的要求,shouldComponentUpdate 里浅对比的要求,action-creator, contants, reducer 以及 react-router 里的杂事儿

一个function 一个return value

ReactComponent 跟 ReactComponent Instance 哈哈哈哈

现在像是 为了达到效果 而去增加特性

昨天我同事还陷入 ReactComponent, ReactElement, ReactComponent isntance 等的关系中,无法自拔~

现在的 react jsx 组件写法,不仅没有降低认知成本,反而增加了很多心智负担,开发者必须深谙 react 之道,并且屏蔽 html 里的部分知识,才能正确理解

react 的 immutable 和 virtual dom 实际上是性能优化引擎方面需要的东西,

Programming 和 Configuration

而 react 里 30 分的开发者,写 40 分的应用。要 60 分的开发者才能写 70+ 分的应用

vue 可以让 30 分的开发者写 70 分的应用

一个 react swiper 组件,用 hoc 来添加不同的特性,如 autoRun 。都能把他们难倒

+1 然而我还是觉得 React 是更正确的路

而使用 vue 去做,他们要做的更少,反而成功率大

经过这两年的尝试,我是看出来了,让普通开发者写 react 和使用 react 生态去增加抽象层,解决有难度的问题,概率很小

总是要增加很多抽象层的

是啊,最后是 mobx+proxy

复杂了以后 react 和 vue 都殊途同归吧

我让他们自己去看 vue 去了

然而 mvvm 讲着讲着变成 flux 了

pure component 和 state 内部管理还是很清晰,加了各种数据流模型就感觉不可控了

上周的前端沙龙,一位讲师将 MVVM 数据流,双向绑定,他们听了两眼方光,很渴望双向绑定的样子

如果不够高,用 vue 更佳。让开发者做更少事情(反正他们自己做的事情,大多不太好)

如果团队里的平均水平高,可以用 react。让开发者做更多事情。

这些写 React 的同事们,私下还是在尝试 vue,而不是深挖 React

然后隔壁 BU 里用 vue 做出来的东西,效果也很好,写法更简单,学习成本更低

花了很多时间培养、训练和教育,他们可以正常写 React 应用了。但对 React 的背后机制,还是很茫然。

大厂毕竟是大厂,hold 得住各种需求很重要,不能像是社区那样为了设计上的优秀尝试砍掉功能

暴露在应用层,普通开发者写的代码,某些地方用双向绑定的语法维护成本反而更好

可是假设有足够的开发能力,底层完整的不可变数据,上层模拟一些双向绑定,也只是语法糖的问题

在 react 里语法需要修改 parser 或者做元编程才能,

是啊

不过react就是下限太低

但也不代表vue上限低

求分享

对 正确的是什么

shouldComponentUpdate 这个正确的理解,求普及下

@工业聚 “对 shouldComponentUpdate 如何提升性能的理解,9.5个是错误的”,业聚兄顺便普及一遍正确及完整的理解吧

React 里需要层层传递 props 的繁琐,更加剧了他们想走捷径的冲动

对比iOS和Android又是一个道理

我就是在react里操作dom,写canvas动画

10个 react 开发者,对 shouldComponentUpdate 如何提升性能的理解,9.5个是错误的

react 也不算厚,使用起来也可以很简单。关键就是它支持 js 里的各种能力,而水平不高的开发者又容易自作聪明,写出更差的代码

各有好处,但不代表这样react就一定比vue更深入

React是开箱是本厚厚的说明书,就和d3一样

Vue 开箱即用可深入,echarts一个道理

OK,来说一下 react 里的几个问题

第一种写法是常见的模式,把 data 拍平传递给 props,符合 html 里的习惯

为什么我认为 jsx 不是未来,只是过渡方案,可以看一个简单的例子

如果改动了,当然就穿透了 shallowCompare,除非手动写 compare(props.data)

在 shouldComponentUpdate 里进行 shallowCompare 时,如果 data 没有改动,第二种写法只有一个 key

$.ajax({ data: data })

第二种写法,只传递了一个 data 属性,没有浅拷贝。符合 js 里的风格

但是这种写法,浅拷贝了一次 data 给 props,从编译后的 js 来看,是多余的

react 实践里默认推荐展开传递,这样好加 PureComponent,不然就得手动写 shouldComponentUpdate

应该说,props是否应该展开传递的判断标准是,props是否经常变换

如果渲染时,props/state 每次都变化了,那么套上 PureComponent 会导致每次 render 时都要 compare 一下,并且 compare 时必然返回「需要更新」,这就导致徒增了冗余比较

只有满足多个条件,才能用 PureComponent 提升性能:1)子树很大,compare props/state 的损耗很小;2)props/state 在多次 re-render 中,有相当比例的情况是没有变化的

本来 input 只有 type, value 等少数字段,也没有子元素,diff/patch, render 的损耗极小,套上 PureComponent 后,反而要 compare 1W 个 key

如果你的组件只是一个 input,而你的 props/state,通过 {…data} 全量传递,有 1万个 key,那么加上 PureComponent 后,性能更差

PureComponent 的性能提升的来源是:shallowCompare(props, nextProps) && shallowCompare(state, nextState) 的损耗,小于 component.render 及其 diff/patch 的损耗

那么,给所有 {…data} 都套上 PureComponent 就能提升性能了吗?也未必

第二个矛盾时, {…data} 的写法是要配合 shouldComponentUpdate 才有效果,stateless component 和没有 shouldComponentUpdate 的组件里,不过是冗余浅拷贝而已

前面揭示的第一个矛盾是,jsx 里越像 html 的写法,编译后从 Js 本身的角度看,未必合理

所以 react 里普遍采用第一种做法,这样可以简单地通过 PureComponent 做优化;但是,这会进入第二个矛盾

如果可以把 shouldComponentUpdate 的 compare 损耗降到极低,比如用 === 来直接判断

厉害了

immutable-data 如何提升 react 的性能?背后就是因为上述原因

更精准有效的比较,是手动指定要比较的 key 和返回 true|false 的判断

第二种是,缓存 render 结果,让下一次 diff tree 时,直接相等

第一种是,shouldComponentUpdate 永远 return false,这样只在首次渲染时,render 函数执行一次,往后都不执行,达到静态化的效果

有两种方式可以创建一个静态组件

PureComponent 不等于 shouldComponentUpdate,前者只是默认了一个浅比较,后者是可以更精确地手动优化比较方式

pureComponent对于顶层业务组件借助immer维护状态的还是可以的

template 虽然表达能力弱,但是腾出了更多的 compiler 优化空间

但它没有,而且它可以写各种 js 表达式,导致 compiler 的优化成本极高,效果极不稳定

比如

编译成 xxx &&
的短路表达式形式

jsx 里的另一个巨大问题时,它本来可以听过 compiler 做很多优化

没人想手写 shouldComponentUpdate

无脑 PureComponent,常常带来反效果。但除此之外,也没有太多更友好的做法

总而言之,shouldComponentUpdate 是 react 里的逃生出口,跟 react 内部机制有紧密的关联,但是要通过它获得性能优化,太麻烦了
通过 shouldComponentUpdate 的第三个参数,可以防止 context 穿透更新或者解决 context 变化了子树却没更新

即便 vdom === oldVdom,如果 context 变化了,也需要去 re-render

shouldComponentUpdate 其实有三个参数 (nextProps, nextState, nextContext),react context 是可以穿透 diff 的

如果不需要更新,就说不需要更新;如果实在要更新,可以延后到下一帧去更新

shouldComponentUpdate 还可以做一个异步更新的判断

那么不管子树是多小,它都可以带来收益

即便用了 immer,保持了 immutable-data,在 js 这种灵活性很强的语言面前,没人对自己的 react vdom tree 是否真的避免了无效更新,有充分的信心

比如 vue 之前做的跳过 vdom 缓解,在 SSR 阶段直接拼字符串的模式

而且,阻止更新是一个统计学问题,有时要更新,有时要避免冗余更新

我之前曾说,virtuale-dom 是用计算资源的浪费,来换取开发者的注意力资源,可以关心更有意义的事情

一个在生产环境被证明是优化的方案,随着时间推移,用户使用习惯的变化,它可能不是优化了。但开发者谁知道这个情况,谁敢改之前被认为是优化的代码?

在 B 用户里,却可能反过来

计算收益也是动态的,在 A 用户的数据场景里,PureComponent 是正向收益的,因为 A 用户的操作频次较低,数据变更少

它不是明确的,导致更难通过简单试验和工具的高亮,来评估在生产环境里的优化表现

从这个角度看,vue 将来的优化空间更大

render props + context 这个具有穿透特性的东西,大范围使用,几乎等同于放弃优化

而 render props 这个模式,导致优化更难实施。你的 children 是一个函数,即便是同一个函数,它的闭包里的父组件的 props/state 也可能变化了,作为组件,你无法判断是否应该更新

太麻烦了,对开发者的要求也太高。即便是 react 熟手,也可能为了方便,或者实现上的需要,写出难以简单优化的组件

除非每一层手写 shouldComponentUpdate,把 props.state.xxx 里的必要数据抽出来对比

这导致,所有层级里的 props 里都有跟它渲染无关的数据,套 PureComponent 不可能阻止更新

很多人喜欢直接把整个 state 往下透传

把冗余传递的状态,消除掉

大部分 react 开发者,写出来的稍稍复杂一些的组件,要做优化,需要改写很多地方

精通 react,才能准确优化 react app 的性能,才能写出可以简单地通过在关键组件里套 PureComponent 和添加手动 shouldComponentUpdate 的判断,就能提升性能

所以有 shouldComponent, async-render,you may not need virtuale-dom 等多种考量,提升渲染性能,改变渲染模式,以便给用户带来更顺畅的交互体验

我们没有奢侈到可以让 virtual-dom 随意 re-render 的地步

我现在还是这个看法,不过之前是对当下的设备性能高估了,并且低估 web app 的复杂性

pipeline的babel插件貌似没有一个是好使的

看到一个 twitter 说,他们公司从 React V15 升级到了 React V16,废了一番功夫,没有看到什么提升。但起码,为下次升级减小了痛苦。

而 react 里的升级,不是这样的。很多时候,是要手动去做的,是需要破坏性的重构的

当 vue 里提升了 compiler 层面的性能后,有望静默地全局更新,只需要升级版本

每当出现一个新的 compiler 层面的优化技巧,都有机会应用于 compile template