程序生成器express-generator

项目开发:(这是一种规范)
1. 开发环境 dev(development) : npm run dev
2. 生产环境 build(production): npm run build
3. 测试环境 test(test): npm run test (了解, 后期专门的测试工具, 测试岗位)

express-generator作用

通过应用生成器工具 express-generator 可以快速创建一个应用的骨架

安装(全局安装)

npm i express-generator -g

(全局安装后,在这台电脑就不用重复输入这个命令)
安装完成后,可以使用 express 命令 搭建项目; 会自动生成一个项目结构

//  语法规则
express 模板引擎 项目名称
//  案例
express -e myapp

这里的-e指的是ejs模板引擎的简写
接着按照它的指示操作
在这里插入图片描述

cd myapp

安装依赖

npm install 
npm i (简写)

运行项目是如下

npm run start

会生成如下一个文件夹
在这里插入图片描述
如果还需要什么插件可以后续在下载 npm i 包名 --save

局部安装 nodemon 热更新

  1. 安装
npm i nodemon --save
  1. 安装完成,需要配置 启动命令, 在package.json文件中的“scripts”字段中配置启动命令
"scripts":{
    
    
   "dev":"nodemon ./bin/www"
}
  1. 配置完成后可以使用 npm run dev 启动服务

功能介绍
在这里插入图片描述

使用步骤

首先引入路由配置文件,进行路由匹配
app.js文件是一个总页面是顶级路由,可以在里面引入你需要的页面
浙江仓库去笨哦了
req是客户端向服务器(黑窗口)请求
res是服务器(黑窗口)像客户端进行响应
next是放行
var router = express.Router();创建一个路由容器
在这里插入图片描述
res.render(' ejs模板引擎名')会进入这个模板名的ejs文件
(这里res.send()方法是服务器像客户端响应的数据)

在这里插入图片描述

这样就完成了一个基础的运行机制(这是一个对一个模块的导出.app.use中,routes文件夹有几个js文件就引入了几次)
可以在ejs模板引擎中书写主体,这是前后端不分离的做法

二级路由

引入:如果我们在list.js文件下在建立一个admin路由,就要这样访问,相当于二级路由
http://localhost:3000/list/admin

在这里插入图片描述在这里插入图片描述

在这里插入图片描述
只有index.js文件夹中的路由是可以直接匹配使用,除了index.js以外的路由模块中的路由都需要和app.js中的路由进行拼接使用

练习:用post请求获取到用户输入的账户,密码

app.js部分 引入路由配置文件

var listRouter = require('./routes/login');
app.use('/login', loginRouter);

ejs部分
小知识:当你直接就在自己本项目请求的,就不用写http://localhost:3000,可以直接写你的路由地址/login/dologin
当然你如果写完整,也不会出错

 url: 'http://localhost:3000/login/dologin',
<body>
    <p class="err"></p>
    <p>
        <input type="text" name="user" class="user">
    </p>
    <p>
        <input type="password" name="pwd" class="pwd">
    </p>
    <p>
        <button>登录</button>
    </p>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script>
        $('button').click(function() {
    
    
            $.ajax({
    
    
                url: 'login/dologin',
                type: 'post',
                data: {
    
    
                    user: $('.user').val(),
                    pwd: $('.pwd').val(),
                },
                success: function(data) {
    
    
                    console.log(data);
                    if (data.code == 400) {
    
    
                        $('.err').text(data.message)
                    } else if (data.code == 200) {
    
    
                        console.log(data);
                        //  存储用户信息
                        localStorage.setItem('user', data.data.name)
                            //  页面重定向                        
                        location.href = '/'
                    }
                }
            })
        })
    </script>

二级路由部分

因为从连接池传过来的query(数据库)是一个promise对象,所以它有then方法

var express = require('express');
 const query = require('../utils/query')
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
    
    
  res.render('login');
});


//  next 放行
router.post('/dologin', (req, res, next) => {
    
    
    console.log(req.body);
    let {
    
    user, pwd} = req.body;
    query('select * from admin where name = ? and pwd = ?', [user, pwd]).then(data => {
    
    
        if(data.length){
    
    
            delete data[0].pwd
            res.send({
    
    
                code:200,
                message:'登录成功',
                data:data[0]
            })
        }else{
    
    
            res.send({
    
    
                code:400,
                message:'用户名或密码错误',
                data:[]
            })
        }
    })
    
})

module.exports = router;

在这里插入图片描述

使用 console.log(req.body); //将用户信息输出到控制台
在这里插入图片描述
对后端如何使用数据库连接池的解释
在这里插入图片描述

路由模块封装

解决二级路由的嵌套

这样就不用在app.js里面多次引入路由配置文件
在这里插入图片描述打开服务器后
可以通过api来测试接口是否畅通

在这里插入图片描述
请求的地址,是什么就写完整,然后输出就好了

数据库连接池

对数据库的封装
通常会在app.js同级文件夹下建一个utils文件夹里面放query.js文件,这是一种规范,不是必须的

