在coding以前,咱们先把环境搭好,包括数据库的安装配置以及thinkjs的安装配置。javascript
一、数据库安装css
本项目使用关系型数据库MySQL,电脑上没有安装上MySQL的同窗能够自行上官网下载安装,有关MySQL的知识能够上菜鸟教程和慕课网学习,这里很少说。html
二、ThinkJS安装前端
这里咱们使用ThinkJS 2.2版本,因此如下步骤都是针对2.2版本,想使用3.0版本的同窗能够自行尝试。可直接使用npm进行安装,参考官方文档。安装完成后便可建立项目。java
三、模版引擎安装mysql
使用thinkjs命令建立好项目好,经过npm install安装依赖项,而后能够安装模版引擎,这里以nunjucks为例,安装命令以下:jquery
npm install nunjucks --save
主要进行两项配置,一是数据库配置,二是模版引擎配置。ajax
一、数据库配置sql
配置文件db.js所在目录以下图(2.2版本):数据库
配置代码以下图:
二、模版引擎的配置
配置文件view.js所在目录以下图(2.2版本):
nunjucks配置代码以下图:
项目的开始咱们要设计数据表,咱们能够只建立一个表think_tododemo,它包含三个键,参考代码以下:
CREATE TABLE IF NOT EXISTS `think_tododemo`( `id` INT UNSIGNED AUTO_INCREMENT, `title` VARCHAR(100) NOT NULL, `done` INT UNSIGNED NOT NULL, PRIMARY KEY ( `id` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8;
其中id用做编号,title为每项事务的内容,done表示是否已经完成(0表示正在进行,1表示已经完成)。固然你能够设计不一样的数据表。
因为咱们要实现的todolist是单页应用,因此只须要一个控制器,在里面实现相应的接口方法便可。
一、home/index/indexAction
首先,咱们实现home模块中index控制器的indexAction方法,参考代码以下:
async indexAction(){ let model = this.model('tododemo'); //查询正在进行的待办项数据 let todoData = await model.where({done: 0}).select(); //查询已经完成的待办项数据 let doneData = await model.where({done: 1}).select(); //变量赋值,传递给view this.assign('todoList', todoData); this.assign('doneList', doneData); this.assign('todoCount', todoData.length); this.assign('doneCount', doneData.length); return this.display(); }
这样访问这个控制器方法就能够把数据库中的数据赋值到变量中,而且渲染view中对应的index_index.html。
二、home/index/addAction
而后咱们实现addAction这个方法,用于添加新的待办项,参考代码以下:
async addAction(){ let model = this.model('tododemo'); if(this.isPost()){ let item = this.post('title'); let insertItem = await model.add({ title: item, done: 0 }); if(!insertItem){ return this.fail(1000, '添加待办项失败!'); } else{ return this.success(); } } else { return this.fail(2000, 'post传递参数不存在!'); } }
当待办项被正确添加到数据库中,能够经过this.success(data)返回数据,不然能够经过this.fail(errno, errmsg)返回错误提示。
其余须要实现的方法包括updateAction、removeAction、clearAction等等,请同窗们自行实现。
在view目录中,咱们实现HTML的结构设计,即home模块下的index_index.html。在完成这一步以前,须要先学习一下模版引擎,好比咱们这里要用到nunjucks。参考代码以下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ToDoList</title> <link rel="stylesheet" type="text/css" href="/static/css/index.css"> <script type="text/javascript" src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script> </head> <body> <header> <form action="javascript:add()" method="POST"> <label for="title">ToDoList</label> <button id="btn" class="btn" type="submit">提交</button> <input type="text" id="title" name="title" placeholder="添加ToDo"> </form> </header> <section> <h2>正在进行 <span id="todocount"> {{ todoCount }} </span> </h2> <ol id="todolist" class="list"> {% for item in todoList %} <li> <input type="checkbox" onchange="update({{ item.id }}, 1)" /> <p id="p-{{item.id}}" onclick="edit({{ item.id }})">{{ item.title }}</p> <a href="javascript:remove({{ item.id }})">-</a> </li> {% endfor %} </ol> <h2>已经完成 <span id="donecount"> {{ todoCount }} </span> </h2> <ul id="donelist" class="list"> {% for item in doneList %} <li> <input type="checkbox" onchange="update({{ item.id }}, 0)" /> <p id="p-{{item.id}}" onclick="edit({{ item.id }})">{{ item.title }}</p> <a href="javascript:remove({{ item.id }})">-</a> </li> {% endfor %} </ul> </section> <footer>Copyright © 2017 <a href="javascript:clear()">clear</a> </footer> <script type="text/javascript" src="/static/js/index.js"></script> </body> </html>
这里要注意css和js文件的存放位置以及引用路径,并且这里用到了jQuery,因此同时须要引用jQuery。同窗们能够自行添加不一样的css样式。
前端js文件存放在www/static/js目录下(2.2版本),咱们要实现其中的方法,好比添加待办项的add方法,参考代码以下:
function add(){ var title = document.querySelector("#title"); if(title.value == ""){ alert("内容不能为空"); } else{ var item = title.value; $.ajax({ url: '/home/index/add', type: 'POST', dataType: 'json', data: { title: item }, success: res => { if(!res.errno) { window.location.reload(); } else alert(res.errmsg); } }); } }
在参考代码中,实际上只有当后端返回成功提示时,页面才会刷新显示新添加的数据,这并非一种良好的交互设计,因此可想办法使得提交新待办项后前端页面能够及时更新而不用等后端响应。
这里只实现了add方法,其余方法请自行实现。
除了上述功能外,能够按照本身的想法实现一些新功能,好比正在进行的列表项能够拖拽改变它们的顺序。