Facebook React 和 Web Components(Polymer)对照上风和劣势

译者媒介

这是一篇来自 StackOverflow 的问答,发问的人以为 React 比拟 WebComponents
有一些“先天不足”的处所,列举以下:

  • 原生浏览器支撑
  • 原生语法支撑(意即不把款式和构造殽杂在 JS 中)
  • 运用 Shadow DOM 封装款式
  • 数据的双向绑定

这些都是确然的。不过他照样愿望听听人人的意见,因而就有了这篇精彩的回复。

须要申明的是,这篇回复并没有议论太多的技术细节,但却普遍周全的谈及了许多
看法性的东西,而且补充了许多进阶的浏览材料。能够说“含金量”平常然则“信
息量”很大,迥殊能够协助许多进阶者开辟视野,增进学问,转换看法。

别的,答案里所援用的几个演讲视频都非常精彩!遗憾地是接见受限——人人懂的。
但是我一向以为这年头不会“科学上网”的话就不要搞开发了,所以在此照样尽力
引荐你好悦目一看。

我以为会对一些人有所助益的,迥殊是发题目老是提不到点子上的朋侪(笑),特
此翻译并纪录于下:

原题:Pros and Cons of Facebook’s React vs. Web Components
(Polymer)

Update: this answer seems to be pretty popular so I took some time to
clean it up a little bit, add some new info and clarify some things that
I thought was not clear enough.

更新:看来我的答案蛮受喜爱的,因而我花了点时刻略做整顿,添加了新的内
容并把之前没有讲清楚的处所也做了进一步的诠释。

Most of your concerns are really a matter of opinion and personal
preference but I’ll try to answer as objectively as I can:

你所说起的大部份现实上都属于个人偏好,不过我照样尽我所能客观的回复以下:

Native vs. Compiled

Write JavaScript in vanilla JavaScript, write CSS in CSS, write HTML
in HTML.

原生言语对决预编译言语

用纯 JavaScript 来写 JavaScript,用 CSS 来写 CSS ,用 HTML 来写 HTML。

Back in the day there were hot debates whether one should write native
Assembly by hand or use a higher level language like C to make the
compiler generate Assembly code for you. Even before that people refused
to trust assemblers and preferred to write native machine code by hand
(and I’m not joking).

回忆往昔,人们也曾争辩究竟是直接手写汇编照样用像 C 如许的高阶言语运用编译
器来天生汇编代码。以至在更早之前人们谢绝信托汇编程序而情愿手工编写原生气希望
器代码(我没开打趣)。

Meanwhile, today there are a lot of people who write HTML in Haml or
Jade, CSS in Sass or Less and JavaScript in CoffeeScript or TypeScript.
It’s there. It works. Some people prefer it, some don’t.

时至今日,许多人都运用 Haml 或 Jade 编写 HTML,用 Sass 或 Less 编写 CSS
,用 CoffeeScript 或 TypeScript 编写 JavaScript。存期近真谛,能抓老鼠的
就是好猫。有人爱,固然也会有人恨。

The point is that there is nothing fundamentally wrong in not writing
JavaScript in vanilla JavaScript, CSS in CSS and HTML in HTML. It’s
really a matter of preference.

重点是在本质上运用预编译言语没有什么毛病。这纯粹是喜好的题目。

Internal vs. External DSLs

Style encapsulation using Shadow DOM React instead has this, which
requires writing CSS in JavaScript. Not pretty.

内部与外部 DSLs 的对决

运用 Shadow DOM 封装款式,而 React 则运用这个解决方案
,须要把 CSS 写进 JavaScript 里。不文雅。

Pretty or not, it is certainly expressive. JavaScript is a very powerful
language, much more powerful than CSS (even including any of CSS
preprocessors). It kind of depends on whether you prefer internal or
external DSLs for those sorts of things. Again, a matter of preference.

