web-dev-qa-db-ja.com

Phoenix Frameworkアプリケーションの特定のページにJavaScriptを含める

私のフェニックスアプリケーションの特定のページにのみ含めたいJavascriptが少しあります。

現在、myapp/web/templates/post/form.html.eexのスクリプトタグ内にJavascriptがあります。

JavaScriptをweb/static/js/app.jsに移動できることを理解していますが、すべてのページにJavaScriptを含めたくありません(特定の2ページでのみ必要です)。

コードを複製せずにDRY原則に違反せずに、アプリケーションの特定のページにJavaScriptのこのセクションをロードする最良の方法は何ですか?

29
Andrew Hendrie

1。

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)
}}
_

2。

app.html<script src="#{static_path(@conn, "/js/app.js")}"></script>の下に、次を追加します。

_<%= render_existing @view_module, "scripts.html", assigns %>
_

3。

次に、ビューに(おそらく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は、投稿ビューが使用されている場合にのみ読み込まれます。

25
cmititiuc

これを実現する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>
6
Asif Shiraz

別の方法は、ページ固有のクラス/要素を利用することです。たとえば、次のapp.jsのコードは、lesson/showページでのみ#lesson-containerというIDの要素があるため、そのページでのみコードが実行されるようにします。

import { startLesson } from './lesson/show.ts';

if (document.querySelector('#lesson-container')) {
  startLesson();
}
2
xji
<script src="myscripts.js"></script>

コードを新しい.jsファイルに入れます。スクリプトタグをソースと一緒に、関連するhtmlファイルのファイルパスに含めます。

1
Jake Roby

これは 質問に対するガズラーのコメント に基づいており、 よりも少しより一般的な回答です。 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_existingrenderの違いは、参照されたテンプレートが存在しない場合でも前者はエラーを発生させないことです(その場合もページHTMLには何も出力されません)。

The ~E sigil は「ソースファイル内のHTMLセーフEEx構文」を提供し、(ほとんどの場合、または場合によっては常に)対応するコードに似ています cmititiuc's answer =:

~s{<script>require("web/static/js/posts").Post.run()</script>}
|> raw

結論

一般に、ページscripthead要素(またはbodyの末尾)を介して特定のJavaScriptファイルをインポートするか、CSSファイルをリンクするか、その一部のページ出力に何かを実行するページレイアウトで処理される場合は、上記のようにレイアウトテンプレートでrender_existingを使用し、それらのページのビューモジュールに適切なrender句を実装します。

さらに、上記の2つの例のbothのようなものを使用できなかった理由はありません。そのため、ビューモジュールとそのテンプレートについて、両方できます:

  • allビューモジュールテンプレート(すべてではない)のスクリプト(またはCSSファイルを含めるか、レイアウトテンプレートでHTML出力を操作する)を含めるアプリ全体のテンプレート)
  • 単一のテンプレートのみにいくつかのスクリプト(または...)を含めます
0
Kenny Evitt