Vanilla.js - 入门
欢迎使用 Vanilla.js,一个由 JavaScript 驱动的零资源占用框架!Vanilla.js 可帮助您构建适用于 Web、移动和桌面的现代应用程序。
本指南将向您介绍如何构建和运行一个简单的 Vanilla.js 应用。您将使用文本编辑器来开发应用,并使用每个Vanilla.js 项目都适用的 JavaScript 语言功能。
本指南只需不到 10 分钟即可完成。本指南末尾(作为最终代码审查的一部分)提供了一个链接,可查看最终应用程序代码。(即使您不执行本指南中的步骤,仍然可以访问最终应用程序代码。)
先决条件
在开始之前,请确保您的开发环境包含一个文本编辑器(您的选择)和一个 Web 浏览器(同样,您的选择)。
JavaScript 引擎
Vanilla.js 需要支持 JavaScript 的浏览器。哦,等等,所有现代浏览器都支持!(你应该已经准备好了)。
包管理器和构建工具
Vanilla.js 不依赖任何包并且不需要任何构建工具。
本快速入门使用您选择的简单文本编辑器,该编辑器应该已安装在您的系统中。如果没有,如果您有浏览器要求,也可以使用jsFiddle。它的易用性可能会让您有点不知所措。
要检查您是否安装了 Vanilla.js 客户端,请打开浏览器,启动开发人员工具(通常可通过访问F12
),键入console.info("OK")
,ENTER
然后验证是否看到OK
回显。
步骤 1:创建 HTML 文件并开始编辑
您将使用您最喜欢的文本编辑器来创建网页并执行各种正在进行的开发任务,例如测试、捆绑和部署。
以下是一些可帮助您入门的 HTML 示例:
<html> | |
<head> | |
<title>My Vanilla.js App</title> | |
</head> | |
<body> | |
<div id="app"> | |
</div> | |
</body> | |
</html> |
<html> | |
<head> | |
<title>My Vanilla.js App</title> | |
</head> | |
<body> | |
<div id="app"> | |
</div> | |
</body> | |
</html> |
这是一些 CSS。我们需要它来让应用程序看起来更美观。CSS 的具体功能以及它是如何构建的,是现代 Web 开发中最大的谜团之一。
body { | |
font-family: sans-serif, arial, helvetica; | |
} | |
button { | |
cursor: pointer; | |
margin-top: 1em; | |
padding: 1em; | |
border-radius: 50%; | |
} | |
div.post { | |
border-top: solid black 2px; | |
} | |
h1 { | |
width: 95%; | |
font-size: 1.5em; | |
background: lightgray; | |
padding: 0.2em; | |
text-align: justify; | |
} | |
p { | |
margin-left: 2em; | |
} | |
.tooltip { | |
position: relative; | |
display: inline-block; | |
border-bottom: 1px dotted black; | |
} | |
.tooltip .tooltiptext { | |
visibility: hidden; | |
background-color: gray; | |
color: #fff; | |
text-align: center; | |
padding: 5px; | |
margin-left: -5px; | |
border-radius: 6px; | |
position: absolute; | |
z-index: 1; | |
} | |
.tooltiptext:hover { | |
visibility: visible; | |
} | |
.tooltip:hover .tooltiptext { | |
visibility: visible; | |
} |
body { | |
font-family: sans-serif, arial, helvetica; | |
} | |
button { | |
cursor: pointer; | |
margin-top: 1em; | |
padding: 1em; | |
border-radius: 50%; | |
} | |
div.post { | |
border-top: solid black 2px; | |
} | |
h1 { | |
width: 95%; | |
font-size: 1.5em; | |
background: lightgray; | |
padding: 0.2em; | |
text-align: justify; | |
} | |
p { | |
margin-left: 2em; | |
} | |
.tooltip { | |
position: relative; | |
display: inline-block; | |
border-bottom: 1px dotted black; | |
} | |
.tooltip .tooltiptext { | |
visibility: hidden; | |
background-color: gray; | |
color: #fff; | |
text-align: center; | |
padding: 5px; | |
margin-left: -5px; | |
border-radius: 6px; | |
position: absolute; | |
z-index: 1; | |
} | |
.tooltiptext:hover { | |
visibility: visible; | |
} | |
.tooltip:hover .tooltiptext { | |
visibility: visible; | |
} |
您可以将 CSS 包含在<style></style>
开始和结束标记内,或将其保存在名为的文件中,并在HTML 文档的部分style.css
中包含以下特殊代码行:head
<link rel="stylesheet" type="text/css" href="style.css">
第 2 步:创建初始应用程序
您可以在文本编辑器的上下文中开发应用程序。您的文件系统包含一个或多个页面的文件。
要创建初始应用程序,请创建一个名为的文件app.js
并在页面正文中引用它,如下所示:
<script src="./app.js"></script>
或者将代码粘贴到<script></script>
代码块中。以下是初始应用程序代码:
const app = document.getElementById("app"); | |
window.run = () => app.innerText="Fun!"; | |
app.innerHTML = '<button onclick="run()">Load</button>'; |
const app = document.getElementById("app"); | |
window.run = () => app.innerText="Fun!"; | |
app.innerHTML = '<button onclick="run()">Load</button>'; |
是的,目前这是一个非常简单的应用程序。
步骤 3:提供应用程序
在大多数系统上,您只需双击或点击index.html
文件,它就会在浏览器中打开并运行。如果您需要 Web 服务器,那就需要开始做一些疯狂的事情,比如安装第三方工具。当然,这是可能的。
假设您的系统上已经配置了node.js(以及它的伙伴npm
),您可以安装一个像这样的简单 Web 服务器:
npm install http-server -g
之后,通过输入以下内容从存储文件的目录中运行它:
http-server .
然后您可以导航到http://localhost:8080/index.html上的文件。
您的应用程序将通过一个按钮向您致意,单击该按钮时该按钮会发生变化:
步骤 4:创建一个功能齐全的 RSS 样式阅读器,其中包含动态可折叠帖子和悬停时显示的地理编码用户信息
其实,实际工作量并没有听起来那么大。对于数据,我们将实时调用“ JSON Placeholder ”提供的示例信息。数据集有很多,但我们只查看“帖子”和“用户”。
我们应该使用什么库或框架来获取数据?
你知道 JavaScript 有一个方便的内置fetch API吗?以下是通用代码,它将从我们的端点获取数据并将其存储在名为 的对象中model
。例如,“用户”最终将作为一个数组,您可以通过 引用model.users
。注意,它需要一个在加载完成时执行的回调。
const get = (model, domain, done) => { | |
fetch(`https://jsonplaceholder.typicode.com/${domain}`) | |
.then(response => response.json()) | |
.then(json => { | |
model[domain] = json; | |
done(); | |
}); | |
}; |
const get = (model, domain, done) => { | |
fetch(`https://jsonplaceholder.typicode.com/${domain}`) | |
.then(response => response.json()) | |
.then(json => { | |
model[domain] = json; | |
done(); | |
}); | |
}; |
接下来,我们可以重写主应用程序代码来利用这一点。覆盖原有的代码,粘贴get
上面列出的方法,并添加以下内容:
const app = document.getElementById("app"); | |
const run = (model) => get(model, "users", () => | |
get(model, "posts", | |
() => { | |
model.users.forEach(user => model.userIdx[user.id] = user); | |
app.innerText = ''; | |
model.posts.forEach(post => | |
app.appendChild(renderPost(post, model.userIdx[post.userId]))); | |
})); | |
app.appendChild(Wrapper.generate("button", "Load").click(() => run({ | |
userIdx: {} | |
})).element); |
const app = document.getElementById("app"); | |
const run = (model) => get(model, "users", () => | |
get(model, "posts", | |
() => { | |
model.users.forEach(user => model.userIdx[user.id] = user); | |
app.innerText = ''; | |
model.posts.forEach(post => | |
app.appendChild(renderPost(post, model.userIdx[post.userId]))); | |
})); | |
app.appendChild(Wrapper.generate("button", "Load").click(() => run({ | |
userIdx: {} | |
})).element); |
这段代码会抓取帖子,然后是用户,最后通过 id 映射用户,userIdx
以便于引用。先别急着运行代码!还缺少一些东西。有一个Wrapper
类最终会帮助我们动态生成 HTML 元素,还有一个renderPost
函数,嗯,就是渲染每个帖子。看起来我们已经准备好构建这些了。让我们来创建Wrapper
。
class Wrapper { | |
constructor(element, text, display = true) { | |
this.element = document.createElement(element); | |
this.element.innerHTML = text; | |
this.display = !display; | |
this.toggleDisplay(); | |
} | |
click(val) { | |
this.element.addEventListener("click", () => val()); | |
return this; | |
} | |
showSelectable() { | |
this.element.style.cursor = "pointer"; | |
return this; | |
} | |
addClass(className) { | |
this.element.classList.add(className); | |
return this; | |
} | |
toggleDisplay() { | |
this.display = !this.display; | |
this.element.style.display = this.display ? "" : "none"; | |
return this; | |
} | |
appendChild(child) { | |
this.element.appendChild(child.element); | |
return this; | |
} | |
createChild(element, text, display = true) { | |
var wrapper = new Wrapper(element, text, display); | |
this.appendChild(wrapper); | |
return this; | |
} | |
static generate(element, text, display = true) { | |
return new Wrapper(element, text, display); | |
} | |
} |
class Wrapper { | |
constructor(element, text, display = true) { | |
this.element = document.createElement(element); | |
this.element.innerHTML = text; | |
this.display = !display; | |
this.toggleDisplay(); | |
} | |
click(val) { | |
this.element.addEventListener("click", () => val()); | |
return this; | |
} | |
showSelectable() { | |
this.element.style.cursor = "pointer"; | |
return this; | |
} | |
addClass(className) { | |
this.element.classList.add(className); | |
return this; | |
} | |
toggleDisplay() { | |
this.display = !this.display; | |
this.element.style.display = this.display ? "" : "none"; | |
return this; | |
} | |
appendChild(child) { | |
this.element.appendChild(child.element); | |
return this; | |
} | |
createChild(element, text, display = true) { | |
var wrapper = new Wrapper(element, text, display); | |
this.appendChild(wrapper); | |
return this; | |
} | |
static generate(element, text, display = true) { | |
return new Wrapper(element, text, display); | |
} | |
} |
这只是一小段代码,但非常直观。哦,对了,类的优点在于它们可以重用,所以我们只需要写一次。以下是方法的快速概览:
- 构造函数——生成一个元素并用文本填充。同时,它还可以根据条件将其设置为可见或不可见,并连接一个开关,以便轻松隐藏/显示该元素。
- 单击——包装器,添加“单击”监听器并调用方法。
- 显示可选——只需设置样式,使光标变成手形,表示可以执行操作。
- 添加类——这是指出大多数方法名称都是自文档的适当位置吗?
- 切换显示 —咳咳。
- 附加子元素 — 将元素嵌套在父元素内。
- 创建子项 —创建和附加子项的快捷方法。
- 生成——生成一个新实例,这样您就不必
new
一直调用。
几点说明。首先,我没有诱导你使用TypeScript。所有这些都是有效的、现代的 JavaScript。其次,所有方法都是有原因的
return this
。不,不是你正在读到的this,而是 theWrapper
本身。这是因为它使得链式函数调用成为可能,从而实现更流畅的 API。我们稍后会看到更多。
现代 JavaScript 不仅支持类,还支持经典继承(咳咳,我实在忍不住)。我们可以利用这一点,更轻松地生成锚标签。
class AnchorWrapper extends Wrapper { | |
constructor(href, text, target = "_blank") { | |
super("a", text); | |
this.element.href = href; | |
this.element.target = target; | |
} | |
static generate(href, text, target = "_blank") { | |
return new AnchorWrapper(href, text, target); | |
} | |
} |
class AnchorWrapper extends Wrapper { | |
constructor(href, text, target = "_blank") { | |
super("a", text); | |
this.element.href = href; | |
this.element.target = target; | |
} | |
static generate(href, text, target = "_blank") { | |
return new AnchorWrapper(href, text, target); | |
} | |
} |
现在我们可以把它们整合在一起了。我们已经获取了帖子和用户;我们只需要使用方便的辅助类来渲染它。事不宜迟……
const renderPost = (post, user) => { | |
const bodyDiv = Wrapper.generate("div", "", false) | |
.createChild("p", post.body) | |
.appendChild(Wrapper.generate("p", user.username).addClass("tooltip") | |
.appendChild(Wrapper.generate("span", `${user.name} `) | |
.appendChild(AnchorWrapper.generate(`mailto:${user.email}`, user.email)) | |
.createChild("br", "") | |
.appendChild(AnchorWrapper.generate( | |
`https://maps.google.com?q=${user.address.geo.lat}, ${user.address.geo.lng}`, | |
"🌎 Locate")) | |
.addClass("tooltiptext"))); | |
return Wrapper.generate("div", "") | |
.addClass("post") | |
.appendChild(Wrapper.generate("h1", `${user.username} — ${post.title}`) | |
.showSelectable() | |
.click(() => bodyDiv.toggleDisplay())) | |
.appendChild(bodyDiv) | |
.element; | |
}; |
const renderPost = (post, user) => { | |
const bodyDiv = Wrapper.generate("div", "", false) | |
.createChild("p", post.body) | |
.appendChild(Wrapper.generate("p", user.username).addClass("tooltip") | |
.appendChild(Wrapper.generate("span", `${user.name} `) | |
.appendChild(AnchorWrapper.generate(`mailto:${user.email}`, user.email)) | |
.createChild("br", "") | |
.appendChild(AnchorWrapper.generate( | |
`https://maps.google.com?q=${user.address.geo.lat}, ${user.address.geo.lng}`, | |
"🌎 Locate")) | |
.addClass("tooltiptext"))); | |
return Wrapper.generate("div", "") | |
.addClass("post") | |
.appendChild(Wrapper.generate("h1", `${user.username} — ${post.title}`) | |
.showSelectable() | |
.click(() => bodyDiv.toggleDisplay())) | |
.appendChild(bodyDiv) | |
.element; | |
}; |
代码流畅地生成了模板,并将动态交互所需的一切功能都连接好了。让我们来看看最终完成的应用。
(单击位置链接将带您进入在线地图……您可能会发现样本数据中的目的地非常有趣)。
最终代码审查
您可以在本入门指南中浏览您创建的应用程序的工作示例。
提示:jsFiddle 是尝试 Vanilla.js 的好地方。
“但是,等等!如果我的目标浏览器不支持最新的 JavaScript(ECMAScript 6)怎么办?”
如果是我的话,我只会将该.js
文件重命名为.ts
扩展名并将其编译为 ES5。
后续步骤Next steps
现在您已经了解了 Vanilla.js 应用程序和您最喜欢的文本编辑器的基本知识,请继续阅读以下其他深入思考:
- 你真的需要一个 JavaScript 框架吗?
- 如果您是一位长期从事 JavaScript 开发的开发人员,您是否了解最新语言实现的强大功能?
- 是不是
fetch
比 容易得多(尽管不那么有趣)XmlHttpRequest
?
阅读完本文后,您将准备好通过互联网上的其他指南和参考资料自行继续探索 Vanilla.js,重点关注对您的应用程序最重要的功能。
“但是等等——如果我必须支持旧版浏览器怎么办?”
我们很快就会解决这个问题!
问候,
鏂囩珷鏉ユ簮锛�https://dev.to/jeremylikness/vanilla-js-getting-started-1e3j