Koa2 + Vue 初始化
koa-generator 初始化(npm i yarn -g)
npm i koa-generator -g koa2 -e demo cd demo yarn yarn run dev
.html 渲染页面
/app.js
app.use(views(__dirname + '/views', { map: { html: 'ejs' } }))
公共头部、页底
新建 /views/header.html ( 并引入 vue, vue-router, axios, elementUi )
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/style/style.css' />
<link rel="stylesheet" href="/style/element.css">
<script src="/js/vue.js"></script>
<script src="/js/vue-router.js"></script>
<script src="/js/axios.min.js"></script>
<script src="/js/element.js"></script>
</head>
<body>
新建 /views/footer.html
</body> </html>
/views/index.html 复用页头、页尾
<% include header.html %>
<div id="app">
<router-view></router-view>
</div>
<script>
// 配置单页路由
const router = new VueRouter({
mode: 'hash',
routes: [
{ path: '/course', component: <% include ./layout/course.html %> },
{ path: '/detail', component: <% include ./layout/detail.html %> }
]
})
const app = new Vue({
name: 'app',
router,
data() {
return {
title: '<%- title %>'
}
},
created() {
this.$router.push({ path: '/course' })
},
methods: {
list() {
axios.post('/list', { page: 1, limit: 10 })
.then(res => res.data)
.catch(err => console.log(err))
},
detail() {
axios.get('/detail', { params: { id: 1 } })
.then(res => res.data)
.catch(err => console.log(err))
},
}
}).$mount('#app')
</script>
<% include footer.html %>
新建 /views/layout/course.html
Vue.component('course', { components: { divider: <% include ../component/divider.html %> // 自定义组件 }, data() { return { list: [] } }, created() { this.getList() }, methods: { getList() { axios.post('/list', { page: 1, limit: 10 }) .then(res => { this.list = res.data }) .catch(err => console.log(err)) }, detail({ id }) { this.$router.push({ path: '/detail', query: { id } }) }, }, template: ` <div class="course"> <divider title="人员信息"></divider> <el-table border stripe :data="list" style="width: 100%"> <el-table-column prop="name" label="姓名"></el-table-column> <el-table-column prop="course" label="学科"></el-table-column> <el-table-column fixed="right" label="操作"> <template slot-scope="scope"> <el-button @click="detail(scope.row)" type="text" size="small">查看</el-button> </template> </el-table-column> </el-table> </div> ` })
新建 /views/layout/detail.html
Vue.component('detail', { data() { return { id: this.$route.query.id, list: [] } }, created() { this.detail() }, methods: { detail() { axios.get('/detail', { params: { id: this.id } }) .then(res => { this.list = res.data }) .catch(err => console.log(err)) }, }, template: ` <div class="detail"> <el-table border stripe :data="list" style="width: 100%"> <el-table-column prop="course" label="课程名称"></el-table-column> </el-table> </div> ` })
新建 /views/component/divider.html
Vue.component('divider', { props: ['title'], data() { return { } }, template: ` <div> <el-divider content-position="left">{{title}}(自定义组件)</el-divider> </div> ` })
mysql
yarn add mysql
新建 /utils/mysql.js
const mysql = require('mysql');
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'root',
database: 'test',
supportBigNumbers: true,
bigNumberStrings: true
});
const exec = sql => {
return new Promise((resolve, reject) => {
pool.getConnection((error, connection) => {
if (error) {
reject('DB-获取数据库连接异常!')
}
connection.query(sql, (error, result) => {
if (error) {
reject('DB-执行查询语句异常!')
}
resolve(result)
})
connection.release(error => {
if (error) {
reject('DB-关闭数据库连接异常!')
}
})
})
})
}
module.exports = exec;
数据库交互
/routes/index.js
const router = require('koa-router')()
const exec = require('../utils/mysql');
router.get('/', async (ctx, next) => {
// 页面渲染
await ctx.render('index', {
title: 'vueDemo'
})
})
router.get('/detail', async (ctx, next) => {
const { id } = ctx.query
const sql = `select * from course where userId = ${id};`
const list = await exec(sql)
ctx.body = list
})
router.post('/list', async (ctx, next) => {
const { page, limit } = ctx.request.body // POST 参数
const sql = `select u.*, group_concat(c.course) as course from user u left join course c on c.userId = u.id group by u.id limit ${(page - 1) * limit}, ${limit};`
const list = await exec(sql)
ctx.body = list
})
module.exports = router
pm2
yarn global add pm2
新建 /pm2.conf.json
{ "apps": { "name": "pm2-prd-server", "script": "./bin/www", "watch": true, "ignore_watch": [ "node_modules", "logs" ], "instances": 2, "error_file": "logs/err.log", "out_file": "logs/out.log", "log_date_format": "YYYY-MM-DD HH:mm:ss", "autorestart": true } }
pm2 运行配置
/package.json { "scripts": { "prd": "pm2 start pm2.conf.json" } }
npm run prd
目录
demo
├─ app.js
├─ bin
│ └─ www
├─ logs
│ ├─ err-1.log
│ └─ out-1.log
├─ package.json
├─ pm2.conf.json
├─ public
│ ├─ img
│ ├─ js
│ │ ├─ axios.min.js
│ │ ├─ element.js
│ │ └─ vue.js
│ └─ style
│ ├─ element.css
│ ├─ fonts
│ │ ├─ element-icons.eot
│ │ ├─ element-icons.svg
│ │ ├─ element-icons.ttf
│ │ ├─ element-icons.ttf.sfd
│ │ └─ element-icons.woff
│ └─ style.css
├─ routes
│ ├─ index.js
│ └─ users.js
├─ utils
│ └─ mysql.js
├─ views
│ ├─ components
│ │ └─ divider.html
│ ├─ layout
│ │ ├─ course.html
│ │ └─ detail.html
│ ├─ footer.html
│ ├─ header.html
│ └─ index.html
└─ yarn.lock
仓库
https://gitee.com/senjer/koa2-demo.git
常见问题
问题1:修改 pm2.conf.json 直接运行配置不生效? -- 需先 pm2 delete appName 再 npm run prd