Node学习(三)

此文转载自:https://blog.csdn.net/javaScript1997/article/details/112428777#commentBox

一、开发模式

MVC+MPA(koa art-template)+ssr
SPA(vue react) MPA(koa art-template)
SPA(vue react) — > 接口

1.1MVC

在这里插入图片描述

1.2入门案例

(一)入口文件

const Koa = require('koa');
const app = new Koa;
const path = require('path');
const render = require('koa-art-template'); 

//模板引擎
render(app,{
    root:path.join(__dirname,'views'),
    extname:'.html',
});

//开启路由
require('./controller')(app);

//监听
app.listen(8080,() => {
    console.log('=====>>>','index running...');
})

(二)controller控制层

//处理数据的路由
const router = require('koa-simple-router');
const model = require('../models');

let controller = (app) => {
    app.use(router(_ => {
        _.get('/', (ctx, next) => {
          ctx.render('view')
        })
    
        //get art-template
        _.get('/index1', async (ctx, next) => {
            let data = await model.db()
            
            ctx.render('index1',{data})
        })

        _.get('/index2', async (ctx, next) => {
            let data = await model.db1()
            
            ctx.render('index2',{data})
        })
    }))
}
module.exports = controller

(三)models模型层

let data = {
    db: () => {
        return Promise.resolve('假装这是从数据库获取的数据库');
    },
    db1: () => {
        return Promise.resolve('哈哈哈');
    }
}
module.exports = data;

(四)view视图层
index1.html和index2.html一样

<body>
    <h1>{{data}}</h1>
</body>

二、项目架构搭建

1、项目搭建

(一)首先初始化–npm init -y
(二)创建文件夹assets、components、config、controllers、models、views
(三)使用到Koa框架,先安装–npm i koa -S

2、入口文件

(一)创建app.js入口文件

const Koa = require('koa');
const app = new Koa();
//监听
app.listen(8080,() => {
    console.log(' =====>','server running 8080 ...')
})

(二)在package.json中的"scripts"中加入
在这里插入图片描述

3、注册路由

(一)使用koa-simple-router路由
①npm install koa-simple-router
②在controller文件夹下创建index.js和indexControllers.js
③index.js并在其中导入官网用法
在这里插入图片描述
④indexControllers.js中创建类

//创建一个类
class IndexController {
    constructor(){}
    //方法
    index(){
        return (ctx, next) => {
            ctx.body = 'hello word'
        }
    }
}

//导出
module.exports = IndexController;

⑤是index.js中接收并优化代码

const router = require('koa-simple-router')
 
//导入
const IndexController = require('./indexControllers.js');
//对类进行实例
const indexController = new IndexController();

//导出
module.exports = (app) => {
    app.use(router(_ => {
        _.get('/', indexController.index())
    }))
}

⑥在入门文件app.js中开启路由

/开启路由
require('./controllers')(app)

注: 在npm官网搜索需要的路由,并使用给的用法

4、模板配置

(一)安装npm install --save art-template koa-art-template
(二)在app.js中

//模板引擎
const render = require('koa-art-template');
render(app, {
  root: path.join(__dirname, 'views'),
  extname: '.html',
});

(三)在views中创建index.html和layout.html文件【内容从官网copy】
官网地址

5、静态资源

(一)在assets下css中创建index.css和scripts中创建index.js
(二)安装npm install koa-static

const serve = require('koa-static');
//静态文件
app.use(serve(path.join(__dirname, 'assets')));

(三)在控制类IndexController中index()方法

return async function (ctx) {
    await ctx.render('index');
}

(四)在index.html文件中引入对应的css和js
(五)在layout.html模板文件中引入vue,并在index.html中写

	<div id="app">
        <h2>${message}</h2>
        <input type="text" v-model="message">
    </div>

(六)在index.js中处理vue
注意:如果在Vue中没有设置delimiters:[’${’,’}’]的话,页面{{message}}会冲突

new Vue({
    el:'#app',
    data:{
        message:'hello koa'
    },
    delimiters:['${','}']
})

6、错误处理

(一)创建middlewares文件夹并创建index.js

const middlewares = {
    error(app){
        app.use(async(ctx,next) => {
            try{
                await next();
            }catch(err){
                console.log(err);
                ctx.status = 500;
                ctx.body = "程序员好像出错了,请与程序员小哥联系!!!"
            } 
        })
        app.use(async(ctx,next) => {
            await next();
            if(ctx.status != 404) return;

            ctx.status = 404;
            ctx.body = `<script type="text/javascript" src="//qzonestyle.gtimg.cn/qzone/hybrid/app/404/search_children.js" charset="utf-8"></script>`
        })
    }
}
module.exports = middlewares;

