教程.NodeJS的常见用法

代码实例

操作数据库

综合示例如下,设备管理系统(DMS),可以实现通过NodeJS连接MySQL数据库,实现接口,并且可跨域,然后读取到前端页面上。


数据库

使用MySQL数据库,信息如下:

host: 'localhost',
user: 'root',
password: '123456',
database: 'test'

创建 device 表,包含三个字段:id,name,note


前端

html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script>
    <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.12/index.js"></script>
    <script src="https://cdn.bootcss.com/qs/6.5.1/qs.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"></script>

    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>

<body>
    <div id="app">
        <template>
            <el-card class="box-card membersTab">
                <!-- 查询 -->
                <div style="margin-bottom: 40px;">
                    <el-button @click="getData(input)" style="display: inline-block;" type="primary">查询</el-button>
                    <el-input style="width: 60%;" v-model="input" placeholder="请输入内容"></el-input>
                </div>
                <!-- 新增 -->
                <div style="margin-bottom: 40px;">
                    <el-button type="success" @click="handleInsert(id,name,note)">新增</el-button>
                    <el-input style="width: 20%;" v-model="id" placeholder="请输入id"></el-input>
                    <el-input style="width: 20%;" v-model="name" placeholder="请输入name"></el-input>
                    <el-input style="width: 20%;" v-model="note" placeholder="请输入note"></el-input>
                </div>

                <el-divider></el-divider>

                <!-- 数据表格 -->
                <el-table
                    :data="tableData.slice((pageSettings.currentPage-1)*pageSettings.PageSize,pageSettings.currentPage*pageSettings.PageSize)"
                    stripe style="width: 100%" @sort-change="sortChange">
                    <el-table-column label="id" width="180" sortable prop="id"></el-table-column>
                    <el-table-column label="name" width="180" sortable prop="name"></el-table-column>
                    <el-table-column label="note" width="180" sortable prop="note"></el-table-column>
                    <el-table-column label="操作">
                        <template slot-scope="scope">
                            <el-button size="mini" type="danger" @click="handleDelete(scope)">删除</el-button>
                            <el-button size="mini" type="warning" @click="btn_edit(scope)">编辑</el-button>
                        </template>
                    </el-table-column>
                </el-table>
                <div class="tabListPage">
                    <el-pagination small @size-change="handleSizeChange" @current-change="handleCurrentChange"
                        :current-page="pageSettings.currentPage" :page-sizes="pageSettings.pageSizes"
                        :page-size="pageSettings.PageSize" layout="total, sizes, prev, pager, next, jumper"
                        :total="pageSettings.totalCount">
                    </el-pagination>
                </div>

                <!-- 编辑表单 -->
                <el-dialog title="修改信息" :visible.sync="dialogFormVisible">
                    <el-form :model="form">
                        <el-form-item label="ID" :label-width="formLabelWidth">
                            <el-input v-model="form.id" autocomplete="off"></el-input>
                        </el-form-item>
                        <el-form-item label="NAME" :label-width="formLabelWidth">
                            <el-input v-model="form.name" autocomplete="off"></el-input>
                        </el-form-item>
                        <el-form-item label="NOTE" :label-width="formLabelWidth">
                            <el-input v-model="form.note" autocomplete="off"></el-input>
                        </el-form-item>
                    </el-form>
                    <div slot="footer" class="dialog-footer">
                        <el-button @click="dialogFormVisible = false">取 消</el-button>
                        <el-button type="primary" @click="handleUpdate(form)">确 定</el-button>
                    </div>
                </el-dialog>
            </el-card>
        </template>
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            data() {
                return {
                    input: '',
                    id: '',
                    name: '',
                    note: '',
                    pre_params: '',
                    dialogFormVisible: false,
                    formLabelWidth: '120px',
                    form: {},
                    tableData: [],

                    // 分页配置
                    pageSettings: {
                        // 分页配置
                        // 默认显示第几页
                        currentPage: 1,
                        // 总条数,根据接口获取数据长度(注意:这里不能为空)
                        totalCount: 1,
                        // 个数选择器(可修改)
                        pageSizes: [3, 5, 10, 20],
                        // 默认每页显示的条数(可修改)
                        PageSize: 10,
                    },
                }
            },
            mounted() {
                this.getData()
            },
            methods: {
                // 实现全页面排序
                sortChange({ prop, order }) {
                    this.tableData.sort(this.compare(prop, order));
                },
                sortChange(column) {
                    this.pageIndex = 1; // 排序后返回第一页
                    if (column.order === "descending") {
                        this.tableData.sort((a, b) => b[column.prop] - a[column.prop]);
                    } else if (column.order === "ascending") {
                        this.tableData.sort((a, b) => a[column.prop] - b[column.prop]);
                    }
                },

                // 查询
                getData() {
                    let that = this;

                    axios({
                        method: 'get',
                        url: 'http://localhost:8888/query',
                        params: {
                            name: that.input
                        }
                    }).then(
                        function (res) {
                            that.tableData = res.data;
                            console.log(that.tableData);

                            // 判断如果存在返回值,则将当前页改为1,否则无法显示内容
                            if (that.tableData.length > 0) {
                                that.pageSettings.currentPage = 1
                            }

                            // 将数据的长度赋值给totalCount
                            that.pageSettings.totalCount = that.tableData.length
                        }
                    ).catch(err => console.log(err))
                },

                // 功能_新增
                handleInsert(param) {
                    let that = this;

                    axios({
                        method: 'post',
                        url: 'http://localhost:8888/insert',
                        data: Qs.stringify({
                            id: that.id,
                            name: that.name,
                            note: that.note
                        })
                    }).then(
                        function (res) {
                            that.getData();
                            console.log(res);
                        }
                    ).catch(err => console.log(err));
                },

                // 功能_删除
                handleDelete(param) {
                    let that = this;

                    axios({
                        method: 'post',
                        url: 'http://localhost:8888/delete',
                        data: Qs.stringify({
                            id: param.row.id
                        })
                    }).then(
                        function (res) {
                            that.getData();
                            console.log(res.data);
                        }
                    ).catch(err => console.log(err));
                },

                // 功能_修改
                btn_edit(params) {
                    this.dialogFormVisible = true;
                    pre_params = params.row;
                    console.log(pre_params);

                    // 将被编辑行的原数据带入到编辑表单
                    this.form = {
                        id: pre_params.id,
                        name: pre_params.name,
                        note: pre_params.note
                    }
                },
                handleUpdate(params) {
                    let that = this;
                    console.log(params);

                    axios({
                        method: 'post',
                        url: 'http://localhost:8888/update',
                        data: Qs.stringify({
                            id: params.id,
                            name: params.name,
                            note: params.note,
                            pre_params: pre_params
                        })
                    }).then(
                        function (res) {
                            that.getData();
                            console.log(res.data);
                        }
                    ).catch(err => console.log(err));

                    this.dialogFormVisible = false;
                },

                // 分页
                // 每页显示的条数
                handleSizeChange(val) {
                    // 改变每页显示的条数 
                    this.pageSettings.PageSize = val
                    // 注意:在改变每页显示的条数时,要将页码显示到第一页
                    this.pageSettings.currentPage = 1
                },
                // 显示第几页
                handleCurrentChange(val) {
                    // 改变默认的页数
                    this.pageSettings.currentPage = val
                }
            }
        })
    </script>
    <style lang="">
        .membersTab {
            width: 800px;
            margin: 20px auto;
        }
    </style>