本来可以连接10个 connectionLimit: 10,下面释放资源的目的connection.release()是让别人还可以继续使用连接

const mysql = require('mysql');
//  创建连接池
const pool = mysql.createPool({
    
    
    host: 'localhost',
    user: 'root',
    password: 'root',
    database: 'yunmeng',
    connectionLimit: 10
})

module.exports = (sql, value = []) => {
    
    
    return new Promise((resolve, reject) => {
    
    
        //  从连接池中获取连接
        pool.getConnection((err, connection) => {
    
    
            if (err) {
    
    
                reject(err);
                throw err;
            }
            //  连接成功 执行查询
            connection.query(sql, value, (err, result) => {
    
    
                //  立刻释放资源(连接)
                connection.release()
                if (err) {
    
    
                    reject(err);
                    throw err;
                }
                //  sql执行成功
                resolve(result)
            })
        })
    })
}

这是没学连接池前的写法
数据库模块讲过query方法可以执行数据库的增删改查

module.exports = (sql, value = []) => {
    
    
   return new Promise((resolve, reject) => {
    
    
        pool.query(sql, value, (err, result) => {
    
    
         if (err) {
    
    
             reject(err);
              throw err;
       }
          resolve(result)
       })
    })
}

不论哪种写法;在用到数据库的地方都要引入模块
(自定义的·模块引用时需要加点斜杠,内置模块和第三方模块引入时,直接引入名字

const query = require('../utils/query')

实例:服务端(后端)实现分页请求步骤

首先是服务端把页分好,然后把数据传到客户端,下面是初步的想法
在这里插入图片描述
currentPage可以返回当前页码

currentPage: page  

后端

var express = require('express');
const query = require('../utils/query');
var router = express.Router();
/* GET home page. */
router.get('/', async function(req, res, next) {
    
    
    //请求第一页的1页的数据
    let {
    
     page = 1 } = req.query;
    let length = 10;
    //总数据条数
    let total_sql = 'select * from t_order'
    let pageNum = await query(total_sql);
    // console.log(pageNum);输出所有的数据完整的
    //换算一共显示多少页
    let num = Math.ceil(pageNum.length / length)
    console.log(num);
    let sql = `select * from t_order limit ${
      
      (page-1)*length},${
      
      length}`
    let datalist = await query(sql);
    // console.log(datalist);
    res.render('index', {
    
     data: datalist, pageNum: num, currentPage: page });
});
module.exports = router;

数据库

const mysql = require('mysql');
//创建连接池
const pool = mysql.createPool({
    
    
    host: 'localhost',
    user: 'root',
    password: 'root',
    database: 'yunmeng',
    connectionLimit: 10
})

module.exports = (sql, value = []) => {
    
    
    //执行成功调用resolve.执行失败调用reject
    return new Promise((resolve, reject) => {
    
    
        //  从连接池中获取连接
        pool.getConnection((err, connection) => {
    
    
            if (err) {
    
    
                reject(err);
                throw err;
            }
            //  连接成功 执行查询
            connection.query(sql, value, (err, result) => {
    
    
                //  立刻释放资源(连接)
                connection.release()
                if (err) {
    
    
                    reject(err);
                    throw err;
                }
                //  sql执行成功
                resolve(result)
            })
        })
    })
}

//旧写法
// const mysql = require('mysql');

// const conn = mysql.createConnection({
    
    
//     host: 'localhost',
//     user: 'root',
//     password: 'root',
//     database: 'yunmeng'
// })

// module.exports = (sql, value = []) => {
    
    
//     return new Promise((resolve, reject) => {
    
    
//         conn.query(sql, value, (err, result) => {
    
    
//             if (err) {
    
    
//                 reject(err);
//                 throw err;
//             }
//             resolve(result)
//         })
//     })
// }

ejs模板

<style>
    .pagebean a {
    
    
        font-size: 20px;
        color: #333;
        float: left;
        padding: 10px;
        border: 1px solid #333;
        margin: 5px;
        text-decoration: none;
    }
    
    .pagebean .active {
    
    
        color: red;
        border-color: red;
    }
</style>

<body>
    <!-- 页面首次加载,渲染第一页数据 -->
    <div class="wrap">
        <ul>
            <% data.forEach((item,index)=>{
    
    %>
                <li>
                    <p>
                        作者:
                        <%= item.title%>
                    </p>
                    <p>
                        类型:
                        <%= item.classify%>
                    </p>
                </li>
                <%  })%>

        </ul>
    </div>
    <div class="pagebean">
        <!-- 页面数量 分页按钮的数量(根据数据库内容的条数来定) -->
        <% for(let i = 0;i<pageNum;i++) {
    
    %>
            <a href="/?page=<%= (i + 1)%>" class="<%= currentPage == (i+1)?'active':''%>">
                <%= (i+1)%>
            </a>
            <% }%>
    </div>

</body>

这样就从服务端完成了分页请求
补充:
如果ejs模板需要引入外部的样式css
就在public里面的stylesheets里面新建css样式文件
使用时不需要加…/public前缀,加了会链接不上
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/z18237613052/article/details/115092982