文雅与否,确有其意义。JavaScript 是一门非常壮大的言语,远甚于 CSS(算上
任何一种 CSS 预处理言语也是云云)。这个题目视乎你喜好内部照样外部 DSLs
。照样的,偏好题目。

(Note: I was talking about the inline styles in React that was
referenced in the original question.)

(注重:我指的是原题中援用的在 React 中内联款式的写法。)

Types of DSLs – explanation

Update: Reading my answer some time after writing it I think that I need
to explain what I mean here. DSL is a domain-specific language and it
can be either internal (using syntax of the host language like
JavaScript – like for example React without JSX, or like the inline
styles in React mentioned above) or it can be external (using
a different syntax than the host language
– like in this example would be inlining CSS (an external DLS) inside
JavaScript).

DSLs 的品种 – 诠释

更新:回复完以后又重读一遍我的答案,我以为有必要进一步诠释一下。DSL
指的是范畴特定言语,它可所以内部的(运用宿主言语的语法,比方
JavaScript – 之于不运用 JSX 的 React,或许之前提到的在 React 中内联款式
的写法),也可所以外部的(运用和宿主言语差别的语法 – 比方本例中在
JavaScript 内部编写的内联 CSS (属于外部 DSLs))。

译注:此处作者的回复好像有些自相矛盾,由于在 React 中写内联 CSS 和在
JavaScript 中写内联 CSS 应该是一回事(都属于运用外部 DSLs),毕竟
React 自身就是运用宿主言语(也就是 JavaScript – 这里属于内部 DSLs)来
编写的呀。

It can be confusing because some literature uses different terms than
“internal” and “external” to describe those kinds of DLSs. Sometimes
“embedded” is used instead of “internal” but the word “embedded” can
mean different things – for example Lua is described as “Lua: an
extensible embedded language” where embedded has nothing to do with
embedded (internal) DSL (in which sense it is quite the opposite – an
external DSL) but it means that it is embedded in the same sense
that, say, SQLite is an embedded database. There is even eLua where “e”
stands for “embedded” in a third sense – that it is meant for embedded
systems! That’s why I don’t like using the term “embedded DSL” because
things like eLua can be “DSLs” that are “embedded” in two different
senses while not being an “embedded DSL” at all!

某些材料里用差别的术语来形貌上述的 DSLs 品种,这常常会使人殽杂。有时刻
“嵌入式”会用来指代“内部的”然则“嵌入式”也可所以别的意义——比方说 Lua 可
被形貌为“Lua:一种可扩大的嵌入式言语”,在这里“嵌入式”和“内部 DSLs” 一
毛钱关联都没有(更甚者完整相反,嵌入式是一种外部 DSL),它说的是和
“SQLite 是一种嵌入式数据库”一个意义。以至另有一种 eLua,它的 “e” 代
表别的一种“嵌入式”——嵌入式体系!这就是为何我不喜好运用术语“嵌入式 DSL”
的缘由,像 eLua 可所以具有两种“嵌入式”寄义的 DSLs,但却和“嵌入式 DSLs”
没有任何关联。

To make things worse some projects introduce even more confusion to the
mix. Eg. Flatiron templates are describes as “DSL-free” while in fact it
is just a perfect example of an internal DSL with syntax like:
map.where(‘href’).is(‘/’).insert(‘newurl’);

更糟的是一些项目引入的看法让这潭浊水变得更混了。比方:Flatiron 模板自称
“无 DSL”而现实上倒是一个圆满的内部 DSL 的例子,其语法以下:

map.where('href').is('/').insert('newurl');

That having been said, when I wrote “JavaScript is a very powerful
language, much more powerful than CSS (even including any of CSS
preprocessors). It kind of depends on whether you prefer internal or
external DSLs for those sorts of things. Again, a matter of preference.”
I was talking about those two scenarios:

如前所述,当我写道“JavaScript 是一门非常壮大的言语,远甚于 CSS(算上
任何一种 CSS 预处理言语也是云云)。这个题目视乎你喜好内部照样外部 DSLs
。照样的,偏好题目。”我所指的是以下两个场景:

