共计 6537 个字符,预计需要花费 17 分钟才能阅读完成。
ES6 技术本身非常容易,相信大家也体会到了。各种新特性都不难,但是为什么很多人学习起来困难呢?
其实 ES6 难的不是技术,而是实际工作环境的搭建。比如我们想写一个简单的 ES6 版本的 TodoList.
很多同学学生是这么放弃的:
通过搜索引擎,发现很多教程都是直接引入 Traceur.js 然后讲解 ES6 各种功能和语法的,但是好像实际并不是直接引入 Traceur.js,而是用 babel。
使用 babel 的话好像需要安装 node.js, 还有会用 npm
安装好 npm 以后我是该使用 gulp 还是 webpack 呢?
嗯,应该 webpack 吧,这个好像目前更主流。好,就选它了。
webpack 怎么安装?是不是需要 webpack-cli? 另外 webpack 4.0 好像更好用,但是好像安装又有兼容性问题?
纠结 ing……
考虑了半天后,终于下定决心,就用最新版本,学老的没用。
安装好 webpack 4.0, 对了是不是要配置工作流?
对配置吧,这才是“工作的方式”,js 需要压缩,装个压缩插件,webpack 怎么用啊?有各种 rule,plugins, 还有 entry.
开始头疼,耐着性子把网上的教程配置完,这个插件怎么报错了啊?
继续查,原来是 webpack 4.0 和它不兼容,换 webpack 3.0 还是换插件?
纠结半天后,终于鼓起勇气,换插件!
又配置出错了……
开始进入暴走模式,又气又恼。
好吧,折腾半天,请教大牛总算通过了。
那么问题来了,学了这么久 css 和 js,我居然不知道往哪里写 css……
好吧,听说得用 sass……
配置完了,sass 语法不会……
我就想写一个 ES6 的 todoList,太费劲了,咋得学这么东西啊……
还是放弃吧,我感觉我不适合做前端。
虽然夸张了些,但是大部分前端都有类似的经历。
今天我就让大家彻底的学会如何工作中写 ES6,我们依然用 todoList 举例,对了我们并不需要学习 webpack,sass,插件等等。我们只学习 ES6,对其它的统统不用学,你会用就可以,也不过几个命令而已。
ok, 我们开始。
首先,拿到我配置好的工作流,直接在根目录下进入命令行,然后
npm install
安装完成后,使用
npm run dev
然后就可以用了,
就这几个文件,对应写 html,js 和 css。
首先我们先写 html 文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,
maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
<title>TODOList</title>
</head>
<body>
<div class="container">
<div class="item-area">
<h1 class="title">TODO-LIST</h1>
<ul class="item">
<li class="item-li-default"> 输入任务...</li>
</ul>
</div>
<div class="input-area">
<form class="add-item">
<input maxlength="15" type="text" name="item" placeholder="待办事件..." class="add-text" required>
<input type="submit" value="+ 添加" class="add-button">
</form>
</div>
</div>
</body>
</html>
接着,写 css 美化一下
* {
padding: 0;
margin: 0;
}
li {list-style: none;}
html {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
box-sizing: border-box;
font-family: Futura, "Trebuchet MS", Arial, sans-serif;
background: #ffc600;
}
svg {
fill: #fff;
background: rgba(0,0,0,0.1);
padding: 20px;
border-radius: 50%;
width: 100px;
margin-bottom: 50px;
}
.container {
padding: 20px;
max-width: 350px;
box-shadow: 0 0 0 10px rgba(0,0,0,0.1);
background: #fff;
}
.container .item-area .title {
text-align: center;
margin: 10px 0;
color: #aaa;
font-weight: 200;
}
.container .item-area .item {
background: #fff;
border-radius: 4px;
}
.container .item-area .item .item-li-default {color: #46b7b9;}
.container .item-area .item .item-li {
width: 100%;
border-bottom: 1px solid #eee;
height: 30px;
line-height: 30px;
text-align: left;
color: #f95959;
}
.container .item-area .item .item-li .delete-item {
float: right;
outline: none;
width: 44px;
height: 26px;
border-radius: 4px;
color: #f05941;
background: #fafafa;
}
.container .item-area .item .item-li input:checked + .item-text {
color: #196b69;
text-decoration: line-through;
}
.container .input-area {padding-top: 10px;}
.container .input-area .add-text {
outline: 0;
border: 1px solid rgba(0,0,0,0.1);
height: 40px;
border-radius: 4px;
text-indent: 10px;
}
.container .input-area .add-button {
outline: 0;
height: 40px;
border-radius: 4px;
width: 60px;
padding: 4px;
background-color: #fff;
border: 1px solid rgba(0,0,0,0.1);
}
ok,使用
npm satrt
架子搭完了,很简单,甚至是不需要你写这些东西,但是你必须要会写,不过写这个的意义并不大,因为我们的重点是学 ES6, 好我们直捣黄龙。
import style from "./main.css";
把 css 引入 js 文件,你就把它当成 link 就行。
开始核心部分,
const add = document.querySelector('.add-item');// 找到添加事件的变表单,之所以需要监听 form 而不是 input 是因为这样用户回车时也会触发事件
add.addEventListener('submit', addItem);
点击按钮,添加一个代办事件,看看 addItem 怎么写。
// 定义一个用来存放任务的数组
var items = JSON.parse(localStorage.getItem('items')) || [];
function addItem(e){e.preventDefault(); // 阻止表单提交的默认行为
const text = (this.querySelector('[name=item]')).value;
const item ={
text,
done: false
};
items.push(item);
// 调用 populateList,将 items 数组中的事件添加到 html 页面中
populateList(items, container);
localStorage.setItem('items', JSON.stringify(items));
this.reset();}
把任务扔到数组里,然后让数组去生成列表,最后重置表单。我们看看待办事件列表怎么生成的
// 将 items 数组中的事件添加到 html 页面中
const container = document.querySelector('.item');// 找到将事项加入的元素
function populateList(plate, plateList) {plateList.innerHTML=plate.map( (item, i) => {
return`
<li class="item-li">
<input type="checkbox" data-index=${i} id="item${i}" ${item.done ? 'checked' : ''}>
<lable class="item-text" for="item${i}">${item.text}</lable>
<input type="button" value="删除" class="delete-item" >
</li>
`
}).join('');
}
populateList(items, container);
ok,非常简单。我看看看如何删除一个任务。
// 删除事件
function deleteDone(e) {
const msg ='确定删除该项事件?'
if(!e.target.matches("input[type='button']")) return; // 只有复选框才可以执行事件
const el = e.target;
const index = el.dataset.index;
if(confirm(msg)){items.splice(index,1); // 将选中数组删除
localStorage.setItem('items', JSON.stringify(items));
populateList(items, container);
}else{return;}
}
container.addEventListener('click', deleteDone);
其实最关键的就一句话,
items.splice(index,1); // 将选中数组删除
玩的就是数组,这个例子虽然简单用的却是 MVC 的思想。
接下来我们再看看切换任务状态,
// 切换 checked 状态
function toggleDone(e) {if(!e.target.matches("input[type='checkbox']")) return; // 只有复选框才可以执行事件
const el = e.target;
const index = el.dataset.index;
items[index].done =!items[index].done;
localStorage.setItem('items', JSON.stringify(items));
populateList(items, container);
}
container.addEventListener('click', toggleDone);
我们结合着本地存储的数据结构看,这样就更好理解。
切换状态其实就是对应的数组值取反。
好了,到现在为止,我们看看整体代码:
完整代码如下:
import style from "./main.css";
const add = document.querySelector('.add-item');// 找到添加事件的变表单,之所以需要监听 form 而不是 input 是因为这样用户回车时也会触发事件
const container = document.querySelector('.item');// 找到将事项加入的元素
var items = JSON.parse(localStorage.getItem('items')) || [];
// 将添加的待办事件 push 进 items 数组中
function addItem(e){e.preventDefault(); // 阻止表单提交的默认行为
const text = (this.querySelector('[name=item]')).value;
const item ={
text,
done: false
};
items.push(item);
populateList(items, container);
localStorage.setItem('items', JSON.stringify(items));
this.reset();}
// 将 items 数组中的事件添加到 html 页面中
function populateList(plate, plateList) {plateList.innerHTML=plate.map( (item, i) => {
return`
<li class="item-li">
<input type="checkbox" data-index=${i} id="item${i}" ${item.done ? 'checked' : ''}>
<lable class="item-text" for="item${i}">${item.text}</lable>
<input type="button" value="删除" class="delete-item" >
</li>
`
}).join('');
}
// 切换 checked 状态
function toggleDone(e) {if(!e.target.matches("input[type='checkbox']")) return; // 只有复选框才可以执行事件
const el = e.target;
const index = el.dataset.index;
items[index].done =!items[index].done;
localStorage.setItem('items', JSON.stringify(items));
populateList(items, container);
}
// 删除事件
function deleteDone(e) {
const msg ='确定删除该项事件?'
if(!e.target.matches("input[type='button']")) return; // 只有复选框才可以执行事件
const el = e.target;
const index = el.dataset.index;
if(confirm(msg)){items.splice(index,1); // 将选中数组删除
localStorage.setItem('items', JSON.stringify(items));
populateList(items, container);
}else{return;}
}
add.addEventListener('submit', addItem);
container.addEventListener('click', toggleDone);
container.addEventListener('click', deleteDone);
populateList(items, container);
写完了上线
npm run build
好,我们总结一下:
1. 不要陷入到开发环境里,我们是学习 ES6,而不是 webpack,所以直接用我写的 webpack 工作流就好。
2. 要会写这个项目的 html 和 css,注意实际项目中 css 的引入方式。
3. 学习 mvc 的思想,尝试使用通过修改数组的方式实现任务的增加、删除和修改功能。
4. 掌握本地存储的用法。
好,本文就到这里,下节课我们再做一个更贴近工作的例子。