Create by jsliang on 2019-1-2 08:46:46
Recently revised in 2019-1-10 08:19:41css
Hello 小伙伴们,若是以为本文还不错,记得给个 star , 大家的 star 是我学习折腾的动力!GitHub 地址html
【2019-08-16】Hello 小伙伴们,因为 jsliang 对文档库进行了重构,这篇文章的一些连接可能失效,而 jsliang 没有精力维护掘金这边的旧文章,对此深感抱歉。请须要获取最新文章的小伙伴,点击上面的 GitHub 地址,去文档库查看调整后的文章。前端
关注 Vue 的小伙伴们可能知道前几天尤神在微博发表了个动态:vue
而后,进行了更详细了解的小伙伴,可能知道这个绝密代码中写的,就是 TodoList!git
恰好,本文抛开 Vue-Cli,使用最简单原始的方式开发一个 TodoList,可是,此 TodoList 非彼 Todolist。github
本文的 TodoList 完成正在进行、完成列表、回收站这三个功能模块,并实现下面这些功能:web
代码地址:功成千骨 - 代码地址后端
项目地址:功成千骨 - 线上地址数组
那么,想知道这个 TodoList 怎么实现的小伙伴,一块儿来看下吧!浏览器
不折腾的前端,和咸鱼有什么区别
目录 |
---|
一 目录 |
二 前言 |
三 项目解析 |
四 骨架 - HTML |
五 功能 - JS |
5.1 页面数据化 |
5.2 数据简化 |
5.3 添加数据 |
5.4 改变状态 |
5.5 修改内容 |
5.6 数据回收 |
5.7 完全删除 |
六 皮肤 - CSS |
6.1 重置样式 |
6.2 偷天换日 |
七 总结 |
通过系列的折腾,而且参照不一样大佬的“新人做”,将五花八门的 TodoList 各类写法综合起来,从 0 到 1 不依赖 Vue-Cli 打造一个属于本身的 TodoList,后期将加以 Node 的框架 Koa 链接 MySQL 提供接口,从而实现面向大众的 TodoList!
欲练此功,必先自宫,额(⊙o⊙)…不对,必先学习 Vue 系列之 Vue 基础。
在咱们平时的工做中,咱们应该在拿到 PSD 设计稿或者原型设计的时候,咱们应该对咱们的功能进行划分,对 HTML、CSS、JS 进行划分,以便于后期的维护制做,下面咱们先看一下咱们的 UI:
额(⊙o⊙)…
好吧-_-||
惨不忍睹,咱们仍是按照这形式,将 HTML 搭建出来,并用 JS 实现功能先吧,后期再填充 CSS 了。
下面是目录结构:
如今,咱们先完成 index.html
架构。
而后 index.css
和 index.js
这两个文件,能够是空的,由于咱们先架好骨架,再进行 JS 的事件以及 CSS 的渲染。
index.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,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="shortcut icon" href="./img/favicon.ico" type="image/x-icon">
<title>功成千骨</title>
<!-- css 区 -->
<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/index.css">
<style>
.content-list {
display: flex;
}
</style>
</head>
<body>
<!-- html 区 -->
<div class="main-container" id="app">
<!-- 头部标题 -->
<div class="header">
<h3>功成千骨</h3>
</div>
<!-- 内容区 -->
<div class="content">
<!-- 输入区 -->
<div class="content-input-todo">
<input type="text" placeholder="第 n 个敌人" "v-model="todo"> <button>进击</button> </div> <!-- 列表区 --> <div class="content-list"> <!-- 未完成 --> <div class="content-list-todo"> <h4>千军万马取敌首</h4> <p>(待完成)</p> <ul> <li> <input type="checkbox"> <span class="todo-title">敌军 1</span> <span class="icon-recycle">×</span> </li> <li> <input type="checkbox"> <span class="todo-title">敌军 2</span> <span class="icon-recycle">>×</span> </li> <li> <input type="checkbox"> <span class="todo-title">敌军 3</span> <span class="icon-recycle">×</span> </li> </ul> </div> <!-- 已完成 --> <div class="content-list-finish"> <h4>敌羞吾去脱他衣</h4> <p>(已完成)</p> <ul> <li> <input type="checkbox"> <span class="todo-title">亡军 1</span> <span class="icon-recycle">×</span> </li> <li> <input type="checkbox"> <span class="todo-title">亡军 2</span> <span class="icon-recycle">×</span> </li> <li> <input type="checkbox"> <span class="todo-title">亡军 3</span> <span class="icon-recycle">×</span> </li> </ul> </div> <!-- 回收站 --> <div class="content-list-recycle"> <h4>溃不成军鸟兽散</h4> <p>(回收站)</p> <ul> <li> <span class="content-list-recycle-back">返回</span> <span class="todo-title">逃军 1</span> <span class="icon-delete">×</span> </li> <li> <span class="content-list-recycle-back">返回</span> <span class="todo-title">逃军 2</span> <span class="icon-delete">×</span> </li> <li> <span class="content-list-recycle-back">返回</span> <span class="todo-title">逃军 3</span> <span class="icon-delete">×</span> </li> </ul> </div> </div> <!-- --> </div> <!-- 底部信息 --> <div class="footer"> <p>不折腾的前端</p> <p>和咸鱼有什么区别</p> <p>@2019 <a href="" target="_blank">jsliang 文档库</a></p> </div> </div> <!-- js 区 --> <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script> <script src="./js/index.js"></script> </body> </html> 复制代码
此时页面内容以下所示:
搭建好网页的骨架,咱们先让它跑起来吧。
你能够上面的 HTML 步骤想象成造了一个骷髅人,而后如今你要施法,要让骷髅人跑起来了。
奔跑吧,骷髅人~
如今,咱们进行页面的数据化,咱们须要考虑有哪几块是须要变成数据的:输入的内容、todo 项、完成项、未完成项。
那么,咱们先进行简单抽取:
index.html 代码片断
<!-- 内容区 -->
<div class="content">
<!-- 输入区 -->
<div class="content-input-todo">
<input type="text" placeholder="第 n 个敌人" v-model="todo">
<button>进击</button>
</div>
<!-- 列表区 -->
<div class="content-list">
<!-- 未完成 -->
<div class="content-list-todo">
<h4>千军万马取敌首</h4>
<p>(待完成)</p>
<ul>
<li v-for="todoItem in todoInfos" :key="todoItem.id">
<input type="checkbox" v-model="todoItem.isChecked">
<span class="todo-title" v-text="todoItem.todoTitle"></span>
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
<!-- 已完成 -->
<div class="content-list-finish">
<h4>敌羞吾去脱他衣</h4>
<p>(已完成)</p>
<ul>
<li v-for="finishItem in finishInfos" :key="finishItem.id">
<input type="checkbox" v-model="finishItem.isChecked">
<span class="todo-title" v-text="finishItem.todoTitle"></span>
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
<!-- 回收站 -->
<div class="content-list-recycle">
<h4>溃不成军鸟兽散</h4>
<p>(回收站)</p>
<ul>
<li v-for="recycleItem in recycleInfos" :key="recycleItem.id">
<span class="content-list-recycle-back">返回</span>
<span class="todo-title" v-text="recycleItem.todoTitle"></span>
<span class="icon-delete">x</span>
</li>
</ul>
</div>
</div>
</div>
复制代码
在这里,咱们将页面数据化了,如今看下咱们的 index.js
内容:
index.js
var app = new Vue({
el: "#app",
data: {
id: 1,
todo: "",
todoInfos: [
{
id: 7,
isChecked: false,
todoTitle: "敌军 1",
},
{
id: 8,
isChecked: false,
todoTitle: "敌军 2",
},
{
id: 9,
isChecked: false,
todoTitle: "敌军 3",
},
],
finishInfos: [
{
id: 1,
isChecked: true,
todoTitle: "亡军 1",
},
{
id: 2,
isChecked: true,
todoTitle: "亡军 2",
},
{
id: 3,
isChecked: true,
todoTitle: "亡军 3",
},
],
recycleInfos: [
{
id: 4,
isChecked: false,
todoTitle: "逃军 1",
},
{
id: 5,
isChecked: false,
todoTitle: "逃军 2",
},
{
id: 6,
isChecked: false,
todoTitle: "逃军 3",
},
]
}
})
复制代码
这样,咱们就经过 v-for
完成了数据的渲染,同时页面和以前的同样:
在这里,咱们稍微暂停下,观察 todoInfos
、finishInfos
、recycleInfos
这三个数组,发现它们都是差很少的结构。那么,咱们干脆将它合并?
index.js
var app = new Vue({
el: "#app",
data: {
id: 1,
todo: "",
todoInfos: [
{
id: 7, // id 惟一且自增
isChecked: false, // 未完成和放弃为 false,完成为 true
isEdit: false, // 是否在编辑
todoTitle: "敌军 1",
state: 0, // 0 - 未完成,1 - 完成,2 - 放弃完成
},
{
id: 8, // id 惟一且自增
isChecked: false, // 未完成和放弃为 false,完成为 true
isEdit: false, // 是否在编辑
todoTitle: "敌军 2", // todo 标题
state: 1, // 0 - 未完成,1 - 完成,2 - 放弃完成
},
{
id: 9, // id 惟一且自增
isChecked: false, // 未完成和放弃为 false,完成为 true
isEdit: false, // 是否在编辑
todoTitle: "敌军 3", // todo 标题
state: 2, // 0 - 未完成,1 - 完成,2 - 放弃完成
},
]
}
})
复制代码
这样一来,咱们就能够修改 HTML,让它经过 state
来区分这三块的数据:
index.html 代码片断
<!-- 内容区 -->
<div class="content">
<!-- 输入区 -->
<div class="content-input-todo">
<input type="text" placeholder="第 n 个敌人" v-model="todo">
<button>进击</button>
</div>
<!-- 列表区 -->
<div class="content-list">
<!-- 未完成 -->
<div class="content-list-todo">
<h4>千军万马取敌首</h4>
<p>(待完成)</p>
<ul>
<li v-for="todoItem in todoInfos" :key="todoItem.id" v-if="todoItem.state == 0">
<input type="checkbox" v-model="todoItem.isChecked">
<span class="todo-title" v-if="!todoItem.isEdit" v-text="todoItem.todoTitle"></span>
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
<!-- 已完成 -->
<div class="content-list-finish">
<h4>敌羞吾去脱他衣</h4>
<p>(已完成)</p>
<ul>
<li v-for="finishItem in todoInfos" :key="finishItem.id" v-if="finishItem.state == 1">
<input type="checkbox" v-model="finishItem.isChecked">
<span class="todo-title" v-if="!finishItem.isEdit" v-text="finishItem.todoTitle"></span>
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
<!-- 回收站 -->
<div class="content-list-recycle">
<h4>溃不成军鸟兽散</h4>
<p>(回收站)</p>
<ul>
<li v-for="recycleItem in todoInfos" :key="recycleItem.id" v-if="recycleItem.state == 2">
<span class="content-list-recycle-back">返回</span>
<span class="todo-title" v-if="!recycleItem.isEdit" v-text="recycleItem.todoTitle"></span>
<span class="icon-delete">x</span>
</li>
</ul>
</div>
</div>
</div>
复制代码
此时,咱们的页面仍是如修改以前通常,可是已经实现了数据化。
下面咱们开始写增删改数据的功能方法。
首先,咱们往 HTML 中添加点击事件,固然,若是每次都要点击按钮,就太麻烦了,干脆咱们再加个键盘回车事件:
index.html 代码片断
<!-- 输入区 -->
<div class="content-input-todo">
<input type="text" placeholder="第 n 个敌人" v-model="todo" @keyup.enter="addTodoItem">
<button @click="addTodoItem">进击</button>
</div>
复制代码
而后,咱们往 JS 中添加点击方法:
index.js
var app = new Vue({
el: "#app",
data: {
id: 1,
todo: "",
todoInfos: [
// 已不须要,注释掉
// {
// id: 7, // id 惟一且自增
// isChecked: false, // 未完成和放弃为 false,完成为 true
// isEdit: false, // 是否在编辑
// todoTitle: "敌军 1",
// state: 0, // 0 - 未完成,1 - 完成,2 - 放弃完成
// },
]
},
methods: {
addTodoItem() {
// 每次点击,往数组中添加一组数据
this.todoInfos.push({
id: this.id, // id 惟一且自增
isChecked: false, // 未完成和放弃为 false,完成为 true
isEdit: false, // 是否在编辑
todoTitle: this.todo, // todo 标题
state: 0, // 0 - 未完成,1 - 完成,2 - 放弃完成
})
// id 自增
this.id++;
// 清空输入框
this.todo = "";
},
}
})
复制代码
最后,咱们查看下新增功能是否实现:
下面咱们进行 isChecked
与 state
的改变,从而让数据在这三种状态中变化:
栏目 | 状态 |
---|---|
未完成 | isChecked: false 、state: 0 |
已完成 | isChecked: true 、state: 1 |
回收站 | state: 2 |
在本章节,咱们实现 未完成 -> 已完成 的转变,这里只须要修改下 HTML 代码便可:
index.html 代码片断
<!-- 未完成 -->
<div class="content-list-todo">
<h4>千军万马取敌首</h4>
<p>(待完成)</p>
<ul>
<li v-for="todoItem in todoInfos" :key="todoItem.id" v-if="todoItem.state == 0">
<input type="checkbox" v-model="todoItem.isChecked" @change="todoItem.state = 1">
<span class="todo-title" v-if="!todoItem.isEdit" v-text="todoItem.todoTitle"></span>
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
<!-- 已完成 -->
<div class="content-list-finish">
<h4>敌羞吾去脱他衣</h4>
<p>(已完成)</p>
<ul>
<li v-for="finishItem in todoInfos" :key="finishItem.id" v-if="finishItem.state == 1">
<input type="checkbox" v-model="finishItem.isChecked" @change="finishItem.state = 0">
<span class="todo-title" v-if="!finishItem.isEdit" v-text="finishItem.todoTitle"></span>
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
复制代码
咱们能够查看下结果:
OK,成功完成 待完成 -> 已完成 的转变。
如今,咱们实现点击 todoTitle
,变成修改模式,修改完后点击其余地方,或者按下回车按钮,从而实现数据的修改:
index.html 代码片断
<!-- 列表区 -->
<div class="content-list">
<!-- 未完成 -->
<div class="content-list-todo">
<h4>千军万马取敌首</h4>
<p>(待完成)</p>
<ul>
<li v-for="todoItem in todoInfos" :key="todoItem.id" v-if="todoItem.state == 0">
<input type="checkbox" v-model="todoItem.isChecked" @change="todoItem.state = 1">
<span class="todo-title" v-text="todoItem.todoTitle" v-if="!todoItem.isEdit" @click="todoItem.isEdit = true"></span>
<input v-if="todoItem.isEdit" @blur="todoItem.isEdit = false" @keyup.enter="todoItem.isEdit = false" type="text" v-model="todoItem.todoTitle">
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
<!-- 已完成 -->
<div class="content-list-finish">
<h4>敌羞吾去脱他衣</h4>
<p>(已完成)</p>
<ul>
<li v-for="finishItem in todoInfos" :key="finishItem.id" v-if="finishItem.state == 1">
<input type="checkbox" v-model="finishItem.isChecked" @change="finishItem.state = 0">
<span class="todo-title" v-text="finishItem.todoTitle" v-if="!finishItem.isEdit" @click="finishItem.isEdit = true"></span>
<input v-if="finishItem.isEdit" @blur="finishItem.isEdit = false" @keyup.enter="finishItem.isEdit = false" v-model="finishItem.todoTitle" type="text">
<span class="icon-recycle">x</span>
</li>
</ul>
</div>
<!-- 回收站 -->
<div class="content-list-recycle">
<h4>溃不成军鸟兽散</h4>
<p>(回收站)</p>
<ul>
<li v-for="recycleItem in todoInfos" :key="recycleItem.id" v-if="recycleItem.state == 2">
<span class="content-list-recycle-back">返回</span>
<span class="todo-title" v-text="recycleItem.todoTitle" v-if="!recycleItem.isEdit" @click="recycleItem.isEdit = true"></span>
<input v-if="recycleItem.isEdit" type="text" @blur="recycleItem.isEdit = false" @keyup.enter="recycleItem.isEdit = false" v-model="recycleItem.todoTitle">
<span class="icon-delete">x</span>
</li>
</ul>
</div>
</div>
复制代码
在这里,咱们仅须要在点击 span
标签的时候,改变下 isEdit
的状态,即进入编辑模式,同时,在 input
标签失去焦点或者在输入完成后点击回车按钮,就能够实现数据的修改。
最后,咱们查看下实现状况:
同理,若是咱们要将数据扔进回收站中去,那就须要将 state
改成 2 便可。
若是数据是从回收站返回待完成,咱们只须要将 state
改成 0 便可。
index.html 代码片断
<!-- 未完成 -->
<div class="content-list-todo">
<h4>千军万马取敌首</h4>
<p>(待完成)</p>
<ul>
<li v-for="todoItem in todoInfos" :key="todoItem.id" v-if="todoItem.state == 0">
<input type="checkbox" v-model="todoItem.isChecked" @change="todoItem.state = 1">
<span class="todo-title" v-text="todoItem.todoTitle" v-if="!todoItem.isEdit" @click="todoItem.isEdit = true"></span>
<input v-if="todoItem.isEdit" @blur="todoItem.isEdit = false" @keyup.enter="todoItem.isEdit = false" type="text" v-model="todoItem.todoTitle">
<span class="icon-recycle" @click="todoItem.state = 2">x</span>
</li>
</ul>
</div>
<!-- 已完成 -->
<div class="content-list-finish">
<h4>敌羞吾去脱他衣</h4>
<p>(已完成)</p>
<ul>
<li v-for="finishItem in todoInfos" :key="finishItem.id" v-if="finishItem.state == 1">
<input type="checkbox" v-model="finishItem.isChecked" @change="finishItem.state = 0">
<span class="todo-title" v-text="finishItem.todoTitle" v-if="!finishItem.isEdit" @click="finishItem.isEdit = true"></span>
<input v-if="finishItem.isEdit" @blur="finishItem.isEdit = false" @keyup.enter="finishItem.isEdit = false" v-model="finishItem.todoTitle" type="text">
<span class="icon-recycle" @click="finishItem.state = 2">x</span>
</li>
</ul>
</div>
复制代码
实现结果:
首先,咱们给 HTML 添加点击事件,将参数传递给方法体中
index.html 代码片断
<!-- 回收站 -->
<div class="content-list-recycle">
<h4>溃不成军鸟兽散</h4>
<p>(回收站)</p>
<ul>
<li v-for="recycleItem in todoInfos" :key="recycleItem.id" v-if="recycleItem.state == 2">
<span class="content-list-recycle-back" @click="recycleItem.state = 0; recycleItem.isChecked = false">返回</span>
<span class="todo-title" v-text="recycleItem.todoTitle" v-if="!recycleItem.isEdit" @click="recycleItem.isEdit = true"></span>
<input v-if="recycleItem.isEdit" type="text" @blur="recycleItem.isEdit = false" @keyup.enter="recycleItem.isEdit = false" v-model="recycleItem.todoTitle">
<span class="icon-delete" @click="deleteInfo(recycleItem)">x</span>
</li>
</ul>
</div>
复制代码
而后,咱们经过编写 deleteInfo
来删除 todoInfos
中的数据:
index.js 代码片断
methods: {
addTodoItem() {
// 每次点击,往数组中添加一组数据
this.todoInfos.push({
id: this.id, // id 惟一且自增
isChecked: false, // 未完成和放弃为 false,完成为 true
isEdit: false, // 是否在编辑
todoTitle: this.todo, // todo 标题
state: 0, // 0 - 未完成,1 - 完成,2 - 放弃完成
})
// id 自增
this.id++;
// 清空输入框
this.todo = "";
},
/**
* 这里使用了三种写法
* 1. map + splice
* 2. splice + findIndex
* 3. filter
*/
// // 1. map + splice 写法
// deleteInfo(recycleItem) {
// this.todoInfos.map((item, index) => {
// if(item.id == recycleItem.id) {
// this.todoInfos.splice(index, 1);
// }
// })
// },
// // 2. splice + findIndex 写法
// deleteInfo(recycleItem) {
// this.todoInfos.splice( this.todoInfos.findIndex( v => v.id === recycleItem.id), 1);
// },
// 3. filter 写法
deleteInfo(recycleItem) {
this.todoInfos = this.todoInfos.filter( (x) => {
return x.id != recycleItem.id;
})
}
}
复制代码
兴致突来,想起 茴字的四种写法,因而,这里也奉上删除数据的三种写法,这里就不估算性能损耗了,哪一种喜欢就用哪一种吧。
此时完成功能以下所示:
到此,咱们完成了全部的功能实现~
那么,咱们回来咱们的大难题,就是给这个页面增长皮肤,让这个页面漂亮点。
enm......由于不一样浏览器对于一些 DOM 元素的渲染不一样,因此咱们先重置下浏览器样式吧:
reset.css
/*
* reset 的目的不是让默认样式在全部浏览器下一致,而是减小默认样式有可能带来的问题。
* The purpose of reset is not to allow default styles to be consistent across all browsers, but to reduce the potential problems of default styles.
* create by jsliang
*/
/** 清除内外边距 - clearance of inner and outer margins **/
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* 结构元素 - structural elements */
dl, dt, dd, ul, ol, li, /* 列表元素 - list elements */
pre, /* 文本格式元素 - text formatting elements */
form, fieldset, legend, button, input, textarea, /* 表单元素 - from elements */
th, td /* 表格元素 - table elements */ {
margin: 0;
padding: 0;
}
/** 设置默认字体 - setting the default font **/
body, button, input, select, textarea {
font: 18px/1.5 '黑体', Helvetica, sans-serif;
}
h1, h2, h3, h4, h5, h6, button, input, select, textarea { font-size: 100%; }
/** 重置列表元素 - reset the list element **/
ul, ol { list-style: none; }
/** 重置文本格式元素 - reset the text format element **/
a, a:hover { text-decoration: none; }
/** 重置表单元素 - reset the form element **/
button { cursor: pointer; }
input { font-size: 18px; outline: none; }
/** 重置表格元素 - reset the table element **/
table { border-collapse: collapse; border-spacing: 0; }
/** 图片自适应 - image responsize **/
img { border: 0; display: inline-block; width: 100%; max-width: 100%; height: auto; vertical-align: middle; }
/*
* 默认box-sizing是content-box,该属性致使padding会撑大div,使用border-box能够解决该问题
* set border-box for box-sizing when you use div, it solve the problem when you add padding and don't want to make the div width bigger */ div, input { box-sizing: border-box; } /** 清除浮动 - clear float **/ .jsliang-clear:after, .clear:after { content: '\20'; display: block; height: 0; clear: both; } .jsliang-clear, .clear { *zoom: 1; } /** 设置input的placeholder - set input placeholder **/ input::-webkit-input-placeholder { color: #919191; font-size: 16px } /* Webkit browsers */ input::-moz-placeholder { color: #919191; font-size: 16px } /* Mozilla Firefox */ input::-ms-input-placeholder { color: #919191; font-size: 16px } /* Internet Explorer */ 复制代码
而后,咱们就面临一个问题,要怎么美化呢?
脑阔疼,咱们仍是去网上盗个皮肤下来吧:
很好,而后咱们对着修改下 CSS:
index.css
/* 共用 */
html, body {
height: 100%;
}
body {
background: url("../img/background.jpg") no-repeat center;
background-size: 100% 100%;
}
/* 多项选项框 */
input[type="checkbox"] {
width: 25px;
height: 25px;
background-color: #fff;
-webkit-appearance: none;
border: 1px solid deepskyblue;
border-radius: 2px;
outline: none;
}
input[type="checkbox"]:hover {
cursor: pointer;
}
input[type="checkbox"]:checked {
background: url("../img/icon-checked.png") no-repeat center;
background-size: 100%;
}
/* 共用标题样式 */
.todo-title {
margin-top: 10px;
word-break: normal;
width: 75%;
display: block;
white-space: pre-wrap;
word-wrap: break-word ;
overflow: hidden ;
}
/* 图标样式 */
.icon-recycle {
width: 25px;
height: 25px;
background: url("../img/icon-recycle.png") no-repeat center;
background-size: 100%;
}
.icon-delete {
width: 25px;
height: 25px;
background: url("../img/icon-delete.png") no-repeat center;
background-size: 100%;
}
.content-list-recycle-back {
display: block;
width: 20px;
height: 20px;
background: url("../img/icon-back.png") no-repeat center;
background-size: 100%;
}
/* 页面主体 */
.main-container {
width: 1200px;
height: 100%;
margin: 0 auto;
position: relative;
}
/* 头部标题 */
.header {
width: 100%;
height: 150px;
background: url("../img/title.png") no-repeat center;
}
/* 内容区 */
.content {
text-align: center;
}
/* 内容区 - 输入区 */
.content-input-todo {
height: 40px;
}
.content-input-todo input {
height: 40px;
padding-left: 20px;
padding-right: 20px;
border: none;
border-radius: 20px;
}
.content-input-todo button {
width: 100px;
padding: 5px;
border-radius: 20px;
background: #36AF9E;
color: #fff;
outline: none;
}
/* 内容区 - 列表区 */
.content-list {
display: flex;
margin-top: 30px;
}
.content-list div {
width: 380px;
margin-right: 20px;
border: 1px solid #ccc;
padding: 30px;
border: 15px solid transparent;
border-image: url("../img/border.png") 60 60 stretch;
}
.content-list div ul {
text-align: left;
}
.content-list div ul li {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #ccc;
}
.content-list div ul li:hover {
cursor: pointer;
}
.content-list div ul li input[type="checkbox"] {
margin-right: 10px;
}
.content-list div ul li input[type="text"] {
outline: none;
border: none;
background: rgba(255, 255, 255, 0);
color: #000;
border-bottom: 1px solid #ccc;
}
/* 底部区 */
.footer {
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
}
.footer a {
color: deepskyblue;
}
.footer a:hover {
color: deepskyblue;
}
复制代码
大功告成,看下咱们的成品:
到此,咱们就写完了这个简单的小 Demo 咯~
下面将代码地址和项目地址贴出来,须要 参考 的小伙伴自行下载或者观看。
代码地址:功成千骨 - 代码地址
项目地址:功成千骨 - 线上地址
固然,还没完!
咱们还能够折腾更多:
ElementUI
或者 Bootstrap
进行多端适配localStorage
来进行本地版开发Node
来进行数据多端使用HTML5
的 manifest
来开发 离线存储那么,后面有机会折腾,咱再相会 Todolist ,打造升级版本的啦~
后记
若是小伙伴须要存放 jsliang.top 这样的纯静态页面或者 company.jsliang.top 这样的具备 Node 后端支持的页面,推荐购买云服务器来存放。
若是小伙伴们不知道该怎么选择云服务器,能够查看 详细介绍 或者加 jsliang QQ:1741020489
咨询。
![]()
jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议 进行许可。
基于 github.om/LiangJunron… 上的做品创做。
本许可协议受权以外的使用权限能够从 creativecommons.org/licenses/by… 处得到。