一:

/** @jsx React.DOM */
var colored = { color: myColor };
React.renderComponent(<div style={colored}>Hello World!</div>, mountNode);

二:

// SASS:
.colored {
  color: $my-color;
}
// HTML:
<div class="colored">Hello World!</div>

The first example uses what was
described in the question as: “writing CSS in JavaScript. Not pretty.”
The second example uses Sass. While I agree that using JavaScript to
write CSS may not be pretty (for some definitions of “pretty”) but there
is one advantage of doing it.

第一个例子犹如原题所述:“在 JavaScript 里写 CSS。不文雅。”第二个例子则
运用 Sass。只管我也赞同运用 JavaScript 写 CSS 能够不太文雅(某种意义上的
“文雅”)但是这么做照样有一个长处的。

I can have variables and functions in Sass but are they lexically scoped
or dynamically scoped? Are they statically or dynamically typed?
Strongly or weakly? What about the numeric types? Type coersion? Which
values are truthy and which are falsy? Can I have higher-order
functions? Recursion? Tail calls? Lexical closures? Are they evaluated
in normal order or applicative order? Is there lazy or eager exaluation?
Are arguments to functions passed by value or by reference? Are they
mutable? Immutable? Persistent? What about objects? Classes? Prototypes?
Inheritance?

我能够在 Sass 里运用变量和函数,可它们是词法作用域照样动态作用域的存在呢
?它们是静态范例照样动态范例?数字范例如何?范例强迫转换又如何?哪些是直
真哪些又是假值?我能用高阶函数吗?递归呢?尾挪用?词法闭包?求值是递次还
是按运用序?是不是能够运用惰性求值或主动求值?函数是按值传参照样按援用传参
?它们是可变的?不可变的?耐久化的?另有对象呢?类呢?原型呢?继续呢?

Those are not trivial questions and yet I have to know answers to them
if I want to understand Sass or Less code. I already know those
answers for JavaScript so it means that I already understand every
internal DSL (like the inline styles in React) on those very levels so
if I use React then I have to know only one set of answers to those
(and many similar) questions, while when I use for eg. Sass and
Handlebars then I have to know three sets of those answers and
understand their implications.

这些并不是无碍痛痒的题目,假如我想要邃晓 Sass 或 Less 的代码就必需晓得上述
疑问的答案。我已晓得这些题目(以及许多类似题目)在 JavaScript 里的答案
了,也就意味着我已邃晓每一种内部 DSLs 了,但是当我运用比方说 Sass
和 Handlebars 那末我得晓得三套答案(包含 JS)同时还得邃晓它们的完成。

It’s not to say that one way or the other is always better but every
time you introduce another language to the mix then you pay some price
that may not be as obvious at a first glance, and this price is
complexity.

这倒不是说某一种体式格局肯定会更好,然则每一次你引入别的一种言语就不得不花代
价(去进修和邃晓它),这类价值能够在一开始不是那末显著而且会很庞杂。

I hope I clarified what I originally meant a little bit.

愿望我把我的本意诠释的比较清楚了。

Data binding

Two-way binding

数据绑定

双向绑定

This is a really interesting subject and in fact also a matter of
preference. Two-way is not always better than one-way. It’s a question
of how do you want to model mutable state in your application. I always
viewed two-way bindings as an idea somewhat contrary to the principles
of functional programming but functional programming is not the only
paradigm that works, some people prefer this kind of behavior and both
approaches seem to work pretty well in practice. If you’re interested in
the details of the design decisions related to the modeling of the state
in React then watch the talk by Pete Hunt (linked to in the question)
and the talk by Tom Occhino and Jordan Walke who explain it very well
in my opinion.

