在 Eleventy 中执行小型客户端 JavaScript 的最佳方式是什么?
What's the best way to perform small client-side JavaScript in Eleventy?
问题
我想在我的 Eleventy 网站上添加一点客户端 JavaScript。我似乎无法使用 Eleventy 访问 document.
,这意味着我无法访问元素并听取它们的事件。 不的例子:
const formElement = document.querySelector("form")
我从 Eleventy 收到的错误消息:
ReferenceError: document is not defined
问题
如何使用 Eleventy 来侦听文档元素更改并进行页面更改?
示例:
formElement.addEventListener("change", function () {
// Update nearby paragraph element based on form value
});
我的真实场景:我想要一个段落元素显示 form
的 input type="radio"
中的哪个具有值 checked
。
目前接近
我在 /data 中有一个名为 fruits.json:
的文件
{
"items": [
{
"name": "Apple"
},
{
"name": "Banana"
},
{
"name": "Strawberry"
},
{
"name": "Mango"
},
{
"name": "Peach"
},
{
"name": "Watermelon"
},
{
"name": "Blueberry"
}
]
}
还有一个 HTML 文件在 /_includes/layouts based 我的 base.html 文件:
{% extends "layouts/base.html" %}
{% block content %}
<form>
{% for item in fruits.items %}
{# Create a radio button for each, with the first one checked by default #}
<input type="radio" name="screen" id="{{ item.name | slug }}" value="{{ item.name | slug }}" {% if loop.index === 1 %} checked {% endif %}>
<label for="{{ item.name | slug }}">{{ item.name }}</label>
{% endfor %}
{% set selectedFruit = helpers.getSelectedFruit() %}
<p>Currently selected item from above is: {{ selectedFruit }}</p>
</form>
{% endblock %}
请注意,名为 selectedFruit
的变量已分配给辅助函数:
{% set selectedScreen = helpers.getSelectedScreen() %}
那个 getSelectedScreen()
函数看起来像:
getSelectedScreen() {
const formEl = document.querySelector("form")
console.log(formEl)
}
除了无法使用 .document
之外,我觉得这种方法可能是 'against the grain' 的 Eleventy,其他方面的静态站点生成器:
- 正在文档中间调用脚本
- 该脚本是一次性的并且脱离了它的上下文
我想知道我是否一开始就犯了这个错误,或者我是否只需要做一些事情来允许 .document
访问。
这里有一些误解 — 您的 JavaScript 代码最重要的区别是它是在 构建时间 还是在 客户端执行运行时间.
Eleventy 核心以及您的 .eleventy.js
配置文件都写在 JavaScript 中,它在构建步骤中执行一次,即在生成静态站点时执行一次。这发生在 NodeJS 环境中,而不是在浏览器中,这就是为什么没有 document
变量也没有 DOM.
的原因
如果您想动态更改网站上的某些内容以响应用户交互,您需要编写一个单独的 JavaScript 文件,该文件被复制到静态网站的输出目录中。然后,您可以将其包含在静态网站的 HTML 模板中,以便在部署网站后的正常页面访问期间包含它。
首先,修改您的模板,只为您的 JavaScript 函数生成一个占位符元素,以便稍后添加文本:
{% extends "layouts/base.html" %}
{% block content %}
<form id="fruits-form">
{% for item in fruits.items %}
{# Create a radio button for each, with the first one checked by default #}
<input type="radio" name="screen" id="{{ item.name | slug }}" value="{{ item.name | slug }}" {% if loop.index === 1 %} checked {% endif %}>
<label for="{{ item.name | slug }}">{{ item.name }}</label>
{% endfor %}
<p id="selected-fruits-output"></p>
</form>
{% endblock %}
然后,创建一个 JavaScript 文件来响应表单上的更改事件:
// fruit-form.js
const fruitForm = document.getElementById('fruits-form');
const formOutput = document.getElementById('selected-fruits-output');
fruitForm.addEventListener('change', e => {
// update the formOutput with the list of selected fruits
});
现在你需要确保这个 javascript 文件被复制到你的输出目录,使用 Passthrough file copy:
eleventyConfig.addPassthroughCopy("path/to/fruit-form.js");
最后,确保在您的 HTML 模板中包含脚本元素(确保路径是上面指定的输出的绝对路径):
{# layouts/base.html #}
<script src="/path/to/fruit-form.js" defer></script>
现在它应该可以正常工作了。通常,请确保了解构建时和运行时之间的区别 JavaScript,以便您可以决定在不同情况下哪个最有效。
问题
我想在我的 Eleventy 网站上添加一点客户端 JavaScript。我似乎无法使用 Eleventy 访问 document.
,这意味着我无法访问元素并听取它们的事件。 不的例子:
const formElement = document.querySelector("form")
我从 Eleventy 收到的错误消息:
ReferenceError: document is not defined
问题
如何使用 Eleventy 来侦听文档元素更改并进行页面更改?
示例:
formElement.addEventListener("change", function () {
// Update nearby paragraph element based on form value
});
我的真实场景:我想要一个段落元素显示 form
的 input type="radio"
中的哪个具有值 checked
。
目前接近
我在 /data 中有一个名为 fruits.json:
的文件{
"items": [
{
"name": "Apple"
},
{
"name": "Banana"
},
{
"name": "Strawberry"
},
{
"name": "Mango"
},
{
"name": "Peach"
},
{
"name": "Watermelon"
},
{
"name": "Blueberry"
}
]
}
还有一个 HTML 文件在 /_includes/layouts based 我的 base.html 文件:
{% extends "layouts/base.html" %}
{% block content %}
<form>
{% for item in fruits.items %}
{# Create a radio button for each, with the first one checked by default #}
<input type="radio" name="screen" id="{{ item.name | slug }}" value="{{ item.name | slug }}" {% if loop.index === 1 %} checked {% endif %}>
<label for="{{ item.name | slug }}">{{ item.name }}</label>
{% endfor %}
{% set selectedFruit = helpers.getSelectedFruit() %}
<p>Currently selected item from above is: {{ selectedFruit }}</p>
</form>
{% endblock %}
请注意,名为 selectedFruit
的变量已分配给辅助函数:
{% set selectedScreen = helpers.getSelectedScreen() %}
那个 getSelectedScreen()
函数看起来像:
getSelectedScreen() {
const formEl = document.querySelector("form")
console.log(formEl)
}
除了无法使用 .document
之外,我觉得这种方法可能是 'against the grain' 的 Eleventy,其他方面的静态站点生成器:
- 正在文档中间调用脚本
- 该脚本是一次性的并且脱离了它的上下文
我想知道我是否一开始就犯了这个错误,或者我是否只需要做一些事情来允许 .document
访问。
这里有一些误解 — 您的 JavaScript 代码最重要的区别是它是在 构建时间 还是在 客户端执行运行时间.
Eleventy 核心以及您的 .eleventy.js
配置文件都写在 JavaScript 中,它在构建步骤中执行一次,即在生成静态站点时执行一次。这发生在 NodeJS 环境中,而不是在浏览器中,这就是为什么没有 document
变量也没有 DOM.
如果您想动态更改网站上的某些内容以响应用户交互,您需要编写一个单独的 JavaScript 文件,该文件被复制到静态网站的输出目录中。然后,您可以将其包含在静态网站的 HTML 模板中,以便在部署网站后的正常页面访问期间包含它。
首先,修改您的模板,只为您的 JavaScript 函数生成一个占位符元素,以便稍后添加文本:
{% extends "layouts/base.html" %}
{% block content %}
<form id="fruits-form">
{% for item in fruits.items %}
{# Create a radio button for each, with the first one checked by default #}
<input type="radio" name="screen" id="{{ item.name | slug }}" value="{{ item.name | slug }}" {% if loop.index === 1 %} checked {% endif %}>
<label for="{{ item.name | slug }}">{{ item.name }}</label>
{% endfor %}
<p id="selected-fruits-output"></p>
</form>
{% endblock %}
然后,创建一个 JavaScript 文件来响应表单上的更改事件:
// fruit-form.js
const fruitForm = document.getElementById('fruits-form');
const formOutput = document.getElementById('selected-fruits-output');
fruitForm.addEventListener('change', e => {
// update the formOutput with the list of selected fruits
});
现在你需要确保这个 javascript 文件被复制到你的输出目录,使用 Passthrough file copy:
eleventyConfig.addPassthroughCopy("path/to/fruit-form.js");
最后,确保在您的 HTML 模板中包含脚本元素(确保路径是上面指定的输出的绝对路径):
{# layouts/base.html #}
<script src="/path/to/fruit-form.js" defer></script>
现在它应该可以正常工作了。通常,请确保了解构建时和运行时之间的区别 JavaScript,以便您可以决定在不同情况下哪个最有效。