AbsurdJS自体は主にNodeJS用のモジュールとしてリリースされていますが、クライアント版もリリースされています。これを念頭に置くと、既存のエンジンのほとんどは NodeJS 上で実行され、ブラウザ上では実行できないため、既存のエンジンを直接使用することはできません。
最初のアイデアは次のとおりです:
var TemplateEngine = function(tpl, data) { // magic here ... } var template = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>'; console.log(TemplateEngine(template, { name: "Krasimir", age: 29 }));
単純な関数、入力はテンプレートとデータオブジェクト、出力はおそらく次のように考えるのが簡単です:
<p>Hello, my name is Krasimir. I'm 29 years old.</p>
その中には最初のステップは、内部のテンプレート パラメーターを見つけて、エンジンに渡される特定のデータで置き換えることです。このステップを実行するには正規表現を使用することにしました。ただし、私はこれが得意ではないので、文章が良くない場合は遠慮なくコメントしてください。
var re = /<%([^%>]+)?%>/g;
この正規表現は、 で終わるすべてのフラグメントをキャプチャします。最後のパラメータ g (global) は、1 つだけが一致するのではなく、一致するすべてのフラグメントが一致することを意味します。 Javascript では正規表現を使用する方法がたくさんあります。必要なのは、正規表現に基づいてすべての文字列を含む配列を出力することです。これがまさに exec の機能です。
var re = /<%([^%>]+)?%>/g; var match = re.exec(tpl);
console.log を使用して変数の一致を出力すると、次のようになります:
[ "<%name%>", " name ", index: 21, input: "<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>" ]
しかし、返された配列には最初に一致した項目のみが含まれていることがわかります。すべての一致を取得できるように、上記のロジックを while ループでラップする必要があります。
var re = /<%([^%>]+)?%>/g; while(match = re.exec(tpl)) { console.log(match); }
上記のコードを実行すると、 と が両方とも出力されることがわかります。
ここからが興味深い部分です。テンプレート内の一致を特定したら、それらを関数に渡される実際のデータに置き換える必要があります。最も簡単な方法は、replace 関数を使用することです。次のように書くこともできます:
var TemplateEngine = function(tpl, data) { var re = /<%([^%>]+)?%>/g; while(match = re.exec(tpl)) { tpl = tpl.replace(match[0], data[match[1]]) } return tpl; }
さて、うまくいきましたが、十分ではありません。ここでは単純なオブジェクトを使用して data["property"] の形式でデータを渡しますが、実際の状況では、より複雑なネストされたオブジェクトが必要になる可能性があります。そこで、データ オブジェクトを少し変更しました:
{ name: "Krasimir Tsonev", profile: { age: 29 } }
しかし、このように直接書いても、やはり実行されません。なぜなら、テンプレートで を使用すると、コードがdata['profile .age'] に置き換えた場合、結果は未定義です。このように、単純に replace 関数を使用することはできず、他の方法を使用する必要があります。次のように、JavaScript コードを の間で直接使用して、受信データを直接評価できるようにするのが最善です:
var template = '<p>Hello, my name is <%this.name%>. I\'m <%this.profile.age%> years old.</p>';
これはどのように実現されるのでしょうか?ここで、John は新しい Function 構文を使用して、文字列に基づいた関数を作成します。例を見てみましょう:
var fn = new Function("arg", "console.log(arg + 1);"); fn(2); // outputs 3
fn は本物の関数です。パラメータを 1 つ受け取り、関数本体は console.log(arg + 1); です。上記のコードは、次のコードと同等です:
var fn = function(arg) { console.log(arg + 1); } fn(2); // outputs 3
このメソッドを使用すると、パラメーターと関数本体を含む文字列から関数を構築できます。これこそまさに私たちが望んでいることではないでしょうか!しかし、心配しないでください。関数を構築する前に、関数本体がどのようなものかを見てみましょう。前述の考え方によれば、このテンプレート エンジンの最終的な戻り値はコンパイルされたテンプレートである必要があります。引き続き前のテンプレート文字列を例として使用すると、返されるコンテンツは次のようになります:
return "<p>Hello, my name is " + this.name + ". I\'m " + this.profile.age + " years old.</p>";
もちろん、実際のテンプレート エンジンでは、テンプレートを小さなテキストと意味のある Javascript コードに分割します。これまでに、目的の効果を達成するために単純な文字列の連結を使用しているのを見たかもしれませんが、これは要件を 100% 満たしているわけではありません。ユーザーはより複雑な Javascript コードを渡す可能性が高いため、次のように、ここで別のループが必要です:
var template = 'My skills:' + '<%for(var index in this.skills) {%>' + '<a href=""><%this.skills[index]%></a>' + '<%}%>';
文字列連結を使用する場合、コードは次のようになります:
return 'My skills:' + for(var index in this.skills) { + '<a href="">' + this.skills[index] + '</a>' + }
Ofもちろん、このコードを直接実行することはできません。実行しないとエラーが発生します。そこで、ジョンの記事に書かれたロジックを使用し、すべての文字列を配列に入れ、プログラムの最後でそれらをつなぎ合わせました。
var r = []; r.push('My skills:'); for(var index in this.skills) { r.push('<a href="">'); r.push(this.skills[index]); r.push('</a>'); } return r.join('');
次のステップは、テンプレート内のさまざまなコード行を収集して関数を生成することです。前に紹介した方法により、テンプレート内のどのプレースホルダー (翻訳者注: または正規表現の一致) とその位置を知ることができます。したがって、補助変数 (カーソル、カーソル) に依存して、望ましい結果を得ることができます。
var TemplateEngine = function(tpl, data) { var re = /<%([^%>]+)?%>/g, code = 'var r=[];\n', cursor = 0; var add = function(line) { code += 'r.push("' + line.replace(/"/g, '\\"') + '");\n'; } while(match = re.exec(tpl)) { add(tpl.slice(cursor, match.index)); add(match[1]); cursor = match.index + match[0].length; } add(tpl.substr(cursor, tpl.length - cursor)); code += 'return r.join("");'; // <-- return the result console.log(code); return tpl; } var template = '<p>Hello, my name is <%this.name%>. I\'m <%this.profile.age%> years old.</p>'; console.log(TemplateEngine(template, { name: "Krasimir Tsonev", profile: { age: 29 } }));
上述代码中的变量code保存了函数体。开头的部分定义了一个数组。游标cursor告诉我们当前解析到了模板中的哪个位置。我们需要依靠它来遍历整个模板字符串。此外还有个函数add,它负责把解析出来的代码行添加到变量code中去。有一个地方需要特别注意,那就是需要把code包含的双引号字符进行转义(escape)。否则生成的函数代码会出错。如果我们运行上面的代码,我们会在控制台里面看见如下的内容:
var r=[]; r.push("<p>Hello, my name is "); r.push("this.name"); r.push(". I'm "); r.push("this.profile.age"); return r.join("");
等等,貌似不太对啊,this.name和this.profile.age不应该有引号啊,再来改改。
var add = function(line, js) { js? code += 'r.push(' + line + ');\n' : code += 'r.push("' + line.replace(/"/g, '\\"') + '");\n'; } while(match = re.exec(tpl)) { add(tpl.slice(cursor, match.index)); add(match[1], true); // <-- say that this is actually valid js cursor = match.index + match[0].length; }
占位符的内容和一个布尔值一起作为参数传给add函数,用作区分。这样就能生成我们想要的函数体了。
var r=[]; r.push("<p>Hello, my name is "); r.push(this.name); r.push(". I'm "); r.push(this.profile.age); return r.join("");
剩下来要做的就是创建函数并且执行它。因此,在模板引擎的最后,把原本返回模板字符串的语句替换成如下的内容:
return new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
我们甚至不需要显式地传参数给这个函数。我们使用apply方法来调用它。它会自动设定函数执行的上下文。这就是为什么我们能在函数里面使用this.name。这里this指向data对象。
模板引擎接近完成了,不过还有一点,我们需要支持更多复杂的语句,比如条件判断和循环。我们接着上面的例子继续写。
var template = 'My skills:' + '<%for(var index in this.skills) {%>' + '<a href="#"><%this.skills[index]%></a>' + '<%}%>'; console.log(TemplateEngine(template, { skills: ["js", "html", "css"] }));
这里会产生一个异常,Uncaught SyntaxError: Unexpected token for。如果我们调试一下,把code变量打印出来,我们就能发现问题所在。
var r=[]; r.push("My skills:"); r.push(for(var index in this.skills) {); r.push("<a href=\"\">"); r.push(this.skills[index]); r.push("</a>"); r.push(}); r.push(""); return r.join("");
带有for循环的那一行不应该被直接放到数组里面,而是应该作为脚本的一部分直接运行。所以我们在把内容添加到code变量之前还要多做一个判断。
var re = /<%([^%>]+)?%>/g, reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g, code = 'var r=[];\n', cursor = 0; var add = function(line, js) { js? code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n' : code += 'r.push("' + line.replace(/"/g, '\\"') + '");\n'; }
这里我们新增加了一个正则表达式。它会判断代码中是否包含if、for、else等等关键字。如果有的话就直接添加到脚本代码中去,否则就添加到数组中去。运行结果如下:
var r=[]; r.push("My skills:"); for(var index in this.skills) { r.push("<a href=\"#\">"); r.push(this.skills[index]); r.push("</a>"); } r.push(""); return r.join("");
当然,编译出来的结果也是对的。
My skills:<a href="#">js</a><a href="#">html</a><a href="#">css</a>
最后一个改进可以使我们的模板引擎更为强大。我们可以直接在模板中使用复杂逻辑,例如:
var template = 'My skills:' + '<%if(this.showSkills) {%>' + '<%for(var index in this.skills) {%>' + '<a href="#"><%this.skills[index]%></a>' + '<%}%>' + '<%} else {%>' + '<p>none</p>' + '<%}%>'; console.log(TemplateEngine(template, { skills: ["js", "html", "css"], showSkills: true }));
除了上面说的改进,我还对代码本身做了些优化,最终版本如下:
var TemplateEngine = function(html, options) { var re = /<%([^%>]+)?%>/g, reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g, code = 'var r=[];\n', cursor = 0; var add = function(line, js) { js? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') : (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : ''); return add; } while(match = re.exec(html)) { add(html.slice(cursor, match.index))(match[1], true); cursor = match.index + match[0].length; } add(html.substr(cursor, html.length - cursor)); code += 'return r.join("");'; return new Function(code.replace(/[\r\t\n]/g, '')).apply(options); }
以上がJavaScript を使用してテンプレート エンジン コードのアイデアと詳細な例を作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

はい、JavaScriptのエンジンコアはCで記述されています。1)C言語は、JavaScriptエンジンの開発に適した効率的なパフォーマンスと基礎となる制御を提供します。 2)V8エンジンを例にとると、そのコアはCで記述され、Cの効率とオブジェクト指向の特性を組み合わせて書かれています。3)JavaScriptエンジンの作業原理には、解析、コンパイル、実行が含まれ、C言語はこれらのプロセスで重要な役割を果たします。

JavaScriptは、Webページのインタラクティブ性とダイナミズムを向上させるため、現代のWebサイトの中心にあります。 1)ページを更新せずにコンテンツを変更できます。2)Domapiを介してWebページを操作する、3)アニメーションやドラッグアンドドロップなどの複雑なインタラクティブ効果、4)ユーザーエクスペリエンスを改善するためのパフォーマンスとベストプラクティスを最適化します。

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

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テクノロジーを通じて達成されます。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

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

メモ帳++7.3.1
使いやすく無料のコードエディター

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

ホットトピック









