nodejs入门(二)

NodeJs WEB服务器 静态文件托管、 路由、EJS模板引擎、GET、POST

NodeJs WEB服务器

前面已经完成了一个简单的web服务器,是node最简单的形式

// 表示引入http模块
var http = require('http');
// 创建一个服务器,回调函数表示接收到请求之后做的事情
http.createServer(function (request, response) {
  // req参数表示请求,res表示响应
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World'); // End 方法使 Web 服务器停止处理脚本并返回当前结果
}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

Nodejs 静态文件托管

现在需要把上面的代码修改一下,让其能够访问服务器static下的html文件,如果没有则写出"404这个页面不存在"(加入没有加上.html,则默认找index.html)

var http = require('http');
var fs = require('fs'); // 返回数据内容需要

http.createServer(function (req, res) {
    //1、获取地址
    let pathname = req.url;
    pathname = pathname == '/'?'/index.html' : pathname;

    //2、通过fs模块读取文件
    if(pathname!='/favicon.ico'){
        fs.readFile('./static'+pathname,(err, data) => {
            if(err){
                res.writeHead(404, {'Content-Type': 'text/html;charset="utf-8"'});  
                res.end('404这个页面不存在');               
            }
            res.writeHead(200, {'Content-Type': 'text/html;charset="utf-8"'});  
            res.end(data);
        });
    }

}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

但是这样有一个问题, 当访问js和css代码的时候因为有

Content-Type': 'text/html

而在页面渲染时候失败

所以需要一个动态判断的函数,新建一个node_modules文件夹,创建一个common.js文件,内容如下

exports.getMime = function (extname) {
    switch (extname) {
        case '.html':
            return 'text/html';
        case '.css':
            return 'text/css';
        case '.js':
            return 'text/javascript';
        default:
            return 'text/html';
    }
};

再来修改一下上面的内容

var http = require('http');
var fs = require('fs');
var common = require('common');
var url = require('url');
var path = require('path');

http.createServer(function (req, res) {
    //1、获取地址
    // let pathname = req.url;
    // pathname = pathname == '/'?'/index.html' : pathname;
    let pathname = url.parse(req.url).pathname; // 遇到类似http://127.0.0.1:8081/json/all.json?788351035676484的,可以直接去掉?后面的一串
    pathname = pathname == '/' ? '/index.html' : pathname;
    //可以获取后缀名path.extname()
    let extname = path.extname(pathname);

    //2、通过fs模块读取文件
    if(pathname!='/favicon.ico'){
        fs.readFile('./static'+pathname,(err, data) => {
            if(err) {
                res.writeHead(404, {'Content-Type': 'text/html;charset="utf-8"'});
                res.end('404这个页面不存在');
            }
            let mime = common.getMime(extname);
            // res.writeHead(200, {'Content-Type': 'text/html;charset="utf-8"'});
            res.writeHead(200, {'Content-Type': '' + mime + ';charset="utf-8"'});
            res.end(data);
        });
    }
}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

由于页面有json的请求,请求格式是

http://127.0.0.1:8081/json/all.json?8757847100278133

因此使用了url模块进行分割

但是现在对图片的响应还是没有对,所以继续来修改,新建一个data文件夹,里面有一个mime.json,里面是各种文件后缀对应的响应头

在common.js文件中,新增一个函数getFileMime,内容如下

exports.getFileMime = function(extname) {
    return new Promise((resolve, reject) => {
         fs.readFile('./data/mime.json', (err, data)=>{
             if(err){
                 console.log(err);
                 reject(err);
                 return;
             }
             let mimeObj=JSON.parse(data.toString());
             // console.log(mimeObj[extname]);
             resolve(mimeObj[extname]);
         });
    });
};

因为getFileMime是异步函数,所以在readFile的回调函数中需要加上async,这时的app.js内容如下

var http = require('http');
var fs = require('fs');
var common = require('common');
var url = require('url');
var path = require('path');

http.createServer(function (req, res) {
    //1、获取地址
    // let pathname = req.url;
    // pathname = pathname == '/'?'/index.html' : pathname;
    let pathname = url.parse(req.url).pathname; // 遇到类似http://127.0.0.1:8081/json/all.json?788351035676484的,可以直接去掉?后面的一串
    pathname = pathname == '/' ? '/index.html' : pathname;
    //可以获取后缀名path.extname()
    let extname = path.extname(pathname);

    //2、通过fs模块读取文件
    if(pathname!='/favicon.ico'){
        fs.readFile('./static'+pathname, async (err, data) => {
            if(err) {
                res.writeHead(404, {'Content-Type': 'text/html;charset="utf-8"'});
                res.end('404这个页面不存在');
            }
            // let mime = common.getMime(extname);
            let mime = await common.getFileMime(extname);
            // res.writeHead(200, {'Content-Type': 'text/html;charset="utf-8"'});
            res.writeHead(200, {'Content-Type': '' + mime + ';charset="utf-8"'});
            res.end(data);
        });
    }
}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

再来执行一下,访问8081端口,可以看到访问图片的响应头已经正确了

接下來,还可以使用readFile的异步版本,这样就可以就可以在主函数中省略很多代码了,当然也可以选择修改主函数的readFile

exports.getFileMimeSync = function(extname) {
    var data = fs.readFileSync('./data/mime.json'); // 同步方法
    let mimeObj=JSON.parse(data.toString());
    return mimeObj[extname]; 
};

路由

官方解释:路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问。

非官方解释: 路由指的就是针对不同请求的URL,处理不同的业务逻辑。

上面已经完成了一个静态的web服务器创建,下面对他进行修改,封装一下想用一句话都创建web服务

新建一个route.js,内容如下,主要是把原来在app.js中的内容移过去了

var url = require('url');
var path = require('path');
var fs = require('fs');

let getFileMimeSync = function(extname) {
    var data = fs.readFileSync('./data/mime.json'); // 同步方法
    let mimeObj=JSON.parse(data.toString());
    return mimeObj[extname]; 
};

exports.static = function (req, res, staticPath) {
    //1、获取地址
    let pathname = url.parse(req.url).pathname;
    pathname = pathname == '/' ? '/index.html' : pathname;
    let extname = path.extname(pathname);
    //2、通过fs模块读取文件
    if (pathname != '/favicon.ico') {
        try {
            let data = fs.readFileSync('./' + staticPath + pathname);
            if (data) {
                let mime = getFileMimeSync(extname);
                res.writeHead(200, { 'Content-Type': '' + mime + ';charset="utf-8"' });
                res.end(data);
            }
        } catch (error) {
        }
    }
};

现在app.js的内容如下

var http = require('http');
var routes = require('routes');

http.createServer(function (req, res) {
    routes.static(req, res, 'static');
}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

整个文件夹存放如下图

初识EJS模块引擎

我们学的EJS是后台模板,可以把我们数据库和文件读取的数据显示到Html页面上面。它是一个第三方模块,
需要通过npm安装https://www.npmjs.com/package/ejs,安装:

npm init --yes
npm install ejs -save

Nodejs中使用:

ejs.renderFile(filename, data, options, function(err, str){ }
// str => Rendered HTML string });

EJS常用标签

  • 流程控制标签
  • 输出标签(原文输出HTML标签)
  • 输出标签(HTML会被浏览器解析)

使用例子如下,在上面已经完成的web封装服务器中,修改app.js代码如下

var http = require('http');
var routes = require('routes');
var url = require('url');
var ejs = require('ejs');

http.createServer(function (req, res) {
    routes.static(req, res, 'static');
    //路由
    let pathname=url.parse(req.url).pathname;
    if(pathname=='/login') {
        let msg="数据库里面获取的数据";
        let list=[
            {
                title:'新闻111'
            },
            {
                title:'新闻222'
            },
            {
                title:'新闻3333'
            },
            {
                title:'新闻4444'
            },{
                title:'新闻5555'
            }
        ];
        ejs.renderFile('./views/login.ejs', {
            msg:msg,
            list:list
        },(err, data) => {
            res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
            res.end(data);
        });
    }
}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

新建一个views文件夹,里面存放一个login.ejs(在项目中已经安装了ejs依赖),内容如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2>这是一个登录页面</h2>
    <h3><%=msg%></h3>
    <br>
    <ul>
        <%for(var i=0; i<list.length;i++) {%>
            <li><%=list[i].title%></li>
        <%}%>
    </ul>
</body>
</html>

执行此app.js,浏览器中访问链接,显示的内容如下

Get、Post

超文本传输协议(HTTP)的设计目的是保证客户端机器与服务器之间的通信。

在客户端和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。

GET - 从指定的资源请求数据。(一般用于获取数据)

POST - 向指定的资源提交要被处理的数据。(一般用于提交数据)

获取GET传值:

// 获取get传值----http://127.0.0.1:8081/news?username=zeng&age=47
var query = url.parse(req.url,true).query; // 获取请求对象加上true
console.log("req.url:", req.url, " query.username", query.username); // zeng
res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
res.end('get传值获取成功');

获取POST传值:

else if(pathname == '/doLogin'){
    //获取post传值,post触发data事件
    let postData = '';
    // var buffers = [];
    req.on('data', (chunk)=>{
        postData += chunk;
    });
    // 读取完data数据触发一个end事件
    req.on('end', ()=>{
        console.log(postData, "post");
        res.end(postData);
    });

整个测试例子,views文件夹中新建一个form.ejs,内容如下,接收表单数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/doLogin" method="post">
        用户名:<input type="text" name="username" />
        <br>
        <br>
         密 码: <input type="password" name="password" />
        <br>
        <br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

app.js现在的内容如下

var http = require('http');
var routes = require('routes');
var url = require('url');
var ejs = require('ejs');
var querystring = require('querystring');

http.createServer(function (req, res) {
    routes.static(req, res, 'static');
    // 路由
    let pathname = url.parse(req.url).pathname;

    // 获取请求类型
    console.log(req.method);

    if(pathname == '/news') {
        // 获取get传值----http://127.0.0.1:8081/news?username=zeng&age=47
        var query = url.parse(req.url,true).query; // 获取请求对象加上true
        console.log("req.url:", req.url, " query.username", query.username); // zeng
        res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end('get传值获取成功');
    }
    else if(pathname == '/login') {
        //post演示
        ejs.renderFile("./views/form.ejs",{},(err, data)=>{
             res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
             res.end(data);
        });
     }
     else if(pathname == '/doLogin'){
        //获取post传值,post触发data事件
        let postData = '';
        // var buffers = [];
        req.on('data', (chunk)=>{
            postData += chunk;
            // buffers.push(chunk);
        });
        // 读取完data数据触发一个end事件
        req.on('end', ()=>{
            console.log(postData, "post");
            res.end(postData);
            // 解析post参数
        //    console.log(buffers, "post");
        //    let requestBody = Buffer.concat(buffers).toString();
        //    requestBody = querystring.parse(requestBody)
        //    console.log(requestBody.password);
        //    res.end(requestBody.username);
        });
    }
    else{
        res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end("页面不存在");
    }
}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

测试页面分别为:

http://127.0.0.1:8081/news?username=zeng&age=47
http://127.0.0.1:8081/login

Nodejs路由封装封装一个类似express的路由

模块化的方式封装

整体思想是把上面在app.js的内容都放到route.js中,让其在app.js中能按照指定的目标页进行返回数据

修改route.js的内容

var url = require('url');
var path = require('path');
var fs = require('fs');
var ejs = require('ejs');

let app = {
    static: (req, res, staticPath) => {
        //1、获取地址
        let pathname = url.parse(req.url).pathname;
        pathname = pathname == '/' ? '/index.html' : pathname;
        let extname = path.extname(pathname);
        //2、通过fs模块读取文件
        if (pathname != '/favicon.ico') {
            try {
                let data = fs.readFileSync('./' + staticPath + pathname);
                if (data) {
                    let mime = getFileMime(extname);
                    res.writeHead(200, { 'Content-Type': '' + mime + ';charset="utf-8"' });
                    res.end(data);
                }
            } catch (error) {
            }
        }
    },
    login: (req, res) => {
        ejs.renderFile('./views/form.ejs',{},(err, data)=>{
          res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
          res.end(data)
        })
    },
    news: (req, res) => {       
          res.end('news');
    },
    doLogin: (req, res) => {       
        //获取post传值        
        let postData = '';
        req.on('data',(chunk)=>{
            postData+=chunk;
        })
        req.on('end',()=>{
           console.log(postData);
           res.end(postData);
    })
   },
   error: (req, res) => {
       res.end('error');
   }
}

module.exports=app; // 模块接口的暴露

那么此时app.js就变得简单了

var http = require('http');
var routes = require('routes');
var url = require('url');

http.createServer(function (req, res) {
    routes.static(req, res, 'static');
    // 路由
    // let pathname = url.parse(req.url).pathname;
    let pathname=url.parse(req.url).pathname.replace("/","");
    // 获取请求类型
    console.log(req.method);

    try {
        routes[pathname](req, res);
    } catch (error) {
        routes['error'](req, res);
    }

}).listen(8081);

console.log('Server running at http://127.0.0.1:8081/');

封装仿照express的路由一

第一个版本

这是一个最普通的函数调用的例子

let app=function(){
    console.log('调用app方法')
}

app.get=function(){
    console.log('get方法')
}

app.post=function(){
    console.log('post方法')
}

app.get();

最终目标时以这样的方式配置路由

app.get("/", function(req, res){
    res.send('hello world.')
})

第二个版本

修改一下代码,在一个全部变量G中注册一下函数++++++++++++暂时留着一会回来看

let G = {};

let app = function(req,res){
    console.log('调用app方法')
    if(G['/login']){
       G['/login'](req, res);  //执行方法
    }
}

app.get = function(str, cb){   
    // 注册方法
    console.log('注册方法')
    G[str]=cb;
    // 实际操作就是
    // G["/login"] = function (req, res) {
    //     // res.send('hello world')
    //     console.log("执行login方法");
    // })
}

// 方法的具体实现,上面只是注册对应的函数
app.get("/login", function (req, res) {
    // res.send('hello world')
    console.log("执行login方法");
})

app('req','res');

第三个版本

再来修改一下,app.js可以更简单,目前只是支持/login,修改后让他支持更多路由,新加一个routes.js,放在node_modules文件夹下,内容如下

var url = require("url");

let G = {};

let app = function(req, res) {
    let pathname = url.parse(req.url).pathname;
    if(G[pathname]) {
        G[pathname](req,res);  //执行方法
    }
    else {
        res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end('页面不存在');
    }
}

app.get = function(str, cb){   
    // 注册方法
    console.log('注册方法');
    G[str]=cb;
}

module.exports = app; // 模块接口的暴露

这是app.js代码修改为

var http = require("http");
var app = require('routes.js')

//注册web服务
http.createServer(app).listen(8081);

//配置路由
app.get('/', function(req,res){
    res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
    res.end('首页');
})

//配置路由
app.get('/login', function(req,res){
    res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
    res.end('执行登录操作');
})

//配置路由
app.get('/news', function(req,res){
    res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
    res.end('新闻页面');
})

这样在浏览器就能支持如下链接了

http://127.0.0.1:8081/
http://127.0.0.1:8081/login
http://127.0.0.1:8081/news

封装仿照express的路由二

继续让封装的代码支持post

在views文件夹下新建一个form.ejs,内容如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/doLogin" method="post">
        用户名:<input type="text" name="username" />
        <br>
        <br>
         密 码: <input type="password" name="password" />
        <br>
        <br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

routes.js代码如下,主要是提供注册对应的post和get函数到let G中(还能解决post与get路由重名被覆盖的问题),如果请求为已经注册的路由名,则调用之前注册function

var url = require("url");

let server = function () {
    let G = {};
    //把get 和 post分开
    G._get={};
    G._post={};

    let app = function (req, res) {
        let pathname = url.parse(req.url).pathname;
        //获取请求类型
        let method=req.method.toLowerCase();
        console.log(method);

        if (G['_'+method][pathname]) {
            if(method == "get"){ 
                G['_'+method][pathname](req, res);  //执行方法
            }else{
                //post  获取post的数据 把它绑定到req.body
                let postData = '';
                req.on('data', (chunk)=>{
                    postData+=chunk;
                })
                req.on('end', ()=>{                  
                   req.body=postData;
                   G['_'+method][pathname](req, res);  //执行方法
                })
            }
        } else {
            res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' });
            res.end('页面不存在');
        }
    }

    app.get = function (str, cb) {
        //注册方法
        G._get[str] = cb;     
    }
    app.post = function (str, cb) {
        //注册方法
        G._post[str] = cb;      
    }

    return app;
}

module.exports = server(); // 模块接口的暴露

app.js内容如下,大部分的内容为所注册路由的具体实现

var http = require("http");
var app=require('routes2');
var ejs = require("ejs");

//注册web服务
http.createServer(app).listen(8081);

//配置路由
app.get('/', function(req, res){
    res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
    res.end('首页');
})

//配置路由
app.get('/login',function(req, res){
    ejs.renderFile("./views/form.ejs",{},(err,data)=>{
        res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end(data);
    })
})

app.post('/doLogin',function(req, res){
    res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
    res.end('执行登录操作');
})

加上req.body

在响应是已经有了on触发的data、end事件,只需要把他转发一下

let postData = '';
req.on('data', (chunk)=>{
    postData+=chunk;
})
req.on('end', ()=>{                  
   req.body=postData;
   G['_'+method][pathname](req, res);  //执行方法
})

在具体的dologin路由中输出一下,看是否正确

app.post('/doLogin',function(req, res){
    console.log(req.body);
    res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
    res.end('执行登录操作');
})

将固定writeHead封装起来

在routes.js中新加一个function,在server中进行注册,注册后,res就能扩展使用send函数了

function changeRes(res){
    res.send = (data)=>{
        res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end(data);
    }
}

在原来的server中添加注册

let server = function () {
...
    let app = function (req, res) {
        // 扩展res的方法
        changeRes(res);
...
    }
...
}

把app.js中调用writeHead和end的部分都替换成send

var http = require("http");
var app=require('routes2');
var ejs = require("ejs");

//注册web服务
http.createServer(app).listen(8081);

//配置路由
app.get('/', function(req, res){
    // res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
    // res.end('首页');
    res.send("首页"); // 调用扩展后的res.send方法
})

//配置路由
app.get('/login',function(req, res){
    ejs.renderFile("./views/form.ejs",{},(err,data)=>{
        res.send(data);
    })
})

app.post('/doLogin',function(req, res){
    res.send(req.body);
})

封装仿照express的路由三—支持css等静态路由

想要让服务器支持css、js等目录,就需要封装静态web服务,把之前的data文件夹和里面的mime.json文件放到文件中,在routes.js代码中进行整合

var url = require("url");
var path = require("path");
var fs = require('fs');

function changeRes(res) {
    res.send = (data) => {
        res.writeHead(200, { 'Content-Type': 'text/html;charset="utf-8"' });
        res.end(data);
    }
}

//根据后缀名获取文件类型
function getFileMime(extname) {
    var data = fs.readFileSync('./data/mime.json'); //同步方法
    let mimeObj = JSON.parse(data.toString());
    return mimeObj[extname];
}

//静态web服务的方法
function initStatic(req, res, staticPath) {
    //1、获取地址
    let pathname = url.parse(req.url).pathname;
    pathname = pathname == '/' ? '/index.html' : pathname;
    let extname = path.extname(pathname);
    //2、通过fs模块读取文件
    try {
        let data = fs.readFileSync('./' + staticPath + pathname);
        if (data) {
            let mime = getFileMime(extname);
            res.writeHead(200, { 'Content-Type': '' + mime + ';charset="utf-8"' });
            res.end(data);
        }
    } catch (error) {

    }
}

let server = function() {
    let G = {
        _get : {},
        _post : {},
        staticPath : 'static' //,默认静态web目录
    };

    let app = function(req, res) {
        // 扩展res的方法
        changeRes(res);
        initStatic(req, res, G.staticPath)
        let pathname = url.parse(req.url).pathname;
        //获取请求类型
        let method=req.method.toLowerCase();
        console.log(method);

        if (G['_'+method][pathname]) {
            if(method == "get"){ 
                G['_'+method][pathname](req, res);  //执行方法
            }else{
                //post 获取post的数据 把它绑定到req.body
                let postData = '';
                req.on('data', (chunk)=>{
                    postData+=chunk;
                })
                req.on('end', ()=>{                  
                   req.body=postData;
                   G['_'+method][pathname](req, res);  //执行方法
                })
            }
        } else {
            res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' });
            res.end('页面不存在');
        }
    }

    app.get = function (str, cb) {
        //注册方法
        G._get[str] = cb;     
    }
    app.post = function (str, cb) {
        //注册方法
        G._post[str] = cb;      
    }

    // 配置静态web服务目录
    app.static = function(staticPath){
        G.staticPath = staticPath;
    }

    return app;
}

module.exports = server(); // 模块接口的暴露

新建一个static文件夹存放style.css文件,内容如下

h2 {
    color: red;
}

在form.ejs中引入上面的css文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./css/style.css" />
    <title>Document</title>
</head>
<body>
    <h2>登录页面</h2>
    <form action="/doLogin" method="post">
        用户名:<input type="text" name="username" />
        <br>
        <br>
        密 码: <input type="password" name="password" />
        <br>
        <br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

这时app.js文件内容如下

var http = require("http");
var app=require('routes2');
var ejs = require("ejs");

// 注册web服务
http.createServer(app).listen(8081);

// 如果静态资源不在默认的static文件夹下,则使用
// app.static("public")

// 配置路由
app.get('/', function(req, res){
    res.send("首页"); // 调用扩展后的res.send方法
})

// 配置路由
app.get('/login',function(req, res){
    ejs.renderFile("./views/form.ejs",{},(err, data)=>{
        res.send(data);
    })
})

app.post('/doLogin',function(req, res){
    console.log(req.body);
    res.send(req.body);
})

现在css已经能使用了

全文所涉及的代码下载地址

参考链接

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值