一、nodejs基础
1、认识nodejs
* nodejs是一个javascript运行环境,它让javascript可以开发后端程序,实现几乎其他后端
语言实现的所有功能,可以与php、java、python、.net、ruby等后端语言平起平坐
* nodejs是基于v8引擎,v8是google发布的开源javascript引擎,本身就是用于chrome浏览器
的js解释部分,但是ryan dahl这哥们,鬼才般的,把这个v8搬到了服务器上,用于做服务器的软件
2、nodejs的特性
* nodejs语法完全是js语法,只要你懂js基础就可以学会nodejs后端开发
* nodejs超强的高并发能力,实现高性能服务器
* 开发周期短、开发成本低、学习成本低
3、使用nodejs需要了解多少javascript
* http://n odejs.cn/learn/how-much-javascript-do -you-need-to-know-to-use -nodejs
4、浏览器环境vs node环境
* chrome浏览器
- html/css - javascript
- blink - v8
- 中间层
- 操作系统(网卡/硬盘/显卡...)
* node
- javascript
- v8
- 中间层(libuv)
- 操作系统(网卡/硬盘/显卡...)
* nodejs可以解析js代码(没有浏览器安全级别的限制)提供很多系统级别的api,如:
- 文件的读写(file system)
########
const fs = require("fs")
fs.readFile("./ajax.png", "utf-8", (err, content) => {
console.log(content)
})
########
- 进程的管理(process)
########
function main(argv) {
console.log(argv)
}
main(process.argv.slice(2))
########
- 网络通信(http/https)
########
const http = require("http")
http.createServer((req, res) => {
res.writeHead(200, {
"content-type": "text/plain"
})
res.write("hello nodejs")
res.end()
}).listen(3000)
########
5、开发环境搭建
* http://nodejs.cn/download/
二、模块、包、commonjs
1、为什么要有模块化开发
* 依赖关系 - 命名空间 - 代码组织
* 纠结的编程体验
* 定义 - 暴露接口 - 引用
2、commonjs规范
* modules、binary、packages、console、system、encodings、filesystems、sockets
* nodejs/webpack(部分实现规范)
3、modules模块化规范写法
* 我们可以把公共的功能抽离成为一个单独的js文件作为一个模块,默认情况下面这个模块里面的方法或者属性,
外面是没法访问的。如果要让外部可以访问模块里面的方法或者属性,就必须在模块里面通过exports或者
module.exports暴露属性或者方法。
const name = "gp19"
const sayName = () => {
console.log (name)
}
console.log ("module 1" )
module.exports = {
say: sayName
}
exports.say = sayName
const m1 = require ("./m1" )
m1.say ()
三、npm&yarn
1、npm的使用
npm init
npm install 包名 -g(uninstall、update)
npm install 包名 --save-dev(uninstall、update)
npm list -g(不加-g,列举当前目录下的安装包)
npm info 包名(详细信息) npm info 包名 version(获取最新版本)
npm install md5@1 (安装指定版本)
npm outdated(检查包是否已经过时)
"dependencies" : {"md5" : "^2.1.0" }:^表示如果直接npm install将会安md5 2 .*.*最新版本
"dependencies" : {"md5" : "~2.1.0" }:~表示如果直接npm install将会安装md5 2 .1 .*最新版本
"dependencies" : {"md5" : "*" }:*表示如果直接npm install将会安装md5最新版本
2、全局安装nrm
* nrm(npm registry manager)是npm的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速地在
npm源间切换
* 手动切换方法:npm config set registry https://registry.npm.taobao.org
* 安装nrm:在命令行执行命令,npm install -g nrm,全局安装nrm
* 使用nrm:执行命令nrm ls查看可选的源。其中,带*的是当前使用的源,上面的输出表明当前源是官方源
* 切换nrm:如果要切换到taobao源,执行命令nrm use taobao
* 测试速度:你还可以通过nrm test测试相应源的响应时间
- nrm test
* 扩展:中国npm镜像,这是一个完整npmjs.org镜像,你可以用此代替官方版本(只读),同步频率目前为10分钟
一次以保证尽量与官方服务同步。
- npm install -g cnpm --registry=https://registry.npmmirror.com
3、yarn使用
* npm install -g yarn
* 对比npm :
- 速度超快:yarn 缓存了每个下载过的包,所以每次使用时无需重复下载。同时利用并行下载以最大
化资源利用率,因此安装速度更快。
- 超级安全:在执行代码之前,yarn 会通过算法校验每个安装包的完整性
* 开始新项目
- yarn init
*添加依赖包
- yarn add [package]
- yarn add [package] @[version]
- yarn add [package] --dev
* 升级依赖包
- yarn upgrade [package] @[version]
* 移除依赖包
- yarn remove [package]
* 安装项目的全部依赖
- yarn install
四、内置模块
1、http模块
const http = require ("http" )
const server = http.createServer ((req, res ) => {
res.writeHead (200 , {"Content-Type" : "application/json" })
res.end (JSON .stringify ({
data : "Hello World!"
}))
})
server.listen (8000 )
const http = require ("http" )
const server = http.createServer ()
server.on ("request" , (req, res ) => {
res.writeHead (200 , {"Content-Type" : "application/json" })
res.end (JSON .stringify ({
data : "你好世界!"
}))
})
server.listen (8000 )
2、url模块
const url = require ("url" )
const urlString = "https://www.baidu.com:443/ad/index.html?id=8&name=mouse#tag=110"
const parsedStr = url.parse (urlString)
console .log (parsedStr)
const url = require ("url" )
const urlobject = {
protocol : 'https:' ,
slashes : true ,
auth : null ,
host : 'www.baidu.com:443' ,
port : '443' ,
hostname : 'www.baidu.com' ,
hash : '#tag=110' ,
search : '?id=8&name=mouse' ,
query : {id : "8" , name : "mouse" },
pathname : '/ad/index.html' ,
path : '/ad/index.html?id=8&name=mouse'
}
const parsedObj = url.format (urlobject)
console .log (parsedObj)
const url = require ("url" )
var a = url.resolve ("/one/two/three" , "four" )
var b = url.resolve ("http://example.com/" , "/one" )
var c = url.resolve ("http://example.com/one" , "/two" )
console .log (a + "," + b + "," + c)
3、querystring模块
const querystring = require ("querystring" )
var qs = "x=3&y=4"
var parsed = querystring.parse (qs);
console .log (parsed)
const querystring = require ("querystring" )
var qo = {x : '3' , y : '4' }
var parsed = querystring.stringify (qo);
console .log (parsed)
'use strict' ;
const mysql = require ("mysql" )
let param = "ns"
let pool = mysql.createPool ({
user : "root" ,
password : "root" ,
database : "nlp_dict"
})
pool.getConnection (function (err, conn ) {
let sql = 'select * from tb_nature where nature = "' + param + '" and del_status=1'
conn.query (sql, function (err, result ) {
console .log (result)
})
})
const querystring = require ("querystring" )
var str = "id=3&city=北京&url=https://www.baidu.com"
var escaped = querystring.escape (str)
console .log (escaped)
const querystring = require ("querystring" )
var str = "id%3D3%26city%3D%E5%8C%97%E4%BA%AC%26url%3Dhttps%3A%2F%2Fwww.baidu.com"
var unescaped = querystring.unescape(str)
console.log(unescaped)
4、http模块补充
const http = require ("http" )
const url = require ("url" )
const app = http.createServer ((req, res ) => {
let urlObj = url.parse (req.url , true )
switch (urlObj.pathname ) {
case "/api/user" :
res.end (`${urlObj.query.cb} ({"name": "gp145"})` )
break ;
default :
res.end ("404." )
break ;
}
})
app.listen (8000 , () => {
console .log ("localhost:8000" )
})
const http = require ('http' )
const url = require ('url' )
const querystring = require ('querystring' )
const app = http.createServer ((req, res ) => {
let data = ''
let urlObj = url.parse (req.url , true )
res.writeHead (200 , {
'content-type' : 'application/json;charset=utf-8' ,
'Access-Control-Allow-Origin' : '*'
})
req.on ('data' , (chunk ) => {
data += chunk
})
req.on ('end' , () => {
responseResult (querystring.parse (data))
})
function responseResult (data ) {
switch (urlObj.pathname ) {
case '/api/login' :
res.end (JSON .stringify ({
message : data
}))
break
default :
res.end ('404.' )
break
}
}
})
app.listen (8000 , () => {
console .log ('localhost:8000' )
})
var http = require ('http' )
var https = require ('https' )
const server = http.createServer ((request, response ) => {
var url = request.url .substr (1 )
var data = ''
response.writeHeader (200 , {
'content-type' : 'application/json;charset=utf-8' ,
'Access-Control-Allow-Origin' : '*'
})
https.get (`https://m.lagou.com/listmore.json${url} ` , (res ) => {
res.on ('data' , (chunk ) => {
data += chunk
})
res.on ('end' , () => {
response.end (JSON .stringify ({
ret : true ,
data
}))
})
})
})
server.listen (8080 , () => {
console .log ('localhost:8080' )
})
const https = require ('https' )
const querystring = require ('querystring' )
const postData = querystring.stringify ({
province : '上海' ,
city : '上海' ,
district : '宝山区' ,
address : '同济支路199号智慧七立方3号楼2-4层' ,
latitude : 43.0 ,
longitude : 160.0 ,
message : '求购一条小鱼' ,
contact : '13666666' ,
type : 'sell' ,
time : 1571217561
})
const options = {
protocol : 'https:' ,
hostname : 'ik9hkddr.qcloud.la' ,
method : 'POST' ,
port : 443 ,
path : '/index.php/trade/add_item' ,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
'Content-Length' : Buffer .byteLength (postData)
}
}
function doPost ( ) {
let data
let req = https.request (options, (res ) => {
res.on ('data' , chunk => data += chunk)
res.on ('end' , () => {
console .log (data)
})
})
req.write (postData)
req.end ()
}
const https = require ('https' )
const http = require ('http' )
const cheerio = require ('cheerio' )
http.createServer ((request, response ) => {
response.writeHead (200 , {
'content-type' : 'application/json;charset=utf-8'
})
const options = {
hostname : 'i.maoyan.com' ,
port : 443 ,
path : '/' ,
method : 'GET'
}
const req = https.request (options, (res ) => {
let data = ''
res.on ('data' , (chunk ) => {
data += chunk
})
res.on ('end' , () => {
filterData (data)
})
})
function filterData (data ) {
let $ = cheerio.load (data)
let $movieList = $('.column.content' )
console .log ($movieList)
let movies = []
$movieList.each ((index, value ) => {
movies.push ({
title : $(value).find ('.movie-title .title' ).text (),
detail : $(value).find ('.detail .actor' ).text (),
})
})
response.end (JSON .stringify (movies))
}
req.end ()
}).listen (3000 )
5、event模块
const {EventEmitter} = require("events" )
class MyEventEmitter extends EventEmitter {
}
const event = new MyEventEmitter()
const onplay = (movie) => {
console.log(movie)
}
event .on ("play" , onplay)
event .once('play' , (movie) => {
console.log('once' , movie)
})
event .emit("play" , "我和我的祖国" )
event .removeListener('play' , onplay)
event .emit("play" , "中国机长" )
6、fs文件操作模块
const fs = require ('fs' )
fs.mkdir ('./logs' , (err ) => {
console .log ('done.' )
})
fs.rename ('./logs' , './log' , () => {
console .log ('done' )
})
fs.rmdir ('./log' , () => {
console .log ('done.' )
})
fs.writeFile (
'./logs/log1.txt' ,
'hello' ,
(err ) => {
if (err) {
console .log (err.message )
} else {
console .log ('文件创建成功' )
}
}
)
fs.appendFile ('./logs/log1.txt' , '\nworld' , () => {
console .log ('done.' )
})
fs.readFile ('./logs/log1.txt' , 'utf-8' , (err, data ) => {
console .log (data)
})
fs.unlink ('./logs/log1.txt' , (err ) => {
console .log ('done.' )
})
for (var i = 0 ; i < 10 ; i++) {
fs.writeFile (`./logs/log-${i} .txt` , `log-${i} ` , (err ) => {
console .log ('done.' )
})
}
fs.readdir ('./' , (err, data ) => {
data.forEach ((value, index ) => {
fs.stat (`./${value} ` , (err, stats ) => {
console .log (value + ' is ' + (stats.isDirectory () ? 'directory' : 'file' ))
})
})
})
try {
const content = fs.readFileSync ('./logs/log-1.txt' , 'utf-8' )
console .log (content)
console .log (0 )
} catch (e) {
console .log (e.message )
}
fs.readFile ('./logs/log-0.txt' , 'utf-8' , (err, content ) => {
console .log (content)
console .log (0 )
})
console .log (1 )
const fs = require ("fs" ).promises
fs.readFile ('./logs/log-0.txt' , 'utf-8' ).then (result => {
console .log (result)
})
7、stream流模块
var fs = require ('fs' );
var rs = fs.createReadStream ('sample.txt' , {
highWaterMark : 64 * 1024 ,
});
rs.on ('data' , function (chunk ) {
console .log ('DATA:' )
console .log (chunk);
});
rs.on ('end' , function ( ) {
console .log ('END' );
});
rs.on ('error' , function (err ) {
console .log ('ERROR: ' + err);
});
const fs = require('fs' )
const readstream = fs.createReadStream('./1.txt' , {
highWaterMark: 1 ,
})
const writestream = fs.createWriteStream('./2.txt' , {
highWaterMark: 2 ,
})
readstream.on ('data' , data => {
const flag = writestream.write(data, () => {
})
if (!flag) {
readstream.pause()
}
})
writestream.on ('drain' , () => {
readstream.resume()
})
readstream.on ('end' , () => {
writestream.end()
})
const fs = require ('fs' )
const readstream = fs.createReadStream('./1.txt' )
const writestream = fs.createWriteStream('./2.txt' )
readstream.pipe(writestream)
/**
* 1 、pipe 就像可以把两个水管串成一个更长的水管一样,两个流也可以串起来。
* 一个Readable流和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,
* 这种操作叫pipe 。
* 2 、在Node.js中,Readable流有一个pipe ()方法,就是用来干这件事的。
* 3 、让我们用pipe ()把一个文件流和另一个文件流串起来,这样源文件的所有数据就自动写入到目标文件里了,
* 所以,这实际上是一个复制文件的程序:
*/
8、zlib
const fs = require ('fs' )
const zlib = require ('zlib' )
const gzip = zlib.createGzip ()
const readstream = fs.createReadStream ('./note.txt' )
const writestream = fs.createWriteStream ('./note2.txt' )
readstream
.pipe (gzip)
.pipe (writestream)
9、crypto
const crypto = require('crypto' );
const hash = crypto.createHash('md5' );
// 可任意多次调用update():
hash .update('Hello, world!' );
hash .update('Hello, nodejs!' );
console.log(hash .digest('hex' ));
/**
* 1 、crypto模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript代
* 码实现这些功能不是不可能,但速度会非常慢。Nodejs用C/C++实现这些算法
* 后,通过cypto这个模块暴露为JavaScript接口,这样用起来方便,运行速
* 度也快。
* 2 、MD5是一种常用的哈希算法,用于给任意数据一个“签名”。这个签名通常用一
* 个十六进制的字符串表示
* 3 、update()方法默认字符串编码为UTF-8 ,也可以传入Buffer。
* 4 、如果要计算SHA1,只需要把'md5' 改成'sha1' ,就可以得到SHA1的结果
* 1f32b9c9932c02227819a4151feed43e131aca40。
*/
const crypto = require ('crypto' );
const hmac = crypto.createHmac ('sha256' , 'secret-key' );
hmac.update ('Hello, world!' );
hmac.update ('Hello, nodejs!' );
console .log (hmac.digest ('hex' ));
const crypto = require ("crypto" );
function encrypt (key, iv, data ) {
let decipher = crypto.createCipheriv ('aes-128-cbc' , key, iv);
return decipher.update (data, 'binary' , 'hex' ) + decipher.final ('hex' );
}
function decrypt (key, iv, crypted ) {
crypted = Buffer.from (crypted, 'hex' ).toString ('binary' );
let decipher = crypto.createDecipheriv ('aes-128-cbc' , key, iv);
return decipher.update (crypted, 'binary' , 'utf8' ) + decipher.final ('utf8' );
}
五、路由
1、基础
var fs = require ("fs" )
var path = require ("path" )
function render (res, path ) {
res.writeHead (200 , {"Content-Type" : "text/html;charset=utf8" })
res.write (fs.readFileSync (path, "utf8" ))
res.end ()
}
const route = {
"/login" : (req, res ) => {
render (res, "./static/login.html" )
},
"/home" : (req, res ) => {
render (res, "./static/home.html" )
},
"/404" : (req, res ) => {
res.writeHead (404 , {"Content-Type" : "text/html;charset=utf8" })
res.write (fs.readFileSync ("./static/404.html" , "utf8" ))
}
}
2、获取参数
const route = {
"/api/login" : (req, res ) => {
const myURL = new URL (req.url , 'http://127.0.0.1:3000' );
console .log (myURL.searchParams .get ("username" ))
render (res, `{ok:1}` )
}
}
const route = {
"/api/login" : (req, res ) => {
var post = '' ;
req.on ('data' , function (chunk ) {
post += chunk;
});
req.on ('end' , function ( ) {
post = JSON .parse (post);
render (res, `{ok:1}` )
});
}
}
3、静态资源处理
function readStaticFile (req, res ) {
const myURL = new URL (req.url , 'http://127.0.0.1:3000' )
var filePathname = path.join (__dirname, "/static" , myURL.pathname );
if (fs.existsSync (filePathname)) {
res.writeHead (200 , {"Content-Type" : `${mime.getType(myURL.pathname.split("." )[1 ])} ;charset=utf8` })
res.write (fs.readFileSync (filePathname, "utf8" ))
res.end ()
return true
} else {
return false
}
}
六、express
1、特色
* https://www.expressjs.com.cn/
* 基于 Node.js 平台,快速、开放、极简的 web 开发框架。
* web应用:express是一个基于nodejs平台的极简、灵活的web应用开发框架,它提供一系列强大的特性,
帮助你创建各种web和移动设备应用
* api:丰富的http快捷方法和任意排列组合的connect中间件,让你创建健壮、友好的api变得即快速又简单
* 性能:express不对nodejs已有的特性进行二次抽象,我们只是在它之上扩展了web应用所需的基本功能
2、安装
* npm install express --save
3、路由
var express = require ('express' );
var app = express ();
app.get ('/' , function (req, res ) {
res.send ('hello world' );
});
app.listen (3000 , function ( ) {
console .log ("web服务启动" )
});
app.get ('/' , function (req, res ) {
res.send ('root' );
});
app.get ('/about' , function (req, res ) {
res.send ('about' );
});
app.get ('/random.text' , function (req, res ) {
res.send ('random.text' );
});
app.get ('/ab?cd' , function (req, res ) {
res.send ('ab?cd' );
});
app.get ('/ab/:id' , function (req, res ) {
res.send ('aaaaaaa' );
});
app.get ('/ab+cd' , function (req, res ) {
res.send ('ab+cd' );
});
app.get ('/ab*cd' , function (req, res ) {
res.send ('ab*cd' );
});
app.get ('/ab(cd)?e' , function (req, res ) {
res.send ('ab(cd)?e' );
});
app.get (/a/ , function (req, res ) {
res.send ('/a/' );
});
app.get (/.*fly$/ , function (req, res ) {
res.send ('/.*fly$/' );
});
app.get('/example/a' , function (req, res) {
res.send('Hello from A!' );
});
/**
* 1 、可以为请求处理提供多个回调函数,其行为类似 中间件。
* 唯一的区别是这些回调函数有可能调用 next ('route' )
* 方法而略过其他路由回调函数。
* 可以利用该机制为路由定义前提条件,如果在现有路径上继续执行没有意义,
* 则可将控制权交给剩下的路径。
*/
app.get('/example/b' , function (req, res, next) {
console.log ('response will be sent by the next function ...' );
next ();
}, function (req, res) {
res.send('Hello from B!' );
});
/**
* 1 、使用多个回调函数处理路由(记得指定 next 对象)
*/
var cb0 = function (req, res, next ) {
console .log ('CB0' )
next ()
}
var cb1 = function (req, res, next ) {
console .log ('CB1' )
next ()
}
var cb2 = function (req, res ) {
res.send ('Hello from C!' )
}
app.get ('/example/c' , [cb0, cb1, cb2])
var cb0 = function (req, res, next) {
console.log ('CB0' )
next ()
}
var cb1 = function (req, res, next) {
console.log ('CB1' )
next ()
}
app.get('/example/d' , [cb0, cb1], function (req, res, next) {
console.log ('response will be sent by the next function ...' )
next ()
}, function (req, res) {
res.send('Hello from D!' )
})
/**
* 1 、混合使用函数和函数数组处理路由
*/
4、中间件
* Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:
从本质上来说,一个 Express 应用就是在调用各种中间件。
* 中间件(Middleware) 是一个函数,它可以访问请求对象(request object (req)),
响应对象(response object (res)), 和 web 应用中处于请求-响应循环流程中的中间件,
一般被命名为 next 的变量。
* 中间件的功能包括:
- 执行任何代码。
- 修改请求和响应对象。
- 终结请求-响应循环。
- 调用堆栈中的下一个中间件。
* 如果当前中间件没有终结请求-响应循环,则必须调用 next() 方法将控制权交给下一个中间件,
否则请求就会挂起。
* Express 应用可使用如下几种中间件:
- 应用级中间件
- 路由级中间件
- 错误处理中间件
- 内置中间件
- 第三方中间件
* 使用可选则挂载路径,可在应用级别或路由级别装载中间件。另外,你还可以同时装在一系列中间件函数,
从而在一个挂载点上创建一个子中间件栈。
var app = express ()
app.use (function (req, res, next ) {
console .log ('Time:' , Date .now ())
next ()
})
var app = express ()
var router = express.Router ()
router.use (function (req, res, next ) {
console .log ('Time:' , Date .now ())
next ()
})
router.use ('/user/:id' , function (req, res, next ) {
console .log ('Request URL:' , req.originalUrl )
next ()
}, function (req, res, next ) {
console .log ('Request Type:' , req.method )
next ()
})
router.get ('/user/:id' , function (req, res, next ) {
if (req.params .id == 0 ) next ('route' )
else next ()
}, function (req, res, next ) {
res.render ('regular' )
})
router.get ('/user/:id' , function (req, res, next ) {
console .log (req.params .id )
res.render ('special' )
})
app.use ('/' , router)
app.use(function (err, req, res, next) {
console.error (err.stack)
res.status (500 ).send('Something broke!' )
})
/**
* 1 、错误处理中间件和其他中间件定义类似,只是要使用 4 个参数,
* 而不是 3 个,其签名如下: (err, req, res, next )。
*/
app.use (express.static ('public' ))
app.use (express.static ('uploads' ))
app.use (express.static ('files' ))
var express = require ('express' )
var app = express ()
var cookieParser = require ('cookie-parser' )
app.use (cookieParser ())
5、获取请求参数
req.query
app.use (express.urlencoded ({extended:false }))
app.use (express.json ())
req.body
6、利用 Express 托管静态文件
app.use(express.static('public' ))
/**
* 1、通过 Express 内置的 express.static 可以方便地托管静态文件,
* 例如图片、CSS、JavaScript 文件等。
* 2、将静态资源文件所在的目录作为参数传递给 express.static
* 中间件就可以提供静态资源文件的访问了。例如,假设在 public
* 目录放置了图片、CSS 和 JavaScript 文件,你就可以
* 3、现在,public 目录下面的文件就可以访问了
* - http://localhost:3000/images/kitten.jpg
* - http://localhost:3000/css/style.css
* - http://localhost:3000/js/app.js
* - http://localhost:3000/images/bg.png
* - http://localhost:3000/hello.html
* 4、所有文件的路径都是相对于存放目录的,因此,存放静态文件的目录名不会出现在 URL 中。
*/
app.use (express.static ('public' ))
app.use (express.static ('files' ))
app.use('/static' , express.static('public' ))
/**
* 1、如果你希望所有通过 express.static 访问的文件都存放在一个
* “虚拟(virtual)”目录(即目录根本不存在)下面,可以通过为静态
* 资源目录指定一个挂载路径的方式来实现,如下所示
* 2、现在,你就可以通过带有 “/static” 前缀的地址来访问 public
* 目录下面的文件了。
* - http://localhost:3000/static/images/kitten.jpg
* - http://localhost:3000/static/css/style.css
* - http://localhost:3000/static/js/app.js
* - http://localhost:3000/static/images/bg.png
* - http://localhost:3000/static/hello.html
*/
7、服务端渲染(模板引擎)
* 服务器渲染,后端嵌套模板,后端渲染模板,SSR(后端把页面组装)
- 做好静态页面,动态效果
- 把前端代码提供给后端,后端要把静态html以及里面的假数据给删掉,
通过模板进行动态生成html的内容
* 前后端分离,BSR(前端中组装页面)
- 做好静态页面,动态效果
- json模拟,ajax,动态创建页面
- 真实接口数据,前后联调
- 把前端提供给后端静态资源文件夹
* npm i ejs
* 需要在应用中进行如下设置才能让 Express 渲染模板文件:
- views, 放模板文件的目录,比如: app.set ('views' , './views' )
- view engine, 模板引擎,比如: app.set ('view engine' , 'ejs' )
- res.render("login" );
- res.redirect("/home" );
########
res.setHeader('Location' , 'https://www.baidu.com' )
res.statusCode = 302
res.end()
########
########
<% %>流程控制标签(写的是if else ,for )
<%= %>输出标签(原文输出html标签)
<%- %>输出标签(html会被浏览器解析)
<%# %>注释标签
<%- include('user/show' ,{user:user}) %>导入公共的模板内容
########
* 支持直接渲染html文件
- app.set ('view engine' , 'html' )
- app.engine("html" , require("ejs" ).renderFile)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通