用vue-cli构建工具搭建一个简单的登录页面,一个列表页面
列表页面功能有删除,编辑,添加
简单介绍说下路由配置,做登录拦截
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
let router = new Router({
routes: [
{
path: '/login',
component: resolve => require(['../pages/Login.vue'], resolve)
},
{
path: '/list',
component: resolve => require(['../pages/List.vue'], resolve)
},
{
path: '/',
redirect: '/login'
},
]
})
function getCookie(name){
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null){
return unescape(arr[2]);
}else{
return null;
}
}
router.beforeEach((to, from, next) => {
const token = getCookie('username');
if (to.path === '/login') { // 如果是跳转到登录页的
next()
} else {
if (token !== 'null' && token !== null) {
next() // 如果有token就正常转向
} else {
next('/login') // 否则跳转回登录页
}
}
})
export default router
window上安装mysql,安装步骤可以自己去了解一下,安装完MySQL之后你需要设定一下root账户的密码。保证安全性。
因为我对MySQL的SQL语句不是很熟悉,所以我需要一个可视化的工具来操作MySQL。Windows上我用的是navicat for mysql。
然后我们可以用这些可视化工具连上MySQL的server(默认端口是3306)之后,创建一个新的数据库,叫做todolist。(当然你也可以用SQL语句:CREATE DATABASE todolist,之后不再赘述)。
接着我们可以来开始创建数据表了。
我们需要创建待办事项表。表名是lists
跟数据库打交道的时候我们都需要一个好的操作数据库的工具,能够让我们用比较简单的方法来对数据库进行增删改查。
对于Mongodb来说大家熟悉的是Mongoose以及使用一个相对更简单点的Monk。
对于MySQL,我选用的是Sequelize,它支持多种关系型数据库(Sqlite、MySQL、Postgres等),
它的操作基本都能返回一个Promise对象,这样在Koa里面我们能够很方便地进行”同步”操作。
更多关于Sequelize的用法,可以参考官方文档,以及这两篇文章——Sequelize中文API文档、Sequelize和MySQL对照
安装命令
npm install sequelize mysql
在server目录下的config目录下我们新建一个db.js,用于初始化Sequelize和数据库的连接。
// config/db.js
const Sequelize = require('sequelize'); // 引入sequelize
// todolist:对应的数据库名称 root:对应的数据库账号 123456:对应的数据库密码
const Todolist = new Sequelize('todolist', 'root', '123456', {
host: '127.0.0.1',
port: 3306,
dialect: 'mysql',
logging: false,
freezeTableName: true,
operatorsAliases: false,
pool:{
max:5,
min:0,
idle:10000
}
})
module.exports = {
Todolist // 将Todolist暴露出接口方便Model调用
}
定义list的表结构
// mysql/list.js
module.exports = function(sequelize, DataTypes){
return sequelize.define('lists', {
user_id: {
type: DataTypes.INTEGER(11),
allowNull: true
},
content: {
type: DataTypes.CHAR(255),
allowNull: true
},
status: {
type: DataTypes.INTEGER(1),
allowNull: true
}
},{
timestamps: false
});
}
接着我们去model文件夹里将数据库和表结构文件连接起来。在这个文件夹下新建一个list.js的文件。我们先来写一个查询用户id的东西。
通常我们要查询一个用户id为1的数据,会很自然的想到类似如下的写法:
const list = lists.findOne({ where: { id: 1} }); // 查询
console.log(list); // 输出结果
完整的list数据库操作
// model/list.js
const db = require('../config/db.js'),
listModel = '../mysql/list.js'; // 引入list的表结构
const TodolistDb = db.Todolist; // 引入数据库
const List = TodolistDb.import(listModel); // 用sequelize的import方法引入表结构,实例化了User。
const getUserById = async function(id){
const userInfo = await List.findOne({
where: {
id: id
}
});
return userInfo // 返回数据
}
//返回列表
const getList = async function(){
const list = await List.findAll();
return list
}
//删除一条
const removeList = async function(data){
const result = await List.destroy({
where: {
id: data.id,
user_id: data.userId
}
})
return true
}
//创建一条
const addList = async function(data){
const result = await List.create({
user_id: data.user_id,
content: data.content,
status:1,
})
return true
}
//更新一条
const updateList = async function(data){
const result = await List.update(
{
content:data.content
},
{
where: {
id: data.id,
user_id: data.userId
}
}
)
return true
}
module.exports = {
getList,
removeList,
addList,
updateList
}
接着我们在controller写一个list的controller,来执行这个方法,并返回结果。
// controller/list.js
const list = require('../model/list.js');
const getList = async function(ctx){
const data = ctx.params.id;//get 获取url里传过来的参数
const result = await list.getList();
ctx.body = {
code: 0,
msg: 'success',
data: result
}
}
const removeList = async function(ctx){
const data = ctx.request.body//post koa-bodyparser中间件可以把koa2上下文的formData数据解析到ctx.request.body中
const result = await list.removeList(data);
ctx.body = {
code: 0,
msg: '删除成功!'
}
}
const addList = async function(ctx){
const data = ctx.request.body;//post
const result = await list.addList(data);
ctx.body = {
code: 0,
msg: '添加成功!'
}
}
const updateList = async function(ctx){
const data = ctx.request.body;//post
const result = await list.updateList(data);
ctx.body = {
code: 0,
msg: '修改成功!'
}
}
module.exports = {
getList,
removeList,
addList,
updateList
}
接着我们在controller写一个login的controller,来实现登录,并返回结果。
// controller/login.js
const login = async function(ctx){
const data = ctx.request.body;//post
if(data.username != 'admin'){
ctx.body = {
code: 1,
msg: '账号不正确!'
}
ctx.cookies.set('username','',{signed:false,maxAge:0})
return;
}
if(data.password != 123){
ctx.body = {
code: 1,
msg: '密码不正确!'
}
ctx.cookies.set('username','',{signed:false,maxAge:0})
return;
}
ctx.cookies.set(
'username',
'admin',
{
//domain: 'localhost', // 写cookie所在的域名
//path: '/', // 写cookie所在的路径
maxAge: 1 * 24 * 60 * 60 * 1000, // cookie有效时长 1天
expires: new Date('2018-02-15'), // cookie失效时间
httpOnly: false, // 是否只用于http请求中获取
overwrite: false // 是否允许重写
}
)
ctx.body = {
code: 0,
msg: '登录成功!'
}
}
module.exports = {
login
}
写完这个还不能直接请求,因为我们还没有定义路由,请求经过Koa找不到这个路径是没有反应的。
在routes文件夹下写一个all.js的文件。
// routes/all.js
const list = require('../controller/list.js');
const login = require('../controller/login.js');
const router = require('koa-router')();
router.post('/list/add', list.addList);//添加记录
router.post('/list/remove', list.removeList);//删除记录
router.post('/list/update', list.updateList);//更新记录
router.get('/list/get', list.getList);//获取记录
router.post('/login', login.login);//登录
module.exports = router; // 把router规则暴露出去
至此我们已经接近完成我们的第一个API了,还缺最后一步,将这个路由规则“挂载”到Koa上去。
回到根目录的app.js,改写如下:
const appKoa = new require('koa')
, koa = require('koa-router')()
, path =require('path')
, serve = require('koa-static')
, list = require('./routes/all.js'); // 引入路由
app = new appKoa();
// 静态文件serve在koa-router的其他规则之上
app.use(serve(path.resolve('dist'))); // 将webpack打包好的项目目录作为Koa静态文件服务的目录
app.use(require('koa-bodyparser')());
app.on('error', function(err, ctx){
console.log('server error', err);
});
koa.use('/api', list.routes()); // 挂载到koa-router上,同时会让所有的list的请求路径前面加上'/api'的请求路径。
app.use(koa.routes()); // 将路由规则挂载到Koa上。
app.listen(3000,() => {
console.log('Koa is listening in 3000');
});
module.exports = app;
打开你的控制台,输入node app.js,一切运行正常没有报错的话,大功告成,我们的第一个API已经构建完成!
API Test
接口在跟跟前端对接之前,我们应该先进行一遍测试,防止出现问题。在测试接口的工具上,我推荐Postman,这个工具能够很好的模拟发送的各种请求,方便的查看响应结果,用来进行测试是最好不过了。也可以在chrome浏览器安装插件
nginx配置
真正部署到服务器的时候,我们肯定不会让大家输入域名:3000这样的方式让大家访问。所以需要用Nginx监听80端口,把访问我们指定域名的请求引导转发给Koa服务端。
在服务器etc/nginx/conf.d文件夹创建一个nodejs.conf
nginx默认会引入这个文件夹下的配置
#目录 ect/nginx/conf.d/nodejs.conf
upstream nodejs {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name www.galan.cn;
#charset koi8-r;
#access_log logs/host.access.log main;
#缓存30天
location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
access_log off;
expires 30d;
proxy_pass http://nodejs;
}
#代理3000端口
location / {
proxy_pass http://nodejs;
index index.html index.htm;
}
}
}
配置一下Nginx的Gzip,能让请求的JS\CSS\HTML等静态文件更小,响应速度更快些
目录 ect/nginx/conf.conf
#目录 ect/nginx/conf.conf
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
#gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/javascript;
gzip_vary off;
gzip_disable "MSIE [1-6]\.";
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
最后再放上本文项目的Github地址,如果这个项目对你有帮助,希望大家可以fork,给我提建议,如果再有时间,可以点个Star那就更好啦~