Vue+node.js+express+mysql实例---对图书信息进行管理
一个简单的 CURD 实例 ---对图书信息进行管理
目录
1 开发环境
- 前端:vue、axios
- 后端:node.js、express
- 数据库:mysql
1.1 前端开发环境
新建一个文件夹book-curd-example
,以下前后端代码都将在该文件夹下进行
- 输入以下命令,安装 vue 框架
cnpm install vue-cli -g
vue init webpack "client" //建立一个名称为client的前端项目
cnpm install // 安装依赖
npm run dev
- 安装完毕之后,输入
npm run dev
,在浏览器输入http://localhost:8080/#
后显示以下界面,则 client 项目生成完毕!
1.2 后端开发环境
- 在
book-curd-example
下新建一个文件夹server
文件夹用于保存后端代码 - 进入
server
文件夹 - 安装
express
和其他模块
npm install express body-parser cors morgan nodemon mysql2 sequelize --save
- body-parser 解析
- cors 跨域
- morgan 日志记录
- nodemon 程序调试自启
- mysql2 mysql 数据库驱动管理工具
- sequelize mysql-ORM 工具
- 安装完成之后建立以下目录和文件
使用
npm init -f
生成一个package.json
文件修改为使用 nodemon 启动
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon server.js"
},
- 在
server.js
中写入以下代码用于测试,在server
文件夹下输入npm start
启动后台程序
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');
const app = express();
app.use(morgan('combined'));
app.use(bodyParser.json());
app.use(cors());
app.get('/posts', (req, res) => {
res.send([
{
title: 'Hello World!',
description: 'Hi there! How are you?'
}
]);
});
app.listen(process.env.PORT || 8081);
8.在浏览器中访问http://localhost:8081/posts
,显示以下画面,则后台环境搭建成功。
2 数据库设计和创建
2.1 数据库和表设计
- 数据库名称:book_curd_example
- 数据库表名称:book
2.2 book 表设计
字段 | 中文释义 | 类型 | 是否可为空 | 键 | 默认值 | 其他 |
---|---|---|---|---|---|---|
id | 书籍 id | int(10) unsigned | NO | 主键 | null | auto_increment |
isbn | isbn 编号 | varchar(20) | NO | null | ||
name | 书名 | varchar(50) | NO | null | ||
author | 作者 | varchar(30) | NO | null | ||
出版社 | varchar(50) | null | ||||
publish_time | 出版日期 | date | null | |||
intro | 简介 | varchar(255) | null | |||
remark | 备注 | varchar(200) | null |
2.3 sql 语句编写
DROP DATABASE IF EXISTS book_curd_example;
CREATE DATABASE book_curd_example;
use book_curd_example;
DROP TABLE IF EXISTS book;
CREATE TABLE IF NOT EXISTS `book`(
`id` INT UNSIGNED AUTO_INCREMENT COMMENT '书籍id',
`isbn` VARCHAR(20) NOT NULL COMMENT 'isbn编号',
`name` VARCHAR(50) NOT NULL COMMENT '书名',
`author` VARCHAR(30) NOT NULL COMMENT '作者',
`print` VARCHAR(50) COMMENT '出版社',
`publish_time` DATE COMMENT '出版日期',
`intro` VARCHAR(255) COMMENT '简介',
`remark` VARCHAR(200)COMMENT '备注',
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '图书信息表';
3 后台模块开发
3.1 创建数据库连接
- 创建
/server/config/env.js
文件
// 数据库连接参数
const env = {
database: 'book_curd_example',
username: 'root',
password: '123456',
host: 'localhost',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
};
module.exports = env;
- 创建
/server/config/db.config.js
文件
const env = require('./env.js');
const Sequelize = require('sequelize');
const sequelize = new Sequelize(env.database, env.username, env.password, {
host: env.host,
dialect: env.dialect,
operatorsAliases: false,
pool: {
max: env.max,
min: env.pool.min,
acquire: env.pool.acquire,
idle: env.pool.idle
}
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
// 引入表模型
db.book = require('../model/book.model.js')(sequelize, Sequelize);
module.exports = db;
3.2 创建表模型
- 安装
sequelize-auto
模块,利用sequelize-auto
模块自动生成 book 表模型
npm install -g sequelize-auto
sequelize-auto -h localhost -d book_curd_example -u root -x 123456 -p 3306 -t book
2.复制生成的/models/book.js
文件,粘贴至/model
目录下,并修改文件名为/model/book.model.js
,删除生成的models
目录
参考:Model definition - 模型定义 | sequelize-docs-Zh-CN
PS: 此处可能需要根据数据库字段的属性进行调整,比如自增属性
3.3 编写接口
- 创建
/server/route/book.route.js
文件,用来定义接口
// 图书的增删改查
module.exports = function(app) {
const book = require('../controller/book.controller');
// 新增图书信息
app.post('/book/add', book.create);
// 删除图书
app.delete('/book/delete/:bookId', book.delete);
// 根据id更新图书信息
app.put('/book/update/:bookId', book.update);
// 获取图书信息列表
app.get('/book/list', book.findAll);
// 根据Id查询图书信息
app.get('/book/:bookId', book.findById);
};
- 创建控制器文件
/server/controller/book.controller.js
const db = require('../config/db.config.js');
const Book = db.book; // 引入表模型
// 增加图书
exports.create = (req, res) => {
Book.create({
isbn: req.body.isbn,
name: req.body.name,
author: req.body.author,
print: req.body.print,
publish_time: req.body.publish_time,
intro: req.body.intro,
remark: req.body.remark
})
.then(book => {
let msg = {
code: 200,
msg: '新增成功!',
id: book.id
};
res.status(200).json(msg);
})
.catch(err => {
res.status(500).json('Error -> ' + err);
});
};
// 删除图书
exports.delete = (req, res) => {
const id = req.params.bookId;
Book.destroy({
where: { id: id }
})
.then(() => {
let msg = {
code: 200,
msg: '删除成功!'
};
res.status(200).json(msg);
})
.catch(err => {
res.status(500).json('Error -> ' + err);
});
};
// 更新图书信息
exports.update = (req, res) => {
const id = req.params.bookId;
Book.update(req.body, { where: { id: req.params.bookId } })
.then(() => {
let msg = {
code: 200,
msg: '修改信息成功!'
};
res.status(200).json(msg);
})
.catch(err => {
res.status(500).json('Error -> ' + err);
});
};
// 查询所有图书信息
exports.findAll = (req, res) => {
Book.findAll()
.then(book => {
res.json(book);
})
.catch(err => {
res.status(500).json('Error -> ' + err);
});
};
// 根据id查询图书信息
exports.findById = (req, res) => {
Book.findById(req.params.bookId)
.then(book => {
res.json(book);
})
.catch(err => {
res.status(500).book('Error -> ' + err);
});
};
- 修改
server.js
服务器文件
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const cors = require('cors');
const corsOptions = {
origin: 'http://localhost:8080',
optionSuccessStatus: 200
};
app.use(cors(corsOptions));
const morgan = require('morgan');
app.use(morgan('combined'));
const db = require('./config/db.config');
require('./route/book.route')(app);
// 创建服务器
let server = app.listen(process.env.PORT || 8081, () => {
let host = server.address().address;
let port = server.address().port;
console.log('服务器启动: http://%s:%s', host, port);
});
3.4 接口测试
使用postman
工具进行测试
新建 5 个接口进行测试
新增数据接口测试
删除数据接口测试
修改数据接口测试
查询所有数据接口测试
查询单个实体数据接口测试
4 前端模块开发
4.1 安装并引入前端开发所需外部模块
1.安装axios
模块
npm install axios --save
- 编写文件
/src/utils/http.js
,引入封装好的 axios 类
import axios from 'axios'
let httpInstance = axios.create()
httpInstance.defaults.baseURL = 'http://localhost:8081/'
httpInstance.defaults.timeout = 5000
httpInstance.formurl = (url, data, config) => {
return httpInstance.post(url, data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
...config
})
};
// request拦截器
httpInstance.interceptors.request.use(
config => {
console.log(config)
return config
},
error => {
return Promise.reject(error)
}
)
// reponse拦截器
httpInstance.interceptors.response.use(
response => {
if (response.status === 200) {
return Promise.resolve(response)
}
},
error => {
return Promise.reject(error)
}
)
export default httpInstance
- 在
main.js
中引入http.js
文件,并将其注册为 vue 全局变量
import http from './utils/http'
Vue.prototype.$http = http
- 安装
element-ui
模块
npm install element-ui --save
- 在
main.js
中引入element-ui
模块
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
4.2 建立路由
- 建立文件
在 components 下新建 3 个文件book-list.vue
、book-detail.vue
、book-add.vue
。删除原有的HelloWorld.vue
文件。 - 修改路由
在router/main.js
中将路由修改如下
import Vue from 'vue'
import Router from 'vue-router'
import BookList from '@/components/book-list'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'book-list',
component: BookList
}
]
})
- 删除
App.vue
文件中以下代码
<img src="./assets/logo.png">
- 在
book-list.vue
文件中写入以下代码
<template>
<div>
Hello World!
</div>
</template>
<script>
export default {}
</script>
<style scoped>
</style>
- 使用
npm start
运行项目,在浏览器中访问,则会出现Hello World
的文字
4.3 编写组件
book-list.vue
(1)效果图
(2) 代码
<template>
<div>
<header>图书列表</header>
<div class="container">
<div class="operate-btn">
<el-button @click="addBook">新增图书</el-button>
</div>
<el-table :data="tableData"
border
style="width: 100%">
<el-table-column type="index">
</el-table-column>
<el-table-column prop="name"
label="图书名称"
min-width="180px">
</el-table-column>
<el-table-column prop="isbn"
label="ISBN编号"
min-width="180px">
</el-table-column>
<el-table-column prop="author"
label="作者"
min-width="180px">
</el-table-column>
<el-table-column prop="print"
label="出版社"
min-width="180px">
</el-table-column>
<el-table-column prop="publish_time"
label="出版日期"
min-width="180px">
</el-table-column>
<el-table-column label="操作"
min-width="200px">
<template slot-scope="scope">
<el-button size="mini"
@click="handleDetail(scope.$index, scope.row)">查看</el-button>
<el-button size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<book-detail :bookId="bookId"
:visible="bookDetailVisible"
@closedDialog="closedDetailDialog">
</book-detail>
<book-add :visible="bookAddVisible"
@closedDialog="closeAddDialog"
@addNewBook="addNewBook">
</book-add>
</div>
</template>
<script>
import BookDetail from './book-detail';
import BookAdd from './book-add';
export default {
components: {
BookDetail,
BookAdd
},
mounted () {
this.getBookList()
},
data () {
return {
tableData: [],
bookId: null,
bookDetailVisible: false,
bookAddVisible: false
}
},
methods: {
addNewBook (val) {
this.bookId = val
this.bookDetailVisible = true
},
addBook () {
this.bookAddVisible = true
},
refreshBookList () {
this.getBookList()
},
closeAddDialog () {
this.bookAddVisible = false
this.refreshBookList()
},
closedDetailDialog () {
this.bookDetailVisible = false
this.refreshBookList()
},
handleDelete (index, row) {
this.$http
.delete(`/book/delete/${row.id}`)
.then(res => {
this.$message.success(res.data.msg)
this.refreshBookList()
})
.catch(err => {
console.log('err=>', err)
})
},
handleDetail (index, row) {
this.bookId = row.id
this.bookDetailVisible = true
},
getBookList () {
this.$http
.get('/book/list')
.then(res => {
this.tableData = res.data
})
.catch(err => {
console.log('err->', err)
})
}
}
}
</script>
<style scoped>
header {
font-size: 36px;
height: 60px;
padding-top: 30px;
padding-left: 40px;
box-shadow: 0px 15px 10px -15px #ccc;
margin-bottom: 10px;
}
.container {
text-align: center;
box-shadow: 0px -15px 10px -15px #ccc;
padding: 30px;
}
.el-table {
padding-top: 20px;
}
.operate-btn {
text-align: right;
margin-bottom: 10px;
}
</style>
book-add.vue
(1)效果图
(2)代码
<template>
<el-dialog :visible.sync="dialogVisible"
@closed="closedDialog"
min-width="360px">
<div slot="title">
<span class="title-name">
<span>新增图书</span>
</span>
</div>
<el-row>
<el-col :span="4">
<div class="label">名称</div>
</el-col>
<el-col :span="20">
<el-input v-model="bookInfo.name"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">ISBN编号</div>
</el-col>
<el-col :span="20">
<el-input v-model="bookInfo.isbn"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">作者</div>
</el-col>
<el-col :span="20">
<el-input v-model="bookInfo.author"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">出版社</div>
</el-col>
<el-col :span="20">
<el-input v-model="bookInfo.print"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">出版日期</div>
</el-col>
<el-col :span="20">
<el-date-picker v-model="bookInfo.publish_time"
type="date"
placeholder="选择日期"
size="medium">
</el-date-picker>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">简介</div>
</el-col>
<el-col :span="20">
<el-input type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入内容"
v-model="bookInfo.intro"
max-length="200">
</el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">其他</div>
</el-col>
<el-col :span="20">
<el-input type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入内容"
v-model="bookInfo.remark"
max-length="200">
</el-input>
</el-col>
</el-row>
<div slot="footer"
class="dialog-footer">
<el-button @click="cancelEdit"
size="medium">取 消</el-button>
<el-button type="primary"
@click="addBook"
size="medium">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
props: {
visible: {
type: Boolean
}
},
watch: {
visible: {
handler (newV, oldV) {
this.dialogVisible = newV
}
}
},
mounted () {},
data () {
return {
dialogVisible: false,
bookInfo: {}
}
},
methods: {
addBook () {
this.$http
.post('/book/add', this.bookInfo)
.then(res => {
this.$message.success(res.data.msg)
let bookId = res.data.id
setTimeout(() => {
this.$emit('addNewBook', bookId)
this.closedDialog()
}, 1000)
})
.catch(err => {
console.log('err=>', err)
})
},
cancelEdit () {
this.closedDialog()
},
resetData () {
this.dialogVisible = false
this.bookInfo = {}
},
closedDialog () {
this.$emit('closedDialog')
this.resetData()
}
}
}
</script>
<style scoped>
.el-row {
line-height: 40px;
margin-top: 10px;
}
.label {
font-weight: bold;
}
.edit-btn {
margin-left: 10px;
}
.title-name {
font-size: 30px;
}
.dialog-footer {
text-align: center;
}
</style>
book-detail.vue
(1)效果图
(2)代码
<template>
<el-dialog :visible.sync="dialogVisible"
@closed="closedDialog">
<div slot="title">
<span class="title-name">图书信息</span>
<el-button size="small"
icon="el-icon-edit"
round
class="edit-btn"
@click="editBookInfo">编辑</el-button>
</div>
<el-row>
<el-col :span="4">
<div class="label">名称</div>
</el-col>
<el-col :span="20">
<span v-if="!isEdit">{{bookInfo.name}}</span>
<el-input v-model="bookInfo.name"
v-if="isEdit"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">ISBN编号</div>
</el-col>
<el-col :span="20">
<span v-if="!isEdit">{{bookInfo.isbn}}</span>
<el-input v-if="isEdit"
v-model="bookInfo.isbn"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">作者</div>
</el-col>
<el-col :span="20">
<span v-if="!isEdit">{{bookInfo.author}}</span>
<el-input v-if="isEdit"
v-model="bookInfo.author"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">出版社</div>
</el-col>
<el-col :span="20">
<span v-if="!isEdit">{{bookInfo.print}}</span>
<el-input v-if="isEdit"
v-model="bookInfo.print"
size="medium"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">出版日期</div>
</el-col>
<el-col :span="20">
<span v-if="!isEdit">{{bookInfo.publish_time}}</span>
<el-date-picker v-if="isEdit"
v-model="bookInfo.publish_time"
type="date"
placeholder="选择日期"
size="medium">
</el-date-picker>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">简介</div>
</el-col>
<el-col :span="20">
<span v-if="!isEdit">{{bookInfo.intro}}</span>
<el-input v-if="isEdit"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入内容"
v-model="bookInfo.intro"
max-length="200">
</el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="4">
<div class="label">其他</div>
</el-col>
<el-col :span="20">
<span v-if="!isEdit">{{bookInfo.remark}}</span>
<el-input type="textarea"
v-if="isEdit"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入内容"
v-model="bookInfo.remark"
max-length="200">
</el-input>
</el-col>
</el-row>
<div slot="footer"
class="dialog-footer"
v-if="isEdit">
<el-button @click="cancelEdit"
size="medium">取 消</el-button>
<el-button type="primary"
@click="updateBookInfo"
size="medium">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
props: {
bookId: {
type: Number
},
visible: {
type: Boolean
}
},
watch: {
visible: {
handler (newV, oldV) {
this.dialogVisible = newV
if (this.dialogVisible) {
this.getBookById()
}
}
}
},
mounted () {},
data () {
return {
dialogVisible: false,
bookInfo: {},
isEdit: false
}
},
methods: {
refreshBookInfo () {
this.getBookById()
},
updateBookInfo () {
this.$http
.put(`/book/update/${this.bookId}`, this.bookInfo)
.then(res => {
console.log(this.$message)
this.$message.success(res.data.msg)
this.isEdit = false
this.refreshBookInfo()
})
.catch(err => {
console.log('err->', err)
this.isEdit = false
})
},
cancelEdit () {
this.isEdit = false
},
resetData () {
this.dialogVisible = false
this.bookInfo = {}
this.isEdit = false
},
closedDialog () {
this.$emit('closedDialog')
this.resetData()
},
getBookById () {
this.$http
.get(`/book/${this.bookId}`)
.then(res => {
this.bookInfo = res.data
})
.catch(err => {
console.log('err->', err)
})
},
editBookInfo () {
this.isEdit = true
}
}
}
</script>
<style scoped>
.el-row {
line-height: 40px;
margin-top: 10px;
}
.label {
font-weight: bold;
}
.edit-btn {
margin-left: 10px;
}
.title-name {
font-size: 30px;
}
.dialog-footer {
text-align: center;
}
</style>
Vue+node.js+express+mysql实例---对图书信息进行管理的更多相关文章
- 使用node.js抓取有路网图书信息(原创)
之前写过使用python抓取有路网图书信息,见http://www.cnblogs.com/dyf6372/p/3529703.html. 最近想学习一下Node.js,所以想试试手,比较一下http ...
- Node.js连接Mysql,并把连接集成进Express中间件中
引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...
- 前端使用node.js+express+mockjs+mysql实现简单服务端,2种方式模拟数据返回
今天,我教大家来搭建一个简单服务端 参考文章: https://www.jianshu.com/p/cb89d9ac635e https://www.cnblogs.com/jj-notes/p/66 ...
- 分享Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站
这是个什么的项目? 使用 Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站. 博客线上地址:www.boblog.com Github地址:https: ...
- 基于Vue+node.js的个人博客
前言 作为一个年轻的程序员,而且是作为一个未来的前端工程师,怎么能没有一个属于自己的博客呢,于是乎在暑假咸鱼了一个多月后开始了我的博客的编写. 技术栈 前端 vue.js+scss 因为当时没学vu ...
- Node.js Express 框架学习
转载:http://JavaScript.ruanyifeng.com/nodejs/express.html#toc0 感觉很牛的样子,不过觉得对初学者没太大用,里面很多例子用的api都没有详细的说 ...
- Node.js Express 框架
Node.js Express 框架 Express 简介 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP ...
- Windows下Node.js+Express+WebSocket 安装配置
Linux参考: Linux安装Node.js 使用Express搭建Web服务器 Node.js是一个Javascript运行环境(runtime).实际上它是对Google V8引擎进行了封装.V ...
- Node.js Express框架
Express 介绍 Express是一个最小的,灵活的Node.js Web应用程序框架,它提供了一套强大的功能来开发Web和移动应用程序. 它有助于基于Node Web应用程序的快速开发.下面是一 ...
随机推荐
- sql查询结果多对多转为一对多返回前端
企业表 ent_EnterpriseArchives 有id,企业名称 entName veh_Vehicle 车辆表,有所属企业id companyId,车辆id,车牌号licPlate 目的是 ...
- Datatable paging,Repeater with Paging
/// <summary> /// 塗聚文 /// 20140225 /// </summary> public partial class DatatablePage : S ...
- rest-framework框架——解析器、ur控制、分页、响应器、渲染器、版本
一.解析器(parser) 解析器在reqest.data取值的时候才执行. 对请求的数据进行解析:是针对请求体进行解析的.表示服务器可以解析的数据格式的种类. from rest_framework ...
- 洛谷P1966 火柴排队(逆序对)
题意 题目链接 Sol 不算很难的一道题 首先要保证权值最小,不难想到一种贪心策略,即把两个序列中rank相同的数放到同一个位置 证明也比较trivial.假设\(A\)中有两个元素\(a, b\), ...
- PHP连接MySQL数据库的几种方式
PHP 5 及以上版本建议使用以下方式连接 MySQL : MySQLi :MySQLi 只针对 MySQL 数据库,MySQLi 还提供了 API 接口. PDO (PHP Data Objects ...
- Android 判断当前Fragment是否可见(Visible)
判断当前Fragment是否可见 public abstract class BaseFragment extends Fragment { /** Fragment当前状态是否可见 */ prote ...
- 在一个服务中实现 多个契约 和终结点 z
一个服务作为一系列终结点被定义的.每个终结点都有一个地址,绑定和契约.契约就是暴露终结点能力的.地址就是这些应用或服务从网络的哪个地址可找到,契约是关于如何访问他们的. 在终结点和契约间有一对多的关系 ...
- Nginx+Tomcat+Session 高性能群集搭建
随着IT行业的发展,linux服务器在企业中应用广泛,人们对linux上的应用服务要求也越来越高,早先的apache服务器.apache有优点也 有不足,apache渐渐不能满足人们的要求,目前ngi ...
- 源码安装mysql5.6.37
MYSQL 源码安装: 修改参数文件:vi /etc/security/limits.confmysql soft nproc 2047mysql hard nproc 16384mysql soft ...
- CSS基础语法(一) CSS的3种引入
CSS样式表 CSS可算是网页设计的一个突破,它解决了网页界面排版的难题.可以这么说,HTML的Tag主要是定义网页的内容(Content),而CSS决定这些网页内容如何显示(Layout). Web ...