(二)在app.js中

//错误处理
require('./middlewares').error(app)

7、错误日志

(一)在npm官网搜log4js并npm install log4js安装
(二)在入门文件app.js中

/* 
    记录错误的日志
*/
const log4js = require("log4js");

log4js.configure({
  //appenders输出目的地
  appenders: { cheese: { type: "file", filename: "logs/cheese.log" } },
  //categories类别
  categories: { default: { appenders: ["cheese"], level: "error" } }
});
 
const logger = log4js.getLogger("cheese");
// logger.error("Cheese is too ripe!");

(三)将logger传入错误处理中
(四)在错误处理文件index.js中

logger.error(err);

8、配置外依

(一)使用lodash工具库–先安装npm i --save lodash

//lodash工具库
const _ = require('lodash');

const path = require('path');

let config = {
    "staticDir":path.join(__dirname,'..','assets'),
    "templatesDir":path.join(__dirname,'..','views')
}

if(process.env.NODE_ENV == 'development'){
    let localPort = {
        port:8080
    };
    _.assignIn(config,localPort);
}
if(process.env.NODE_ENV == 'production'){
    let prodPort = {
        port:80
    };
    _.assignIn(config,prodPort);
}
module.exports = config;

(二)在app.js中导入const config = require(’./config’)并修改相关
(三)但是仍然无法访问,原因是如法进入if中判断是否为开发或者生产模式,解决方法使用新的cross-env
cross-env这是一款运行跨平台设置和使用环境变量的脚本。
①npm install --save-dev cross-env
②修改package.json文件中
在这里插入图片描述

三、图书馆案例修改功能展示[基于上面的配置]

使用模态框进行前端渲染,使用ajax处理逻辑,后台controller处理数据;

3.1主页面

解析: ①此处首先引入bootstrap、toastr、template、vue、jQuery
②引入模板和模态框
③引入自己的index.js文件

此处使用了模态框和模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>主页面</title>
    <link rel="stylesheet" href="./css/admin.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
    <!-- 提示框样式 -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet" />
</head>
<body>
    <div class="wrapper">
        <h1>six 图书馆管理系统</h1>
        <a class="btn btn-default" href="#" id="add">添加图书</a>
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>书名</th>
                    <th>作者</th>
                    <th>分类</th>
                    <th>描述</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody id="tbody"></tbody>
        </table>       
    </div>
    <!-- 模态框 -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">

                <!-- == 模态框内容 ==================== -->

                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                            aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="myModalLabel">新增</h4>
                </div>

                <div class="modal-body">

                    <form id="form">
                        <div class="form-group">
                            <label for="txt_departmentname">书名</label>
                            <input type="text" name="name" class="form-control" id="txt_departmentname"
                                placeholder="书名">
                        </div>
                        <div class="form-group">
                            <label for="txt_parentdepartment">作者</label>
                            <input type="text" name="author" class="form-control" id="txt_parentdepartment"
                                placeholder="作者">
                        </div>
                        <div class="form-group">
                            <label for="txt_departmentlevel">分类</label>
                            <input type="text" name="category" class="form-control" id="txt_departmentlevel"
                                placeholder="分类">
                        </div>
                        <div class="form-group">
                            <label for="txt_statu">描述</label>
                            <input type="text" name="description" class="form-control" id="txt_statu" placeholder="状态">
                        </div>
                    </form>
                    
                </div>

                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal"><span
                            class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
                    <!-- <button type="button" id="btn_submit" class="btn btn-primary" data-dismiss="modal"><span
                            class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>保存</button> -->
                    <button type="button" id="btn_submit" class="btn btn-primary"><span
                            class="glyphicon glyphicon-floppy-disk"></span>提交</button>
                </div>

                <!-- == 模态框内容 ==================== -->
            </div>
        </div>
    </div>

    <!-- 模板 -->
    <script type="text/template" id="template">
        {{each data}}
            <tr>
                <td>{{$value.id}}</td>
                <td>{{$value.name}}</td>
                <td>{{$value.author}}</td>
                <td>{{$value.category}}</td>
                <td>{{$value.description}}</td>
                <td class="edit">
                    <a href="javascript:;">修改</a> |
                    <a href="javascript:;">删除</a>
                </td>
            </tr>
        {{/each}}
    </script>
    
    <!-- vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <!-- jQuery.js -->
    <script src="/js/jquery-3.5.1.js"></script>
    <!-- art-template -->
    <script src="https://cdn.staticfile.org/art-template/4.10.0/lib/template-web.min.js"></script>
    <!-- bootstrap.js -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    <!-- 提示框 js -->  
    <!-- https://codeseven.github.io/toastr/ -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
    <!--  -->
    <script src="/js/index.js"></script>