</body>

</html>

后端

js

// 使用expres框架,并创建应用
var express = require('express')
const app = express()

// 解决跨域请求
app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By", ' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

// 使用bodyParser中间件
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
    extended: true
}));

// 使用连接池,连接数据库
var mysql = require("mysql");
var pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: '123456',
    database: 'test'
});

// DMS.新增
app.post('/insert', (req, res) => {
    console.log('-------------------START INSERT---------------------');
    console.log(req.body);
    const sql = `insert into device(id,name,note) values('${req.body.id}','${req.body.name}','${req.body.note}')`;
    console.log(sql);

    pool.query(sql, (err, data) => {
        if (err) {
            console.log(err);
            res.send(err)
        } else {
            res.send(data)
        }
    })
    console.log('-------------------END INSERT---------------------');
})

// DMS.删除
app.post('/delete', (req, res) => {
    console.log('-------------------START DELETE---------------------');
    console.log(req.body);
    // 删除数据
    const sql = `delete from device where id = '${req.body.id}'`
    console.log(sql);

    pool.query(sql, (err, data) => {
        if (err) {
            console.log(err);
            res.send(err)
        } else {
            res.send(data)
        }
    })
    console.log('-------------------END DELETE---------------------');
})

// DMS.修改
app.post('/update', (req, res) => {
    console.log('-------------------START UPDATE---------------------');
    console.log(req.body);

    // 删除数据
    const sql = `update device set id = '${req.body.id}', name = '${req.body.name}', note = '${req.body.note}' where id = '${req.body.pre_params.id}'`
    console.log(sql);

    pool.query(sql, (err, data) => {
        if (err) {
            console.log(err);
            res.send(err)
        } else {
            res.send(data)
        }
    })
    console.log('-------------------END UPDATE---------------------');
})

