在Phoenix Framework应用程序的某些页面上包含Javascript

Include Javascript on Certain Pages in Phoenix Framework Application

本文关键字:包含 Javascript Phoenix Framework 应用程序      更新时间:2023-09-26

我有一点Javascript,我只想在Phoenix应用程序的某些页面上包含它。

现在,我已经在myapp/web/templates/post/form.html.eex中的脚本标记中获得了Javascript。

我知道我可以将JavaScript移动到web/static/js/app.js。。。但我不想在每一页上都包含Javascript(只有两个特定的页面需要它)。

在不重复代码和违反DRY原则的情况下,在应用程序的某些页面上加载Javascript的这一部分的最佳方法是什么?

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

结论

现在,只有在使用post视图时才会加载javascript文件post.js

这里有一种实现这一点的方法。

脚本标记中的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页面上执行,因为只有该页面具有id为#lesson-container:的元素

import { startLesson } from './lesson/show.ts';
if (document.querySelector('#lesson-container')) {
  startLesson();
}

这是基于Gazler对该问题的评论,与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"模板,则会呈现该模板。

对于第二个示例,如果存在"scripts." <> @view_template模板(例如scripts.form.html),则会对其进行渲染。

如果视图模块不存在"脚本"模板,则页面HTML中不会输出任何内容。

查看模块

对于在布局模板中使用render_existing/3的第一个示例,您可以向后视图模块添加这样的代码:

def render("scripts.html", _assigns) do
  ~E(<script src="file.js"></script>)
end

第二次你会添加这样的代码:

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中也不会输出任何内容)。

~E sigil提供了"源文件中HTML安全的EEx语法",并且类似于(在大多数情况下,甚至可能总是)cmititiuk的答案中的相应代码:

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

结论

通常,对于任何页面,如果您希望通过页面head(或body末尾)中的script元素导入特定的JavaScript文件,或链接CSS文件,或对布局处理的页面输出部分执行任何操作,如上所述,您可以在布局模板中使用render_existing,然后在这些页面的视图模块中实现适当的render子句。

此外,没有理由不能同时使用上面两个例子中的这样的东西,因此,对于任何视图模块及其模板,都可以:

  • 包括所有视图模块模板(但不是整个应用程序的所有模板)的一些脚本(或CSS文件或以其他方式在布局模板中操纵的HTML输出)
  • 仅为单个模板包含一些脚本(或…)
<script src="myscripts.js"></script>

将代码放入一个新的.js文件中。在相关html文件中包含带有文件路径源的脚本标记。