</body>
</html>

3.2在controller中index.js下

const router = require('koa-simple-router')

const controllers = require('./indexController');
const contro = new controllers();

let controller = (app) => {
    app.use(router(_ => {
        _.get('/',contro.index())
        //伪静态
        _.get('/index',contro.index())
        //获取图书
        _.get('/admin',contro.adminindex())
        //添加图书页
        _.get('/addpage',contro.actionAddPage())
        _.post('/add',contro.actionAdd())
        //修改编辑图书
        _.get('/editpage',contro.actionEditpage())
        _.post('/edit',contro.actionEdit())
        //删除图书
        _.get('/delete',contro.deleteEdit())    
    }))
}
module.exports = controller;

3.3在controller中indexController.js下

对对应访问的路径进行处理

let SafeRequest = require('../models');
let safeRequest = new SafeRequest(); 

class contributors{
    constructor(){}

    index(){
        // return(ctx, next) => {
        //    ctx.body = 'hello world'
        // }
        let data = '图书馆案例!!!'
        return async function (ctx) {
            await ctx.render('index',{
                data
            });
        }
    }
    //获取图书
    adminindex(){
        return async function (ctx) {
            let msg = await safeRequest.getData();

            //要前端渲染  将msg传给页面
            ctx.body = msg;
            
            // ctx.render('admin',{
            //     data:msg
            // });
        }
    }
    //完成修改
    actionEdit(){
        return async function (ctx) {
            
            try{
                let msg = await safeRequest.editData(ctx.request.body)
                //返回数据
                ctx.body = msg;
                // console.log('msg',msg);
                // ctx.redirect('/admin');
            }catch(err){
                console.log('err',err);
            }
        }
    }
    
}
module.exports = contributors;

3.4在models中index.js数据库处理下

处理完后,将数据返回给controller,controller将数据返回给前端index.js进行渲染;

// let data = require("../data.json");
const path = require("path");
const fs = require("fs");
const db = require("./db_promise")

class SafeRequest{
    constructor(){}
    //获取数据
    getData(){
        return db.query("SELECT * FROM t_book");
        // return new Promise((resolve,reject) => {
        //     resolve(data);
        // })
    }
    async editData(opt) {
        // console.log(opt);
        let result = {
            code:0,
            message:'',
            data:[]
        }
        try{
            let data = await db.query(`update t_book set name=?,author=?,category=?,description=? where id=? `,
                    [opt.name,opt.author,opt.category,opt.description,opt.id]);
            if(data.affectedRows > 0){
                result.message = '修改成功'
                return Promise.resolve(result);
            }else{
                result.message = '修改失败';
                result.code = 1;
                return Promise.reject(result);
            }
        }catch(err){
            result.message = '修改失败';
            result.code = 1;
            result.status = 500
            return Promise.reject(result);
        }
    }
}
module.exports = SafeRequest;

3.5前端渲染

//编辑图书
$('.edit').on('click','a:eq(0)', function(e){
    // console.log('0 ===>',0);
    $('#myModal').modal('show');
    //获取id
    let id = $(this).parent().siblings().eq(0).text();
    // console.log('id',id);

    $.ajax({
        url:'/editpage?editid='+id,
        type: 'get',
        dataType: 'json',
        success(msg){
            console.log('msg =====>',msg);
            $('#form').find('input[name=name]').val(msg.data.name);
            $('#form').find('input[name=author]').val(msg.data.author);
            $('#form').find('input[name=category]').val(msg.data.category);
            $('#form').find('input[name=description]').val(msg.data.description);
            
            //发起请求 修改图书信息
            $('#btn_submit').off('click').click(function(){
                // console.log('2 ===>',2);
                submitData('/edit',id);
                
            })
        },
        error(err){
            console.log('err =====>',err);
        }
    })

})
//封装  提交数据
    function submitData(url,id){
        //使用serialize()方法获取到数据
        let data = $('#form').serialize();
        //使用三元表达式
        data += id ? `&id=${id}` : '';
        // console.log(data);
        $.ajax({
            url:url,
            type: 'post',
            dataType: 'json',
            data: data,
            success(msg){
                console.log('msg =====>',msg);
                if(msg.code === 0){
                    toastr.success('提交成功!');
                    //添加成功后在加载页面
                    getListBook();
                }else{
                    toastr.error('提交失败!');
                }
            },
            error(err){
                console.log('err =====>',err);
                toastr.error('提交失败!');
            }
        })
        //关闭模态框
        $('#myModal').modal('hide');
    }

Node学习(一)
Node学习(二)

   

更多内容详见微信公众号:Python测试和开发

Python测试和开发

原文地址:https://www.cnblogs.com/phyger/p/14313608.html