// DMS.查询
app.get('/query', (req, res) => {
    console.log('-------------------START QUERY---------------------');
    console.log(req.query.name);

    // 判断输入框是否为空
    if (req.query.name == '' || req.query.name == undefined) {
        var sql = 'select * from device order by id'
    } else {
        // 可改为模糊查询
        // var sql = `select * from device where name = '${req.query.name}' order by id`
        var sql = `select * from device where name like '%${req.query.name}%' order by id`
    }
    console.log(sql);

    pool.getConnection((err, connection) => {
        connection.query(sql, function (err, data) {
            console.log(data)
            if (err) {
                console.log(err);
                return;
            }
            res.send(data)

            //释放连接
            connection.release();
            console.log('-------------------END QUERY---------------------');
        });
    });
})



// 端口必须要监听
app.listen(8888, () => {
    console.log("http://localhost:8888")
})



读取本地文件

// api请求:
// method: "get",
// url: "http://localhost:8081/query",
// params: {
//     filename: "input.txt",
// },

// 使用expres框架,并创建应用
const express = require('express');
const app = express();
const fs = require('fs');

// cors解决跨域问题
const cors = require('cors');
app.use(cors());

// 使用bodyParser中间件
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
    extended: true
}));

// 查询
app.get('/query', (req, res) => {
    var filename = req.query.filename;
    console.log(filename);

    // 规定格式:fs.readFile(filename, 'utf-8', (err, data) => {}),如果不指定'utf-8'将解析错误。
    fs.readFile(filename, 'utf-8', (err, data) => {
        if (err) {
            console.log(err);
            res.send(err);
        } else {
            console.log(data);
            res.send(data)
        }
    });
})

// 端口必须要监听
app.listen(8080, () => {
    console.log("http://localhost:8080")
})



常见问题处理

跨域问题

使用cors跨域

const cors = require('cors');
app.use(cors());

手动配置

首先,需要定义app,通过express框架

var express = require('express')
const app = express()

解决跨域接收请求

//设置跨域请求
app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By", ' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

解决跨域返回

// 使用中间件 允许跨域
// app.use(path,中间件函数)
app.use('/', (req, res, next) => {
    // 注意, 需要带 '*'
    res.set('Access-Control-Allow-Origin', '*');        
    next();
});


异步等待

即promise()函数的 async / await 用法。

await必须用在async标记的函数内部。

使用示例如下:

async function write() {
    console.log(1);
    
    // 写法1
    // await new Promise(function(resolve, reject) {
    //     setTimeout(function() {
    //         console.log(2);
    //         resolve(0);
    //     }, 2000);
    // });
    
    // 写法2
    var res = await new Promise((resolve, reject) => {
        setInterval(() => {
            resolve(2)
        }, 1000);
    })
    console.log(res);
    
    console.log(3);
}

write()
// 输出结果:
// 1
// 2 (1s后执行)
// 3

正常情况依次打印三个数字,由于2被设置了延时,所以应该最后打印2。

但是在使用了 async / await 之后,函数执行顺序必须等待打印2完成后才会执行后续。



res的各方法之间的区别

res.wirte()

必须和res.end()成对出现

res.write() 负责向前端返回数据,res.end() 负责结束请求。如果没有 res.end(),浏览器将会一直处于请求状态。

数据不做处理,原封不动返回

res.write()的返回数据是没有经过处理的,原封不动的返回原数据,所见即所得。

在结束浏览器响应请求之前,允许多次调用

使用 res.write() 可以输出多条语句,即在res.end() 之前可以执行多次,且返回的数据会被拼接到一起。

只允许输出字符串类型和Buffer对象两种数据类型

例如,如果输出数字则会报错。


res.send()

数据会被处理

会自动发送更多的响应报文头,包括返回数据类型,所以不会有乱码。

只允许调用一次

即等同于 res.write() + res.end()

支持多种内容格式

允许String、Array、Buffer对象、对象、json等。


res.json()

同 res.send(),响应结果都是json。



解析参数失败

引入 body-parser 模块,作为中间件

var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
    extended: true
}));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值