フロントエンドに長年取り組んできた学生なら 1 つのことを知っているでしょう。それは HTC です。 (HTML コンポーネント)、このものの名前は非常に現代的です。人気のある Web コンポーネントは非常に似ていますが、これらは 2 つの異なるものです。そのアイデアには多くの類似点がありますが、前者は昨日のことであり、後者は優勢です。 . 両者の間にこのギャップが生じるのはなぜでしょうか。
主流のブラウザーの中で HTC をサポートしているのは IE だけであるため、多くの人は無意識のうちにそれが標準ではないと思っていますが、実際には標準ドキュメントもあり、これまでにリンクもありますので、時間に注意してください。
http://www.w3.org/TR/NOTE-HTMLComponents
何ができるか見てみましょう?
HTML ページには 2 つの方法で導入できます。1 つは要素に付加され CSS を使用して導入される「ビヘイビア」として、もう 1 つは HTML タグ システムを拡張する「コンポーネント」としてです。
Behavior は、主にドキュメント構造と動作を分離し、同様のスタイルを通じて動作を分離するために使用される概念です。詳細は、で紹介されています。ここ:
http://msdn.microsoft.com/en-us/library/ms531079(v=vs.85).aspx
HTC ファイルはビヘイビアーにインポートできます。これは HTC 仕様に含まれているので、よりわかりやすくするために抜粋します。
engine.htc
<HTML xmlns:PUBLIC="urn:HTMLComponent"><PUBLIC:EVENT NAME="onResultChange" ID="eventOnResultChange" /><SCRIPT LANGUAGE="JScript">function doCalc(){ : oEvent = createEventObject(); oEvent.result = sResult; eventOnResultChange.fire (oEvent);}
<HTML xmlns:LK="urn:com.microsoft.htc.samples.calc"><HEAD><STYLE> LK\:CALC { behavior:url(engine.htc); } </STYLE></HEAD><LK:CALC ID="myCalc" onResultChange="resultWindow.innerText=window.event.result"><TABLE><TR><DIV ID="resultWindow" STYLE="border: '.025cm solid gray'" ALIGN=RIGHT>0.</DIV></TR><TR><TD><INPUT TYPE=BUTTON VALUE=" 7 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" 8 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" 9 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" / "></TD> <TD><INPUT TYPE=BUTTON VALUE=" C "></TD></TR><TR><TD><INPUT TYPE=BUTTON VALUE=" 4 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" 5 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" 6 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" * "></TD> <TD><INPUT TYPE=BUTTON VALUE=" % " DISABLED></TD></TR><TR><TD><INPUT TYPE=BUTTON VALUE=" 1 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" 2 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" 3 "></TD> <TD><INPUT TYPE=BUTTON VALUE=" - "></TD> <TD><INPUT TYPE=BUTTON VALUE="1/x" DISABLED></TD></TR><TR><TD><INPUT TYPE=BUTTON VALUE=" 0 "></TD> <TD><INPUT TYPE=BUTTON VALUE="+/-"></TD> <TD><INPUT TYPE=BUTTON VALUE=" . "></TD> <TD><INPUT TYPE=BUTTON VALUE=" + "></TD> <TD><INPUT TYPE=BUTTON VALUE=" = "></TD></TR></TABLE></LK:CALC></HTML>
これは計算機の例です。まずはコードの構造を大まかに見てみましょう。ここで、jQuery を使用してこの種のことをどのように実装するかを見てみましょう。セレクターを使用してこれらのボタンを選択し、イベント処理関数を追加します。選択プロセスには追加のステップがあり、プロセス全体で宣言型コーディング スタイルと命令型コーディング スタイルが混在することに注意してください。このアプローチに従う場合、すべての JS は基本的に分離された関連性のないファイルに放り込まれます。プロセス全体は構成プロセスであり、分離は非常に明確です。
仕様書には、この種の計算機に加えて、インターフェイス表示の変更やアニメーションの追加の例もあります。これらのエントリ ポイントは、選択された特定の要素に関連付けられた動作と同等であることに注意してください。 DOM セレクターは CSS セレクターを通じて要素に直接アタッチされるため、JS にセレクターを公開しなくても影響はありません。
これの重要性は現時点では明らかではありませんが、最初に要素を選択してからイベントを追加するために広く使用されており、プレゼンテーションと動作を分離する良い方法でもあります。
しかし、他の使い方は異なります。
狭義の HTML5 は私たちに何をもたらしますか?セクション、ナビ、アクティクルなどの新しい要素タグが多数あります。では、これらを div を使用して直接実装する利点は何でしょうか。それは意味論にあります。
いわゆるセマンティックとは、要素が曖昧さを生じさせることなく、その動作を明確に表現できることを意味します。これは、具体的に何かを表すわけではありませんが、さまざまなものとみなすことができます。使うもの。 nav を書くとすぐに、それがナビゲーションであることがわかります。これは、特定の意味を表現できる、class によって定義されたエンティティ クラスのようなものです。
すると、元の HTML 要素だけでは明らかに不十分です。実際の開発プロセスで表現すべきことは、明らかにこれらの要素をはるかに超えています。たとえば、カレンダーなど、それを記述する要素がありません。言うまでもなく、一部のエンタープライズ アプリケーションにはツリーなどの複雑なコントロールが表示される場合があります。
ネイティブ要素が提供されていないため、コードを書くのが面倒です。 詳細については、Zhihu での以前の回答を参照してください。
http://www.zhihu.com/question/22426434/answer/21433867
つまり、誰もが要素を拡張する独自の方法を提供しようとしていることがわかりましたが、代表的なものは angularjs とポリマーです。初期の頃はそうではありませんでした。
http://msdn.microsoft.com/en-us/library/ms531076(v=vs.85).aspx
これは HTC が追加したカスタマイズです。各要素は、外部から提供される独自の属性、メソッド、イベントを定義できます。内部的には、新しいページを作成するのと同じように機能の実装に集中できます。そして、いいえ、長期的な視点に立って、2 つの異なる組織が提供する同じ名前のカスタム要素を 1 つのページに導入することを防ぐ名前空間を提供していることがわかりました。
これは、外部の世界から完全に分離されており、セレクターを使用して、属性を選択し、メソッドを呼び出すことができます。イベント処理などを追加すると、そのプロパティに get と set があることに気づきました。なんと夢のようなことでしょう。
非常に使いやすいため、当時、ツリー、データ テーブル、日付の選択などのさまざまな基本的なコントロールをカプセル化して、多くのことを行うためにこれを使用しました。そのときは、ブラウザのネイティブの選択とラジオの見栄えが良くないので、画像をカプセル化して機能をシミュレートし、ネイティブのものを置き換えるこのようなものを使用します。
例えば、2004 年には、これを基本的なコントロール以外の場所にも拡張して、すべてがコンポーネントで良いのではないかと考えていました。
但有些事情我直到后来很久以后才想明白,基于业务的端到端组件虽然写起来很方便,却是有致命缺陷的。
到这里为止,对HTML Components的回顾告一段落,也不讨论它为什么就没了之类,这里面争议太大,我只想谈谈从这里面,能看到Web Components这么个大家寄予厚望的新标准需要面对一些什么问题。
以下逐条列出,挨个说明,有的已经有了,有的差一些,有的没有,不管这么多,总之谈谈我心目中的这个东西应当是怎样的。
原因我前面已经说了,可能会有不同组织实现同类功能的组件,存在于同一个页面内,引起命名歧义,所以我想了很久,还是觉得有前缀比较好:
<yours:ComponentA></yours:ComponentA><his:ComponentA></his:ComponentA>
甚至,这里的前缀还可以是个简称别名,比如yours=com.aaa.productA,这可能只有复杂到一定程度才会出现,大家不要以为这太夸张,但总有一天Web体系能构建超大型软件,到那时候你就知道是不是可能了。
这个前一段时间有的浏览器实现过,在组件内部,style上加一个scoped属性,这是正确的方向。为什么要这么干呢,所谓组件,引入成本越小越好,在无约定的情况下都能引入,不造成问题,那是最佳的结果。
如果你一个组件的样式不是局部的,很可能就跟主界面的冲突了,就算你不跟主界面的冲突,怎么保证不跟主界面中包含的其他组件的样式冲突?靠命名约定是不现实的,看长远一些,等你的系统够大,这就是大问题了。
一个自定义组件,应当能够跟主文档进行通讯,这个过程包括两个方向,分别可以有多种不同的方式。
除了事件,真没有什么好办法可以做这个方向的通讯,但事件也可以有两种定义方式,一种是类似onclick那种,主文档应当能够在它上面直接添加对应的事件监听函数,就像对原生元素那样,每个事件都能单独使用。另一种是像postMessage那样,只提供一个通道,具体怎么处理,自己去定义消息格式和处理方式。
这两种实现方式都可行,后者比较偷懒,但也够用了,前者也没有明显优势。
这个也可以有两种方式,一种是组件对外暴露属性或者方法,让主文档调用,一种是外部也通过postMessage往里传。前者用起来会比较方便,后者也能凑合用用。
所以,如果特别偷懒,这个组件就变得像一个iframe那样,跟外部基本都通过postMessage交互。
写到这里我是很纠结的,因为终于来到争议最大的地方了。按照很多人的思路,我这里应该也写隔离成局部作用域的JavaScript才对,但真不行,我们可以先假设组件内部的所有JavaScript都跑在局部作用域,它不能访问主文档中的对象。
我这里解释一下之前那个坑,为什么端到端组件是有缺陷的。
先解释什么叫端到端组件。比如说,我有这么一个组件,它封装了对后端某接口的调用,还有自身的一些展示处理,跟外界通过事件通信。它整个是不需要依赖别人的,初始加载数据都是自己内部做,别人要用它也很简单,直接拿来放在页面里就可以了。
照理说,这东西应当非常好才对,使用起来这么方便,到底哪里不对?我来举个场景。
在页面上同时存在这个组件的多个实例,每个组件都去加载了初始数据,假设它们是不带参数的,每个组件加载的数据都一样,这里是不是就有浪费的请求了?有人可能觉得一点点浪费不算问题,那么继续。
假设这个组件就是一个很普通的下拉列表,用于选取人员的职业,初始可能有医生,教师,警察等等,我把这个组件直接放在界面上,它一出现,就自己去加载了所需的列表信息并且展示了。有另外一个配置界面,用于配置这些职业信息,这时候我在里面添加了一个护士,并且提交了。假设为了数据一致性,我们把这个变更推回到页面,麻烦就出现了。
界面只有一个职业下拉列表的时候可能还好办,有多个的时候,这个更新的策略就有问题了。
如果在组件的内部做这个推送的对接,就会出现要推送多份一致的数据给组件的不同实例的问题。如果把这个放在外面,那我们也有两种方式:
これら 2 つはどちらであっても、データをどこに置くかという問題があります。ソース?
明らかに、コンポーネント内に配置することはできません。「グローバル」な場所にのみ配置できます。ただし、コンポーネント内の JavaScript コードは外部オブジェクトにアクセスできないと考えられます。 🎜 >
しかし、アクセスが許可されている場合、コンポーネントの分離メカニズムは役に立ちません。最善の方法は両方をサポートすることです。デフォルトはローカル スコープであり、JS フレームワークなどには特別なスコープがありますが、ブラウザの実装の難しさははるかに大きい可能性があります。私たちの明るい未来のために問題を作り出すために、なぜ問題をこれほど複雑にし、そのような BT シナリオを使用するのかと疑問に思う人もいるかもしれません。何かを作る前に、常に問題に直面する必要があると思います。
私は Web コンポーネントに対する多くの友人の態度を注意深く観察してきましたが、そのほとんどは完全に肯定的ですが、一部の友人、主にフロントエンド MV* に携わる学生は Web コンポーネントに対して非常に保守的な態度をとっていました。 . 主な原因は私にあるはずです。このグループは主にシングルページ アプリケーションに取り組んでいるため、遭遇する問題は従来のフロントエンドとは異なります。
では、たとえば、Angular や React と Web コンポーネントとのコラボレーション ポイントはどこにあるのでしょうか?個人的にはエンジンは残して、上の部分は徐々にWeb Componentsと統合していくべきだと思っているので、誰が誰を食べるかではなく、どう統合していくかが重要だと思っています。最終的に、フロントエンドには 2 つのレイヤーがあり、1 つはデータおよびビジネス ロジックのレイヤーで、もう 1 つは UI 指向のレイヤーであり、Web コンポーネントのような垂直セグメンテーションが非常に適しています。
最後に、Polymer についての私の意見を共有したいと思います。私の意見は @ Stu Zhengmei ほど粗暴ではありませんが、Polymer の基本的なコンセプトはエンドツーであるため、彼の意見に同意します。コンポーネントを終了すると、多くの課題に直面することになります。コンポーネント化されたフレームワークであるため、コンポーネント化は大規模なコラボレーションの問題を解決するのに最適ですが、大規模なシングルページ アプリケーションへの道筋を見ると、Angular や React に比べてゴールからははるかに遠いです。