这是很有意义的话题而且现实上照样偏好题目。双向绑定不老是比单向绑定好。这
取决于你想要如何来模子化运用的可变状况(也就是如何经由过程对象来形貌可变状况
,或许说为可变状况建模)。我一向将双向绑定视作对立于函数式编程的一种思绪
,不过函数式编程也不是唯一可用的范式,一些人喜好如许的体式格局而且在现实中也
能很好地事情。假如你有兴致相识在 React 中关于状况模子化背地的设想决议计划细
节的话,引荐你寓目 Pete Hunt 的演讲 以及 Tom
Occhina 和 Jordan Walke 的演讲
,他俩把我的看法诠释的非常精
彩。

Update: see also another talk by Pete Hunt: Be predictable, not correct:
functional DOM programming.

更新:同时看看 Pete Hunt 的别的一个演讲:Be predictable, not
correct: functional DOM programming

Native vs. VM

Native browser support (read “guaranteed to be faster”)

原生对决 VM(虚拟机)

浏览器原生支撑(暗示“确保更快”)

Now finally something that is not a matter of opinion.

终究到不是偏好题目的部份了。

Actually here it is exactly the other way around. Of course “native”
code can be written in C++ but what do you think the JavaScript engines
are written in?

好有一比亦具异曲同工之妙,“原生”代码能够用 C++ 来写,不过你以为
JavaScript 引擎是用什么写的呢?

译注:此段不好直译。作者的本意是浏览器的原生支撑是用能够用 C++ 搞定,然则虚
拟机(JavaScript 的诠释器,比方 V8)也是用 C++ 写的),所以不能由于虚
拟机不属于浏览器原生支撑的部份就以为它没有原生支撑“快”。

As a matter of fact the JavaScript engines are truly amazing in the
optimizations that they use today – and not only V8 any more, also
SpiderMonkey and even Chakra shines these days. And keep in mind that
with JIT compilers the code is not only as native as it can possibly be
but there are also run time optimization opportunities that are simply
impossible to do in any statically compiled code.

现实上本日的 JavaScript 引擎的机能优化做得非常精彩——而且不仅仅是 V8,
还包含 SpiderMonkey 甚或 Chakra。要邃晓有了 JIT 编译器,代码(实行)不只
是无穷逼近于原生而且还会有静态编译代码所不具备的运行时优化。

When people think that JavaScript is slow, they usually mean JavaScript
that accesses the DOM. The DOM is slow. It is native, written in C++ and
yet it is slow as hell because of the complexity that it has to
implement.

人们所议论的“JavaScript 很慢”,现实上指的是接见 DOM 的 时刻,DOM 很慢
才是真的。即使它是原生的,运用 C++ 编写,却照样慢到怒不可遏,这是由于它
的完成非常庞杂。

Open your console and write:

翻开控制台(浏览器开发者东西中的)然后实行:

console.dir(document.createElement('div'));

and see how many properties an empty div element that is not even
attached to the DOM has to implement. These are only the first level
properties that are “own properties” ie. not inherited from the
prototype chain:

看看一个空的 div 元素(而且还没有插进去到 DOM)有若干属性要完成吧。这还
只是第一层的也就是“自有属性”,没包含自原型链继续而来的。

