私のフェニックスアプリケーションの特定のページにのみ含めたいJavascriptが少しあります。
現在、myapp/web/templates/post/form.html.eex
のスクリプトタグ内にJavascriptがあります。
JavaScriptをweb/static/js/app.js
に移動できることを理解していますが、すべてのページにJavaScriptを含めたくありません(特定の2ページでのみ必要です)。
コードを複製せずにDRY原則に違反せずに、アプリケーションの特定のページにJavaScriptのこのセクションをロードする最良の方法は何ですか?
form.html.eexのすべてのjavascriptを独自のファイルに入れます(多分js/posts.jsのようなもの)。
これを下部に追加します。
_export var Post = { run: function() {
// put initializer stuff here
// for example:
// $(document).on('click', '.remove-post', my_remove_post_function)
}}
_
app.htmlの<script src="#{static_path(@conn, "/js/app.js")}"></script>
の下に、次を追加します。
_<%= render_existing @view_module, "scripts.html", assigns %>
_
次に、ビューに(おそらくviews/post_view.ex)、次のようなメソッドを追加します。
_def render("scripts.html", _assigns) do
~s{<script>require("web/static/js/posts").Post.run()</script>}
|> raw
end
_
これで、JavaScriptファイルpost.jsは、投稿ビューが使用されている場合にのみ読み込まれます。
これを実現する1つの方法を次に示します。
スクリプトタグ内にあるJavaScriptは、それを別のファイルに移動します。
「通常の」JavaScript(すべてのページに含まれる)とこのカスタムJavaScript(特定のページに含まれる)を別々のディレクトリに分割します。例えばapp/common/standard.jsおよびapp/custom/unique.js
Brunch-config.jsを次のように変更します。
module.exports = {
files: {
javascripts: {
joinTo: {
'custom.js': /^app[\\\/]common[\\\/][\S*?]\.js/,
'app.js': /^app[\\\/]common[\\\/][\S*?]\.js/
}
}
}
次に、すべてのページにapp.jsを含めます。
<script src="<%= static_path(@conn, "/js/app.js") %>"></script>
しかし、custom.jsは、それを必要とするページ(またはレイアウト)テンプレートでのみです。
<script src="<%= static_path(@conn, "/js/custom.js") %>"></script>
別の方法は、ページ固有のクラス/要素を利用することです。たとえば、次のapp.js
のコードは、lesson/show
ページでのみ#lesson-container
というIDの要素があるため、そのページでのみコードが実行されるようにします。
import { startLesson } from './lesson/show.ts';
if (document.querySelector('#lesson-container')) {
startLesson();
}
<script src="myscripts.js"></script>
コードを新しい.jsファイルに入れます。スクリプトタグをソースと一緒に、関連するhtmlファイルのファイルパスに含めます。
これは 質問に対するガズラーのコメント に基づいており、 よりも少しより一般的な回答です。 cmititiuc 。その回答のようにページ固有のJavaScriptコードを厳密にラップする必要はなく、ページ固有のscript
要素にページ固有のファイルをインポートする以外に何もする必要はありません。
次のようなレイアウトで Phoenix.View.render_existing/3
を使用します。
<head>
<%= render_existing @view_module, "scripts.html", assigns %>
</head>
...またはこれ:
<head>
<%= render_existing @view_module, "scripts." <> @view_template, assigns %>
</head>
最初の例では、関連するビューモジュールに"scripts.html"
テンプレートが存在する場合、これがレンダリングされます。
2番目の例の場合、"scripts." <> @view_template
テンプレート。 scripts.form.html、存在する場合はレンダリングされます。
'scripts'テンプレートがビューモジュールに存在しない場合、ページHTMLには何も出力されません。
レイアウトテンプレートでrender_existing/3
を使用する最初の例では、次のようなコードを投稿ビューモジュールに追加します。
def render("scripts.html", _assigns) do
~E(<script src="file.js"></script>)
end
...そして、2番目に、次のようなコードを追加します。
def render("scripts.show.html", _assigns) do
~E(<script src="show-file.js"></script>)
end
def render("scripts.index.html", _assigns) do
~E(<script src="index-file.js"></script>)
end
render_existing
とrender
の違いは、参照されたテンプレートが存在しない場合でも前者はエラーを発生させないことです(その場合もページHTMLには何も出力されません)。
The ~E
sigil は「ソースファイル内のHTMLセーフEEx構文」を提供し、(ほとんどの場合、または場合によっては常に)対応するコードに似ています cmititiuc's answer =:
~s{<script>require("web/static/js/posts").Post.run()</script>}
|> raw
一般に、ページscript
のhead
要素(またはbody
の末尾)を介して特定のJavaScriptファイルをインポートするか、CSSファイルをリンクするか、その一部のページ出力に何かを実行するページレイアウトで処理される場合は、上記のようにレイアウトテンプレートでrender_existing
を使用し、それらのページのビューモジュールに適切なrender
句を実装します。
さらに、上記の2つの例のbothのようなものを使用できなかった理由はありません。そのため、ビューモジュールとそのテンプレートについて、両方できます: