成果展示
启动mysql,用knex连接数据
终端运行
mysql.server start
看到“starting mysql SUCCESS!”,把服务启动起来后,再新开一个终端窗口,用root登录
mysql -u root // 显示welcome to the MySQL monitor
show databases
use example //例子中用到了example这个database
knex是一个npm包,用于node.js下连接mysql。
连接mysql
var knex = require('knex')({
client:'mysql',
connection:{
host:'localhost',
user: 'root',
password: '',
database: 'example'
}
})
接口功能拆分
建表:创建任务列表
function createToDoList() {
return
knex.schema
.hasTable('todolist')
.then( ifExist => {
if(!ifExist){
return knex.schema.createTable('todolist', (table) =>{
table.increments('task_id').primary()
table.string('task_name').notNullable()
table.integer('task_status').notNullable().defaultTo(0)
table.dateTime('task_start_date')
table.dateTime('task_end_date')
})
}
})
.catch( err => {
console.log('error !!!', err.message, err.stack)
return
})
}
查询任务列表
状态分为0(未完成)和1(已经完成),分别保存在两个数组里。
async function getTasks(){
var toDoTasks = await knex('todolist').select().where('task_status', 0)
var finishedTasks = await knex('todolist').select().where('task_status', 1)
return {toDoTasks, finishedTasks}
}
添加任务
function addTask(content){
return knex('todolist').insert({
task_name: content,
task_start_date: new Date(),
}).then( (task_id) => {
return knex('todolist').select().where('task_id', task_id)
}).then( newtask =>{
return newtask
})
.catch(err => {
throw err
})
}
// 测试一下
//addTask('learn knex api ')
//addTask('finish eg.js').then( (task_id) => {console.log('from addTask', task_id)})
删除任务
function deleteTask(task_id){
return knex('todolist').where('task_id', task_id).del()
.then( deleteRowNum => {
return deleteRowNum
})
.catch(err => {
throw err
})
}
//deleteTask(1)
修改任务内容
function editTask(taskobj){
return knex('todolist').where('task_id', taskobj.task_id)
.update('task_name', taskobj.task_name)
.then( editRowNum => {
return editRowNum
})
.catch(err => {
throw err
})
}
// editTask({
// task_id: 1,
// task_name: 'wanna eat dinner'
// })
把任务设为已完成/恢复任务为未完成
function checkTask(taskobj){
var dateobj = +taskobj.task_status? {} : {task_end_date: new Date()}
var updateobj = Object.assign({}, {task_status :taskobj.task_status? 0 : 1}, dateobj)
return knex('todolist')
.where('task_id', taskobj.task_id)
.update(updateobj)
.then( editRowNum => {
return editRowNum
})
.catch(err => {
throw err
})
}
然后配一下controller,让路由去到正确的操作。我是整体配在/taskapi下面的,再分到每一个具体的api。以getTasks和addTask为例:
const {createToDoList, getTasks, addTask, deleteTask, editTask, checkTask } = require('../models/tasks')
const express = require('express');
const router = express.Router();
router.get('/getTasks', (req, res, next) => {
getTasks().then( tasks => {
res.send(tasks)
}).catch(err => {
throw err
})
})
router.post('/addTask', (req, res) => {
addTask(req.body['task_name'])
.then( newtasks =>{
res.send(newtasks[0])
})
.catch(err => {
throw err
})
})
前端展示:vue+bootstrap
express的view engine 设的是ejs,对应views下的 todolist.ejs 引入vue和bootstrap等文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title><%= title %>- Demo</title>
<link rel='stylesheet' href='/lib/bootstrap/dist/css/bootstrap.min.css' />
<link rel='stylesheet' href='/stylesheets/todolist.css' />
<script type="text/javascript" src='/lib/vue/dist/vue.min.js'></script>
</head>
要使src顺利引入,还需要配一下static的路径。
app.use('/lib', express.static('whereYourNodeModulesFolderAre/orResourcesInOtherPlace')) //
以下是todolist.ejs 的 主体部分,直接写vue 就可以了,就该怎么写怎么写呗~~
<div class="container root">
<h3>to do list</h3>
<aside>点击要做的事项,即可编辑</aside>
<ul>
<li is='to-do-item' v-for="(task,taskIndex ) in toDoTasks" :key="task.task_id"
:task=task
@remove='toDoTasks.splice(taskIndex, 1)'
></li>
<div class="input-group mb-3">
<input class="form-control" v-model='newTaskName' @keyup.enter='addNewToDo' placeholder='回车键添加新任务' />
</div>
</ul>
<h3>finished tasks</h3>
<ol v-if='finishedTasks.length' class='listgroup'>
<li v-for='task in finishedTasks' :key='task.task_id' class="list-group-item">{{task.task_name}}</li>
</ol>
<hr />
<footer>
<p><a href="https://blog.csdn.net/github_36487770" target="_blank">十方魔</a> 2018</p>
</footer>
</div>
发送ajax就跟正常一样就行了
addNewToDo(){
const _task_name = this.newTaskName.trim()
if(!_task_name){
alert('任务不能为空')
return
}
$.post('/taskapi/addTask', {task_name: _task_name}, (newtask) => {
this.toDoTasks.push(newtask)
this.newTaskName = ''
})
}
All Done:一点想法
羞愧地说,这都是一个多月前做的了,不管当时有什么想法,现在都不记得了。