align, onwaiting, onvolumechange, ontimeupdate, onsuspend, onsubmit,
onstalled, onshow, onselect, onseeking, onseeked, onscroll, onresize,
onreset, onratechange, onprogress, onplaying, onplay, onpause,
onmousewheel, onmouseup, onmouseover, onmouseout, onmousemove,
onmouseleave, onmouseenter, onmousedown, onloadstart,
onloadedmetadata, onloadeddata, onload, onkeyup, onkeypress,
onkeydown, oninvalid, oninput, onfocus, onerror, onended, onemptied,
ondurationchange, ondrop, ondragstart, ondragover, ondragleave,
ondragenter, ondragend, ondrag, ondblclick, oncuechange,
oncontextmenu, onclose, onclick, onchange, oncanplaythrough,
oncanplay, oncancel, onblur, onabort, spellcheck, isContentEditable,
contentEditable, outerText, innerText, accessKey, hidden,
webkitdropzone, draggable, tabIndex, dir, translate, lang, title,
childElementCount, lastElementChild, firstElementChild, children,
nextElementSibling, previousElementSibling, onwheel,
onwebkitfullscreenerror, onwebkitfullscreenchange, onselectstart,
onsearch, onpaste, oncut, oncopy, onbeforepaste, onbeforecut,
onbeforecopy, webkitShadowRoot, dataset, classList, className,
outerHTML, innerHTML, scrollHeight, scrollWidth, scrollTop,
scrollLeft, clientHeight, clientWidth, clientTop, clientLeft,
offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft,
localName, prefix, namespaceURI, id, style, attributes, tagName,
parentElement, textContent, baseURI, ownerDocument, nextSibling,
previousSibling, lastChild, firstChild, childNodes, parentNode,
nodeType, nodeValue, nodeName

Many of them are actually nested objects – to see second level (own)
properties of an empty native div in your browser, see this fiddle.

它们中有许多现实上照样层叠的对象——要检察浏览器里一个空的原生 div
第二层(自有的)属性,请见这个 fiddle

I mean seriously, onvolumechange property on every single div node? Is
it a mistake? Nope, it’s just a legacy DOM Level 0 traditional event
model version of one of the event handlers “that must be supported by
all HTML elements, as both content attributes and IDL attributes”
[emphasis added] in Section 6.1.6.2 of the HTML spec by W3C – no way
around it.

说真的,有必要让每个 div 节点都包含 onvolumechange 属性吗?这是个错
误?不是的,这只是老旧的 DOM Level 0 版本中传统事宜模子里的一个事宜回调
,它“必需为一切的 HTML 元素所支撑,既作为内容属性也作为 IDL 属性”(重
点强调),定义于 W3C 的 HTML 范例中的 Section 6.1.6.2,无可
逃避。

Meanwhile, these are the first level properties of a fake-DOM div in
React:

与之对应的,以下是 React 中伪 DOM div 元素的第一层属性列表:

props, _owner, _lifeCycleState, _pendingProps, _pendingCallbacks,
_pendingOwner

Quite a difference, isn’t it? In fact this is the entire object
serialized to JSON (LIVE DEMO), because hey you actually can serialize
it to JSON as it doesn’t contain any circular references – something
unthinkable in the world of native DOM (where it would just throw an
exception):

大不一样,不是吗?现实上这是序列化为 JSON 的一全部对象(演示
),因而你完整能够把它序列化成 JSON 由于它不会包含轮回援用,
这在原生 DOM 的天下里是不可设想的(那只会抛出非常)。

{
  "props": {},
  "_owner": null,
  "_lifeCycleState": "UNMOUNTED",
  "_pendingProps": null,
  "_pendingCallbacks": null,
  "_pendingOwner": null
}

This is pretty much the main reason why React can be faster
than the native browser DOM – because it doesn’t have to implement
this mess.

这就是 React 比原生浏览器 DOM 快的主要缘由——它不必完成那些有的没的

See this presentation by Steven Luscher to see what is faster: native
DOM written in C++ or a fake DOM written entirely in JavaScript. It’s
a very fair and entertaining presentation.

看看这个 Steven Luscher 的演讲 吧,看看哪一个更快:用 C++
写的原生 DOM 照样用 JavaScript 写的伪 DOM。这是一个非常平正且有很欢欣的
演讲。

To sum it up: features from Web Components like templates, data binding
or custom elements will have a lot of advantages over React but until
the document object model itself gets significantly simplified then
performance will not be one of them.

总结陈词:WebComponenets 的特性如模板,数据绑定或自定义元素终会有许多胜
于 React 的上风,但是机能绝非其一除非文档对象模子能够获得显著地简化。

    原文作者:n͛i͛g͛h͛t͛i͛r͛e͛
    原文地址: https://segmentfault.com/a/1190000000753400
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