使用原生 Javascript ES6 的 TicTacToe
介绍
我们将学习如何创建 ES6 纯 JavaScript 井字游戏。为此,我们将创建组件、库和模块。
在我们开始之前:
- 确保你对 DOM 1~2 级有一定程度的理解
- 确保具备 Javascript ECMAScript 5 (ES5) 的使用经验
- 我假设你对 ECMAScript 6 有一点了解
设置环境
由于本文的目的是构建一个纯 JS 实现的井字游戏,并包含必要的最少 HTML,因此我们需要Browserify、Babelify、NodeJs以及您选择的可以访问终端/shell 的 IDE。
直接从官方网站下载安装NodeJS 。
如果您没有终端,您可以下载git-scm,在那里您可以下载并设置 Git Bash 终端。
创建工作区
首先,我们需要一个项目文件夹。由于我们要让 Browserify 打包我们的代码,因此我们最好在项目文件夹中创建src和dist文件夹:
$> mkdir tic-tac-toe
$> cd tic-tac-toe
$> mkdir src
$> cd src
$> mkdir lib modules components
$> cd ..
$> mkdir dist
现在我们准备开始打包,发出npm init并回答问题。由于我们以后会使用 git,所以我们继续在项目(tic-tac-toe)的根目录中创建一个.gitignore文件,并将node_modules/作为第一行(这样我们在将项目发送到 git 时就可以忽略依赖项)。
命名和导出
每个文件都应该有一个很好的描述,说明它的作用。如果你的文件名可以被理解为执行各种功能,那么你可能应该将该功能重构为两个单独的文件。这样我们就可以继续简单地发展我们的游戏。
文件中唯一能够导出的是类、函数和对象(例如,如果我们需要使用某些选项模型。尽管这些在本文中不存在。)
导出命名应该与文件名称相同;
文件名称 | 出口名称 |
---|---|
the-thing.js | 怪形 |
word.js | 单词 |
创建新功能
组织层次结构
了解您想要创建哪些功能以及它属于哪里。
pex:如果您想改变元素textContent的值,则该功能应该在组件级别;
而如果您想要计算选择器中有多少个元素,则应该将其创建为模块,然后在需要该功能时将其导入。
代码风格
这次,我放弃了使用JavaScript Linter的习惯。不过,我坚持了一些做法:
- 使用严格
- 提早返回
- 注意分号
- 空格不是制表符
结合 DRY 方式,这些对于代码的阅读和理解来说已经足够了。我也喜欢尽可能描述性地编写代码。这样方法就可以保持小而整洁,阅读代码就变得轻而易举了。
安装并设置依赖项
现在我们已经整理好了工作区,并且忽略了 node_modules,我们可以设置依赖项了。我们提到了两个“ify”事物的名称,Browserify 和 Babelify:这些是节点模块,它们将帮助我们将 ES6 代码转换为浏览器可读的 ES5。
为什么?因为有些浏览器还不支持 ES6 模块化,而这是我们程序设计中一个复杂部分。另一种方法是将整个游戏写入单个文件 - 任何头脑正常的人都不会愿意多次查看前 20 行左右的内容。为了避免这种情况,我们使用 Browserify。
Browserify 理解 ES6 模块,负责将所有内容捆绑成一个整洁的文件,然后将其交给 Babelify,后者使用最新的预设翻译我们的 ES6 代码(因此我们可以使用所有好东西,尽管我们不会在第一篇文章中滥用它们)。
$> npm install --save-dev browserify babelify babel-preset-latest
然后,编辑你的package.json以包含对 browserify 模块的以下引用
{
"browserify": {
"transform": ["babelify"]
}
}
这样,每次测试应用程序时,我们就不必费力打字了,只需将以下脚本添加到package.json 的scripts属性中即可。
{
"scripts": {
"prebundle": "cp src/index.html dist/index.html",
"bundle":
"browserify src/game-start.js -t babelify --outfile dist/bundle.js"
}
}
现在,为了让 Babelify 知道要使用哪个预设,请创建一个名为.babelrc的新文件:
{ "presets": ["latest"] }
健全性检查!
让我们来看看我们的代码到底做了什么。bundle脚本创建了src/game-start.js所需的每个文件的捆绑文件。prebundle脚本将src/index.html文件复制到dist/index.html
有人会说Gulp 或 Grunt这样的工具在这里会很完美,但这些工具可能有点大材小用。npm 脚本足以自动完成我们在这种情况下需要做的事情。但是,对于较大的项目,我建议自由发挥,找出最有效的方法。
项目设计
模块、库和组件
模块、库、组件都不过是类而已,它们具有不同的功能,可以相互区分。
模块
模块将库和组件粘合在一起。它们是 JavaScript 开发的基础,并且用于一切事物。
图书馆
库是单一动作类。例如,我们的 GameEngine 是一个库,因为它只负责保存回合信息和占领区域。
成分
虽然不如 WebComponents 先进,但我们的组件是页面中 HTML 元素的类表示。这是通过在构造函数上为类分配元素属性来实现的,该构造函数本身是document.createElement(),以便随后可以通过模块附加它。
ES6 类
MDN对类有很多内容,但你可以将它们视为旧的揭示模块模式:
var TheThing = function() {
function privateFn() {
/** ... */
}
return { name: "The Thing" };
};
但是,我们使用的是Class语句,而不是function标签。它具有类的所有优点:extends、get、set等等(但还有static和 sorts)。
作为一个类,“TheThing”将被写成:
class TheThing {
constructor() {
this.name = "TheThing";
function privateFn() {
/** ... */
}
}
}
在这种情况下,您将无法从构造函数外部调用privateFn 。人们已经提交了私有方法的提案,但这些提案尚未实施。(我们可以使用最新的预设糖衣稻草人::但很多时候感觉不对。因此,我们要么用_预先命名私有函数,要么干脆不写私有函数。)
编码井字游戏
游戏基础知识:我们对井字游戏了解多少?
- 我们知道游戏场地通常是 3x3 的网格,但</font
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~