{"action":"opened","issue":{"url":"https://api.github.com/repos/yyx990803/tucao/issues/1","labels_url":"https://api.github.com/repos/yyx990803/tucao/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/yyx990803/tucao/issues/1/comments","events_url":"https://api.github.com/repos/yyx990803/tucao/issues/1/events","html_url":"https://github.com/yyx990803/tucao/issues/1","id":85647384,"number":1,"title":"Nuclear 技术分析","user":{"login":"yyx990803","id":499550,"avatar_url":"https://avatars.githubusercontent.com/u/499550?v=3","gravatar_id":"","url":"https://api.github.com/users/yyx990803","html_url":"https://github.com/yyx990803","followers_url":"https://api.github.com/users/yyx990803/followers","following_url":"https://api.github.com/users/yyx990803/following{/other_user}","gists_url":"https://api.github.com/users/yyx990803/gists{/gist_id}","starred_url":"https://api.github.com/users/yyx990803/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yyx990803/subscriptions","organizations_url":"https://api.github.com/users/yyx990803/orgs","repos_url":"https://api.github.com/users/yyx990803/repos","events_url":"https://api.github.com/users/yyx990803/events{/privacy}","received_events_url":"https://api.github.com/users/yyx990803/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-06-05T22:28:31Z","updated_at":"2015-06-05T22:28:31Z","closed_at":null,"body":"起因是有位同学在微博上发了个框架，叫 [Nuclear](http://www.weibo.com/1759063797/Cl7TPdV1c)，并且 at 了一大堆人求扩散。我也被 at 了，所以就看了两眼。网站的样式做得和 React 一样，API 长得也很像，宣传上也说是 “类似 React”，并且 “废除了 JSX, Virtual DOM 和 rAF”。虽然我不确定作者到底是不是这意思，总之给人的感觉就是 “我造了个和 React 很像但是比 React 更好的轮子”。看了源码之后觉得这个实现并不怎么样，所以就忍不住吐槽了两句，没想到作者还不开心了。微博上看热闹的多，加上我一直觉得很多人并不理解 React，所以特意这里写篇文章分析一下我为啥要吐槽这个 Nuclear。\r\n\r\n了解 React 的人都知道，React 的精髓有两块：\r\n\r\n1. 函数式的视图渲染思维，`UI = f(state)`。但是由于 DOM 的慢，需要用 Virtual DOM 来解决性能问题，用 JSX 来解决 Virtual DOM 的书写语法问题。\r\n2. 组件能够声明式地进行嵌套组构，像搭积木一样搭出整个应用。\r\n\r\n## 函数式渲染\r\n\r\nNuclear 的示例是这样的：\r\n\r\n``` html\r\nvar HelloMessage = Nuclear.create({\r\n  render: function () {\r\n    return '<div>Hello , {{name}} !</div>';\r\n  }\r\n});\r\n```\r\n\r\n乍看之下和 React 很像，但这里的 `render` 函数返回的是一个字符串模板。内部实现直接用了 Mustache.js 来编译模板。这个实现比起 React 有很多问题：\r\n\r\n1. 语法上完全受制于字符串模板语言的限制。JSX 优于传统模板的一个地方，就在于它其实具有完整的 JavaScript 语言的逻辑表达能力。举个例子，比如你要在一个循环的模板里输出当前的 index，Mustache.js 的语法里是根本没有这个功能的。你只能在数据源里面手动加上 index。但是在 JSX 里面，你可以直接用 `Array.map((item, i) => i)`。用 JSX 的时候，你并不需要考虑 “这样的逻辑在这个模板语言里怎么写”，因为只要你能用 JavaScript 表达它就可以了。虽然 JSX vs. 模板有很大的偏好问题（我自己也更喜欢模板），但我看到太多人根本不理解 JSX 的好处在哪里。\r\n\r\n2. 性能上，Nuclear 采用的是这样的方案：通过 `observe-js` 观察组件的数据对象，有任何变动发生就重新渲染。这里作者做了几个性能方面的考量：\r\n\r\n  1. 重绘有一个 50ms 的 debounce。这里其实应该用 throttle 而不是 debounce。debounce 有一个严重的问题：如果我每隔小于 50ms 进行一次数据变动，是永远不会有重绘发生的。比如这个 [Timer 的例子](https://github.com/AlloyTeam/Nuclear/blob/master/timer.html)，如果把 timeout 改成 30ms，DOM 永远不会更新。\r\n\r\n  2. 每次重绘的时候：\r\n\r\n    1. 首先由 Mustache.js 重新渲染整个字符串模板，得到新的 HTML\r\n    2. 把新的 HTML 字符串转化为 DOM tree。这里并没有把新的 DOM tree 插入 document，但是代价其实一点也不低。\r\n    3. 用户需要**手动**在模板里添加 `nc-refresh` 属性来提示哪一块需要局部更新。Nuclear 从新的 DOM tree 里面用 `querySelectorAll` 把它们挑出来，然后替换进旧的 DOM 里面。\r\n    4. 如果用户没有添加 `nc-refresh` 属性，则默认是整个替换...\r\n\r\n  虽然想想都知道这性能好不到哪里去，但我还是负责任地做了个 [dbmonster 渲染测试](http://vuejs.github.io/js-repaint-perfs/nuclear/)。有兴趣的可以看看[其他框架的表现](http://vuejs.github.io/js-repaint-perfs)，尤其是 React。\r\n\r\n## 组件\r\n\r\n很让我惊讶的是，Nuclear 宣传自己类似 React，却不支持组件的声明式嵌套，只支持 “命令式嵌套”，也就是说模板里不能调用其他组件，只能手动 `new` 了以后像 DOM 一样去操作...\r\n\r\n其实组件之间如何组合，这里面的问题非常多，比如嵌套组件的生命周期如何管理，数据如何在组件之间传递，如何根据数据状态渲染不同的子组件... 等等。命令式地去管理这些东西和手动操作 DOM 其实没什么区别，后期根本无法维护。连这样核心的功能都没有就急着上微博圈人求扩散，是不是有点浮躁？\r\n\r\n## 题外话\r\n\r\n这篇文章并不是想针对谁，而是因为\r\n\r\n1. 看到很多人不喜欢 React，却其实并不理解 React，也就是黑不到点子上。Nuclear 这个框架在我看来，恰恰是把 React 最精髓的两个东西丢掉了。\r\n\r\n2. 我在微博上的原话：\r\n\r\n> 这里的问题是：要造轮子，而且是参照着别人的东西试图造一个更好的轮子，起码得对别人的东西做深入的研究，理解别人的东西优点是什么。做不到这点的话，我看到的更多是自大和浮躁。说得可能不够客气，但是我觉得前端真的不需要更多半吊子的轮子了。"}}