毎日たくさんのツールを使用しています。さまざまなライブラリとフレームワークが私たちの毎日の仕事の一部です。ボンネットの下で何が起こっているのかわからなくても、すべてのプロジェクトのホイールを再発明したくないので、それらを使用します。この記事では、最も人気のあるライブラリで起こっている魔法のプロセスのいくつかを明らかにします。また、彼らの動作を再現できるかどうかも確認します
キーテイクアウト- jqueryのようなJavaScriptライブラリは、ネストされた要素のような複雑なケースを正しく処理することにより、文字列から要素を作成するなど、DOM操作を簡素化します。
- AngularJSの依存関係注入システムは、明示的な合格せずに依存関係を魔法のように管理します。インジェクターパターンを使用して、実行時に依存関係を動的に提供します。 ember.jsは、計算されたプロパティでJavaScriptオブジェクトを強化し、プロパティが機能のように動作できるようにし、依存関係が変更されたときに自動的に更新します。
- ReactのJSX構文により、JavaScriptにHTMLを埋め込むことができます。HTMLは、ReactのJSXトランスによって処理され、動的UIコンポーネントを作成します。 この記事は、依存関係の注入と計算された特性のためのカスタムソリューションを示しており、開発者がプロジェクトで同様の機能をどのように実装できるかを示しています。
- 人気のあるJavaScriptフレームワークの基礎となるメカニズムを理解することで、開発者がより効率的で保守可能なコードを作成できるようになります。
- 文字列からdom要素を作成
- シングルページアプリケーションの増加により、JavaScriptで多くのことを行っています。アプリケーションのロジックの大部分がブラウザに移動されました。ページ上の要素を生成または交換することは一般的なタスクです。以下に示すものと同様のコードは非常に一般的になりました。
- 結果は、ドキュメントの本文に追加された新しい要素です。この単純な操作は、1行のjQueryで行われます。 jQueryがなければ、コードはもう少し複雑ですが、それほど多くはありません:
一時的な
要素を作成する独自のユーティリティメソッドStringtodomを定義しました。私たちはそのinnerhtmlプロパティを変更し、最終的に私たちは実際に必要なものである最初の子供を単に返しました。同じように機能しました。ただし、次のコードではさまざまな結果が見られます。視覚的には、ページに違いはありません。ただし、Chromeの開発者ツールで生成されたマークアップを確認すると、興味深い結果が得られます。
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
stringtodom関数は、実際の
タグではなく、テキストノードのみを作成したようです。しかし、同時に、jQueryはなんとかそれをすることができました。問題は、HTML要素を含む文字列がブラウザのパーサーを介して実行されることです。そのパーサーは、正しいコンテキストに配置されていないタグを無視し、テキストノードのみを取得します。テーブルのないテーブルの列は、ブラウザには無効です。 jQueryは、正しいコンテキストを作成することで問題を正常に解決し、必要な部分のみを抽出します。ライブラリのコードを少し掘り下げると、このようなマップが表示されます: <span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
特別な処理を必要とするすべての要素には、配列が割り当てられています。アイデアは、適切なDOM要素を構築し、必要なものを取得するためにネストのレベルに依存することです。たとえば、要素の場合、 子供を持つテーブルを作成する必要があります。したがって、2つのレベルのネストがありますマップがあるため、最終的にどのようなタグが必要かを確認する必要があります。次のコードでは、
のtrを抽出します <span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
の最終的なバリアントですの使用はまだありますが、今回はブラウザが有効なDOMツリーを作成できるように適切なタグを渡しています。最終的には、時間ループを使用することで、必要なタグに到達するまで深く深く進んでいます。'], col: [2, '<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
ここに、実装を示すCodepenがあります:素晴らしいAngularJS依存関係の注入を調査して続けましょう
AngularJS依存性注入を明らかにしますそれは典型的なAngularJSコントローラーです。 HTTP要求を実行し、JSONファイルからデータを取得し、現在のスコープに渡します。 TODOCTRL関数を実行しません。引数を渡す機会はありません。フレームワークはそうします。それで、これらの$スコープと$ http変数はどこから来たのでしょうか?それは非常にクールな機能であり、ブラックマジックに非常に似ています。それがどのように行われているか見てみましょう。
システムにユーザーを表示するJavaScript関数があります。同じ関数は、生成されたHTMLを配置するためにDOM要素にアクセスし、データを取得するAJAXラッパーにアクセスする必要があります。例を簡素化するために、データとHTTPの要求を模倣します。
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
コンテンツホルダーとして
タグを使用します。 AjaxWrapperはリクエストをシミュレートするオブジェクトであり、DataMockupはユーザーを含む配列です。使用する関数は次のとおりです<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
そしてもちろん、displayUsers(body、ajaxwrapper)を実行すると、コンソールでリクエストされているページに3つの名前が表示されます。私たちの方法には、ボディとajaxwrapperの2つの依存関係があると言えます。したがって、アイデアは、議論を渡さずに関数を機能させることです。つまり、DisplayUsers()を呼び出すことで同じ結果を得る必要があります。これまでのところコードでそれを行うと、結果は次のとおりです。Ajaxパラメーターが定義されていないため、
そしてそれは正常です。<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
依存関係注入のメカニズムを提供するフレームワークのほとんどには、通常は
injectorという名前のモジュールがあります。依存関係を使用するには、そこに登録する必要があります。その後、ある時点で、当社のリソースは、同じモジュールによってアプリケーションのロジックに提供されます。 インジェクターを作成してみましょう:
2つの方法は必要です。最初のものである登録は、リソース(依存関係)を受け入れ、内部に保存します。 2番目のものは、注入のターゲット、つまり依存関係を持つ関数とパラメーターとして受信する必要がある関数を受け入れます。ここでの重要な瞬間は、インジェクターが関数を呼び出すべきではないことです。それが私たちの仕事であり、私たちはそれをコントロールできるはずです。 Resolveメソッドでできることは、ターゲットをラップして呼び出す閉鎖を返すことです。たとえば、
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
そのアプローチを使用して、必要な依存関係を持つ関数を呼び出す機会があります。同時に、アプリケーションのワークフローを変更していません。インジェクターはまだ独立したものであり、ロジック関連の機能を保持していません。
もちろん、displayUsers関数をResolveメソッドに渡すことは役に立ちません。<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
それでも同じエラーが発生します。次のステップは、合格したターゲットが必要とするものを見つけることです。その依存関係は何ですか?そして、これがAngularjsから採用できるトリッキーな部分です。繰り返しますが、フレームワークのコードを少し掘り下げて、これを見つけました:
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>
<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) { </span> $http<span>.get('users/users.json').success(function(data) { </span> $scope<span>.users = data; </span> <span>}); </span><span>}</span>
<span>var dataMockup = ['John', 'Steve', 'David']; </span><span>var body = document.querySelector('body'); </span><span>var ajaxWrapper = { </span> <span>get: function(path<span>, cb</span>) { </span> <span>console.log(path + ' requested'); </span> <span>cb(dataMockup); </span> <span>} </span><span>}</span>
argdeclアレイの2番目の要素を取得すると、必要な依存関係の名前が見つかります。名前を使用すると、インジェクターのストレージからリソースを配信できるため、まさにそれが必要なものです。これが私たちの目標をうまくカバーするバージョンです:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
.split(/、?/g)を使用して文字列ドメル、ajaxを配列に変換していることに注意してください。その後、依存関係が登録されているかどうかを確認し、はいの場合はターゲット関数に渡すかどうかを確認します。インジェクターの外側のコードは次のようになります
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
このような実装の利点は、多くの機能にDOM要素とAjaxラッパーを注入できることです。そのようなアプリケーションの構成を配布することもできます。クラスからクラスにオブジェクトを渡す必要はありません。それはただの登録と解決方法です。削除後にコードを動作させたい場合、インジェクターはさらに複雑になります。私たちが知っているように、ミニファイヤーは関数、変数、さらにはメソッドの引数の名前を置き換えます。そして、私たちのロジックはこれらの名前に依存しているため、回避策について考える必要があります。考えられる解決策の1つは、Angularjsから再び登場することです:
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
実際の例:
CodepenでKrasimir Tsonev(@krasimir)によるペンBxdarを参照してください。 Emberの計算されたプロパティの採用
FirstNameおよびLastNameプロパティを備えたクラスがあります。計算されたプロパティのフルネームは、その人のフルネームを含む連結文字列を返します。奇妙なことは、フルネームに適用された関数に対して.propertyメソッドを使用する部分です。私は個人的にそれを他のどこにも見ませんでした。そして、繰り返しになりますが、フレームワークのコードをすばやく見て、魔法が明らかになります:
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
ライブラリは、新しいプロパティを追加することにより、グローバル関数オブジェクトのプロトタイプを微調整します。クラスの定義中にロジックを実行するのは素晴らしいアプローチです。
Emberは、GettersとSetterを使用して、オブジェクトのデータを使用して動作します。これにより、実際の変数に到達するために1つのレイヤーが1つあるため、計算されたプロパティの実装が簡素化されます。ただし、プレーンJavaScriptオブジェクトで計算されたプロパティを使用できれば、さらに興味深いでしょう。たとえば、
のように<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
名前は通常のプロパティとして使用されますが、実際には、firstNameとlastNameを取得または設定する関数です。
JavaScriptのビルドイン機能があり、そのアイデアを実現するのに役立ちます。次のスニペットをご覧ください:<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
object.definePropertyメソッドは、スコープ、プロパティの名前、ゲッター、セッターを受け入れることができます。私たちがしなければならないのは、2つの方法の本体を書くことです。そして、それだけです。上記のコードを実行できるようになり、期待される結果が得られます。<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
名前メソッドをセッターとして、同時にゲッターと同時に使用したいと考えています。これは、Emberの計算されたプロパティに似ています
ここで、関数オブジェクトのプロトタイプに独自のロジックを追加しましょう:<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
上記の行を追加すると、すべての関数定義の最後に.computed()を追加できます。
その結果、名前プロパティには機能が含まれなくなりましたが、古い関数で満たされたTrueおよびFUNCプロパティに等しいプロパティを計算したオブジェクトです。本当の魔法は、コンピューターヘルパーの実装で起こります。オブジェクトのすべてのプロパティを通過し、Object.definePropertyを使用します。
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
元のプロパティ名を削除していることに注意してください。一部のブラウザObject.DefinePropertyでは、まだ定義されていないプロパティでのみ動作します。.computed()関数を使用するユーザーオブジェクトの最終バージョンはあります。
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>
フルネームを返す関数は、FirstNameとLastNameを変更するために使用されます。それは、合格した引数のチェックと最初の議論の処理の背後にあるアイデアです。それが存在する場合、私たちはそれを分割し、通常のプロパティに値を適用します。
すでに目的の使用法について言及しましたが、もう一度見てみましょう:<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) { </span> $http<span>.get('users/users.json').success(function(data) { </span> $scope<span>.users = data; </span> <span>}); </span><span>}</span>
CodepenでKrasimir Tsonev(@krasimir)によるPen Ahpqoを参照してください。
クレイジーな反応テンプレート
おそらく、Facebookのフレームワークの反応について聞いたことがあるでしょう。それは、すべてがコンポーネントであるという考えを中心に構築されています。興味深いのは、コンポーネントの定義です。次の例を見てみましょう:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
最初に考え始めるのは、これがJavaScriptであるということですが、それは無効なものです。レンダリング関数があり、おそらくエラーが発生します。ただし、このコードは、カスタムタイプ属性を備えた<script>タグに入れられることです。ブラウザはそれを処理しません。つまり、エラーから安全であることを意味します。 Reactには、有効なJavaScriptに書かれたコードを変換する独自のパーサーがあります。 Facebookの開発者は、XML Like Language <em> jsx と呼ばれていました。 JSXトランスは390Kで、約12000行のコードが含まれています。だから、それは少し複雑です。このセクションでは、シンプルなものを作成しますが、それでも非常に強力です。 ReactのスタイルでHTMLテンプレートを解析するJavaScriptクラス。 </script>
Facebookが行ったアプローチは、JavaScriptコードとHTMLマークアップを混合することです。したがって、次のテンプレートがあるとしましょう<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
', '
'], _default: [1, '', ' ', ''] }; wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td;さあ、解析機能を書きましょう。私たちの最初のタスクは、HTMLを式と区別することです。式とは、の間に置かれる文字列を意味します。正規表現を使用してそれらを見つけます。また、すべてのマッチを通過するためにシンプルな間ループを使用します。<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
のように<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>
機能の本体を構築することができます。ですから、私たちは表現の位置と、それらの背後に正確に立っているものを知っています。一時的な配列とカーソルを使用する場合、サイクルはそのようになります:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
コンソールの出力は、私たちが正しい軌道に乗っていることを示しています:
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
コード配列は、関数の本体となる文字列に変換する必要があります。たとえば、
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
この結果を達成するのは非常に簡単です。コード配列のすべての要素を通過して、アイテムが文字列またはオブジェクトであるかどうかをチェックするループを作成する場合があります。ただし、これは再びケースの一部のみをカバーします。次のテンプレートを持っている場合はどうなりますか:
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
式を連結するだけで、色がリストされていることを期待することはできません。したがって、文字列を文字列に追加する代わりに、配列に収集します。ここに、解析関数の更新バージョンがあります:
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
コード配列が入力されたら、関数の本体の構築を開始します。テンプレートのすべての行は、配列rに保存されます。行が文字列の場合、引用符を逃れ、新しい行とタブを削除することで、少しクリアしています。プッシュメソッドを介して配列に追加されます。コードスニペットがある場合は、有効なJavaScriptオペレーターではないかどうかを確認します。はいの場合、それを配列に追加するのではなく、単に新しいラインとしてドロップするだけです。エンド出力のconsole.log:
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>
いいねコンポーネントのコンテキストで実行される適切にフォーマットされた作業JavaScriptは、目的のHTMLマークアップを生成します。
残っている最後のものは、実質的に作成された機能の実際の実行です:<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) { </span> $http<span>.get('users/users.json').success(function(data) { </span> $scope<span>.users = data; </span> <span>}); </span><span>}</span>
コンポーネントのコンテキストで実行するために、コードをステートメントでラップしました。それなしでは、タイトルと色の代わりにthis.titleとthis.colorsを使用する必要があります。要約
大きなフレームワークとライブラリの背後には、スマート開発者がいます。彼らは、些細なことではなく、魔法のようなトリッキーなソリューションを見つけて使用しています。この記事では、その魔法のいくつかを明らかにしました。 JavaScriptの世界では、私たちが最高から学び、彼らのコードを使用できるのは素晴らしいことです。 この記事のコードは、githubからダウンロードできます。 JavaScriptの魔法に関するよくある質問(FAQ)
JavaScriptの魔法の方法とは何ですか?それらはどのように機能しますか?
JavaScriptの魔法の方法は、クラスの動作にフックを提供する特別な方法です。それらは直接呼び出されませんが、特定のアクションが実行されると呼び出されます。たとえば、toString()メソッドは、オブジェクトをテキスト値として表現する必要がある場合に自動的に呼び出される魔法の方法です。別の例は、valueof()メソッドです。これは、オブジェクトがプリミティブ値として表される場合に呼び出されます。
JavaScriptで魔法のメソッドを使用するにはどうすればよいですか?
JavaScriptのマジックメソッドは、オブジェクトまたはクラスでそれらを定義することで使用できます。たとえば、オブジェクトにtoString()メソッドを定義して、オブジェクトが文字列として表現される方法をカスタマイズできます。簡単な例は次のとおりです。
let person = {
firstName: "john"、
lastName: "doe"、
toString:function(){
return this.firstname " "this.lastname;
}
};
console.log(person.tostring()); // "John doe"javascriptの魔法の機能の重要性は何ですか?
javascriptの魔法機能は、特定の状況でオブジェクトの動作を制御およびカスタマイズできるため、重要です。彼らはあなたのコードをより直感的で理解しやすくすることができ、あなたのデータをカプセル化して保護する方法を提供することができます。 JavaScriptの魔法の機能の例をいくつか紹介します。 toString():このメソッドは、オブジェクトを表す文字列を返します。 valueof():このメソッドは、オブジェクトのプリミティブ値を返します。 hasownProperty():このメソッドは、オブジェクトに指定されたプロパティがあるかどうかを示すブール値を返します。魔法の方法は非常に便利であり、いくつかの制限もあります。 1つは、特にそれらがどのように機能するかに慣れていない場合、コードをより複雑でデバッグしにくくすることができます。また、正しく使用されないと予期しない動作につながる可能性があります。 「魔法の方法」。ただし、toString()やvalueof()など、同様に動作する特定の方法があります。これらの方法は、他の言語の魔法の方法によく似た特定の状況で自動的に呼び出されます。それらを使用する時期を理解し、それらを控えめに使用して複雑さを避け、常にコードを徹底的にテストして、予想どおりに動作するようにしてください。 ReactやvueなどのJavaScriptフレームワーク?
はい、Magic Methodは、ReactやVueなどのJavaScriptフレームワークで使用できます。ただし、それらの使用方法は、フレームワークによって異なる場合があります。特定のフレームワークのドキュメントをガイダンスするためのドキュメントを参照することが常に最善です。
javascriptで魔法の方法についてもっと知るにはどうすればよいですか?
JavaScriptの魔法の方法について詳しく知るために利用できるリソースがたくさんあります。公式のJavaScriptドキュメント、およびオンラインチュートリアルやコースから始めることができます。また、自分のプロジェクトでそれらを使用して実践的な体験を得ることもできます。 JavaScriptでマジックメソッドの使用に役立つツール。たとえば、Lodashは人気のJavaScriptユーティリティライブラリで、配列、オブジェクト、その他の種類のデータを使用するための役立つ方法を提供します。
以上がJavaScriptの魔法を明らかにしますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール
