构建自己的函数
在上一篇文章中处理了大部分必要的理论知识后,本文将提供实践经验。在这里,你将获得一些构建自己的自定义函数的实践。在此过程中,我们还将解释一些处理函数的有用细节。
先决条件 | 对 HTML、CSS 和 JavaScript 初步知识 的基本了解。此外,还需要了解 函数——可重用的代码块。 |
---|---|
目标 | 提供一些构建自定义函数的实践,并解释一些更有用的相关细节。 |
主动学习:让我们构建一个函数
我们将要构建的自定义函数将被称为 displayMessage()
。它将在网页上显示一个自定义的消息框,并将充当浏览器内置的 alert() 函数的自定义替代品。我们之前见过这个函数,但让我们回顾一下。在你喜欢的任何页面上,在浏览器的 JavaScript 控制台中键入以下内容:
alert("This is a message");
alert
函数接受一个参数——在警报框中显示的字符串。尝试更改字符串以更改消息。
alert
函数的功能有限:你可以更改消息,但不能轻松地更改其他任何内容,例如颜色、图标或其他任何内容。我们将构建一个更有趣的函数。
注意:此示例应该在所有现代浏览器中都能正常工作,但在稍旧的浏览器中,样式可能看起来有点奇怪。我们建议你在现代浏览器(如 Firefox、Opera 或 Chrome)中进行此练习。
基本函数
首先,让我们构建一个基本的函数。
注意:对于函数命名约定,应遵循与 变量命名约定 相同的规则。这很好,因为你可以区分它们——函数名后面带有括号,而变量没有。
- 首先访问 function-start.html 文件并制作一个本地副本。你会看到 HTML 非常简单——主体只包含一个按钮。我们还提供了一些基本的 CSS 来设置自定义消息框的样式,以及一个空的
<script>
元素来放置我们的 JavaScript 代码。 - 接下来,在
<script>
元素内添加以下内容:我们从关键字jsfunction displayMessage() { ... }
function
开始,这意味着我们正在定义一个函数。后面跟着我们想要赋予函数的名称、一对括号和一对花括号。我们想要赋予函数的任何参数都放在括号内,当我们调用函数时运行的代码放在花括号内。 - 最后,在花括号内添加以下代码:js
const body = document.body; const panel = document.createElement("div"); panel.setAttribute("class", "msgBox"); body.appendChild(panel); const msg = document.createElement("p"); msg.textContent = "This is a message box"; panel.appendChild(msg); const closeBtn = document.createElement("button"); closeBtn.textContent = "x"; panel.appendChild(closeBtn); closeBtn.addEventListener("click", () => panel.parentNode.removeChild(panel), );
这段代码相当长,所以我们将逐步为你讲解。
第一行使用 DOM API 获取全局 document
对象的 body
属性,并将其赋值给一个名为 body
的常量,以便我们稍后对其进行操作。
const body = document.body;
下一部分使用一个名为 document.createElement()
的 DOM API 函数创建一个 <div>
元素,并将对它的引用存储在一个名为 panel
的常量中。此元素将成为消息框的外层容器。
然后,我们使用另一个名为 Element.setAttribute()
的 DOM API 函数为我们的面板设置一个 class
属性,其值为 msgBox
。这样做是为了更容易地设置元素的样式——如果你查看页面上的 CSS,你会看到我们正在使用 .msgBox
类选择器来设置消息框及其内容的样式。
最后,我们对之前存储的 body
常量调用一个名为 Node.appendChild()
的 DOM 函数,它将一个元素嵌套在另一个元素内作为其子元素。我们将面板 <div>
指定为我们想要附加到 <body>
元素内的子元素。我们需要这样做,因为我们创建的元素不会自己出现在页面上——我们需要指定放置它的位置。
const panel = document.createElement("div");
panel.setAttribute("class", "msgBox");
body.appendChild(panel);
接下来的两部分使用了我们已经见过的相同的 createElement()
和 appendChild()
函数来创建两个新元素——一个 <p>
和一个 <button>
——并将它们作为面板 <div>
的子元素插入页面中。我们使用它们的 Node.textContent
属性(表示元素的文本内容)在段落中插入一条消息,并在按钮中插入一个“x”。当用户想要关闭消息框时,此按钮将是需要点击/激活的按钮。
const msg = document.createElement("p");
msg.textContent = "This is a message box";
panel.appendChild(msg);
const closeBtn = document.createElement("button");
closeBtn.textContent = "x";
panel.appendChild(closeBtn);
最后,我们调用 addEventListener()
来添加一个函数,该函数将在用户点击“关闭”按钮时调用。该代码将从页面中删除整个面板——以关闭消息框。
简单来说,addEventListener()
方法由按钮(实际上,页面上的任何元素)提供,可以传递一个函数和一个事件的名称。在本例中,事件的名称为“click”,这意味着当用户点击按钮时,函数将运行。你将在我们的 事件文章 中了解更多关于事件的信息。函数内的行使用 Node.removeChild()
DOM API 函数指定我们想要删除 HTML 元素的特定子元素——在本例中,是面板 <div>
。
closeBtn.addEventListener("click", () => panel.parentNode.removeChild(panel));
基本上,这段代码生成的 HTML 代码块如下所示,并将其插入页面中:
<div class="msgBox">
<p>This is a message box</p>
<button>x</button>
</div>
有很多代码需要处理——如果现在不记得每个部分是如何工作的,请不要太担心!我们这里要重点关注的是函数的结构和用法,但我们想为此示例展示一些有趣的内容。
调用函数
你现在已将函数定义正确地写入 <script>
元素中,但它本身不会执行任何操作。
- 尝试在你的函数下面包含以下行来调用它:此行调用函数,使其立即运行。当你保存代码并在浏览器中重新加载它时,你会看到一个小消息框立即出现,并且只出现一次。毕竟,我们只调用它一次。js
displayMessage();
- 现在在示例页面上打开浏览器开发者工具,转到 JavaScript 控制台并再次在那里键入该行,你会看到它再次出现!所以这很有趣——我们现在有一个可重用的函数,可以随时调用。但我们可能希望它响应用户和系统操作而出现。在一个真实的应用程序中,这样的消息框可能会在新的数据可用、发生错误、用户尝试删除他们的个人资料(“你确定要这样做吗?”)或用户添加新的联系人并且操作成功完成等情况下被调用。在本演示中,我们将使消息框在用户点击按钮时出现。
- 删除你之前添加的行。
- 接下来,我们将选择按钮并将对它的引用存储在一个常量中。将以下行添加到你的代码中,位于函数定义之上:js
const btn = document.querySelector("button");
- 最后,在上一行下面添加以下行:与我们的 closeBtn 的点击事件处理程序类似,这里我们正在响应按钮被点击而调用一些代码。但在此例中,我们不是调用包含某些代码的匿名函数,而是按名称调用我们的js
btn.addEventListener("click", displayMessage);
displayMessage()
函数。 - 尝试保存并刷新页面——现在你应该会看到当你点击按钮时消息框出现。
你可能想知道为什么我们没有在函数名后面包含括号。这是因为我们不想立即调用函数——只有在按钮被点击后才会调用。如果你尝试将该行更改为:
btn.addEventListener("click", displayMessage());
并保存和重新加载,你会看到消息框在没有点击按钮的情况下出现!在这种情况下,括号有时被称为“函数调用运算符”。只有当你希望在当前作用域中立即运行函数时才使用它们。同样,匿名函数内部的代码不会立即运行,因为它位于函数作用域内。
如果你尝试了最后一个实验,请确保在继续之前撤消最后的更改。
使用参数改进函数
就目前而言,该函数仍然不是很有用——我们不希望每次都显示相同的默认消息。让我们通过添加一些参数来改进我们的函数,以便我们可以使用一些不同的选项来调用它。
- 首先,更新函数的第一行:更改为:js
function displayMessage() {
现在,当我们调用函数时,可以在括号内提供两个变量值来指定要在消息框中显示的消息以及消息的类型。jsfunction displayMessage(msgText, msgType) {
- 为了使用第一个参数,更新函数内的以下行:更改为:js
msg.textContent = "This is a message box";
jsmsg.textContent = msgText;
- 最后,你现在需要更新函数调用以包含一些更新的消息文本。更改以下行:更改为以下代码块:js
btn.addEventListener("click", displayMessage);
如果我们想要为调用的函数在括号内指定参数,那么我们不能直接调用它——我们需要将其放在匿名函数内,以便它不在立即作用域内,因此不会立即被调用。现在它只有在按钮被点击后才会被调用。jsbtn.addEventListener("click", () => displayMessage("Woo, this is a different message!"), );
- 重新加载并再次尝试代码,你会看到它仍然可以正常工作,只是现在你还可以更改参数内的消息以在框中显示不同的消息!
更复杂的参数
接下来是下一个参数。这将涉及更多工作——我们将设置它,以便根据 msgType
参数设置为的值,函数将显示不同的图标和不同的背景颜色。
- 首先,从 GitHub 下载此练习所需的图标(警告 和 聊天)。将它们保存到一个名为
icons
的新文件夹中,该文件夹与你的 HTML 文件位于同一位置。注意:警告和聊天图标最初是在 iconfinder.com 上找到的,由 Nazarrudin Ansyari 设计——谢谢!(实际的图标页面已被移动或删除。)
- 接下来,找到 HTML 文件中的 CSS。我们将进行一些更改以腾出空间放置图标。首先,将
.msgBox
的宽度从:更改为:csswidth: 200px;
csswidth: 242px;
- 接下来,在
.msgBox p { }
规则内添加以下行:csspadding-left: 82px; background-position: 25px center; background-repeat: no-repeat;
- 现在我们需要在
displayMessage()
函数中添加代码来处理图标的显示。在函数的结束花括号 (}
) 正上方添加以下代码块:这里,如果将jsif (msgType === "warning") { msg.style.backgroundImage = "url(icons/warning.png)"; panel.style.backgroundColor = "red"; } else if (msgType === "chat") { msg.style.backgroundImage = "url(icons/chat.png)"; panel.style.backgroundColor = "aqua"; } else { msg.style.paddingLeft = "20px"; }
msgType
参数设置为'warning'
,则会显示警告图标,并将面板的背景颜色设置为红色。如果将其设置为'chat'
,则会显示聊天图标,并将面板的背景颜色设置为青绿色。如果根本没有设置msgType
参数(或设置为其他值),则代码的else { }
部分开始执行,段落将使用默认填充且没有图标,并且也没有设置背景面板颜色。如果没有提供msgType
参数,这将提供一个默认状态,这意味着它是一个可选参数! - 让我们测试一下更新后的函数,尝试将
displayMessage()
调用从以下内容更新为以下内容之一jsdisplayMessage("Woo, this is a different message!");
您可以看到我们(现在不再那么)小的函数变得多么有用。jsdisplayMessage("Your inbox is almost full — delete some mails", "warning"); displayMessage("Brian: Hi there, how are you today?", "chat");
注意:如果您在尝试使示例工作时遇到问题,请随时将您的代码与GitHub 上的完成版本 (查看其运行效果) 进行比较,或向我们寻求帮助。
测试你的技能!
您已阅读完本文,但您能记住最重要的信息吗?在继续之前,您可以找到一些进一步的测试来验证您是否保留了这些信息——请参阅测试您的技能:函数。这些测试需要下一篇文章中介绍的技能,因此您可能需要先阅读下一篇文章,然后再尝试测试。