node
node采用EcmaSaipt进行编码。
node没有bom和dom
node中的JavaScript有文件操作的能力
读文件
// fs是file-system的简写,就是文件系统的意思
// 在node中想进行文件操作,就鼻血 引入fs这个核心模块
// 在fs核心模块中,就提供了所有文件操作相关的api
// 列如:fs.readFile就是用来读取文件的
// 1.使用require方法加载fs核心模块
var fs = require('fs')
// 2.读取文件
// 第一个参数是读取文件的路径
// 第二个是一个回调函数
// error 和 data
fs.readFile('./data/hello.txt',function(error,data){
console.log(data)
// <Buffer 68 61 69>
// 这是十六进制,所以要用toString方法把其转化为我们能认识的文字
console.log(data.toString())
})
写文件
//写文件
var fs = require('fs')
// 第一个参数:文件路径
// 第二个参数:文件内容
// 第三个参数:回调函数
fs.writeFile('./data/你好.md','大家好,我是node.js',function(error){
console.log('文件写入成功')
})
node的http搭建服务器
// 使用node构建一个web服务器
// 在node中提供了一个核心模块:http
// http这个模块就是帮你创建编写服务器的
// 1.加载hhtp核心模块
var http =require('http')
// 2.使用http.createServer()方法创建一个web服务器
// 返回一个server实例
var server= http.createServer()
// 3.服务器要干嘛?
// 提供服务:数据服务
// 发送请求,接受请求,处理请求,给个反馈。
// 注册request请求事件
// 当客户端请求过来,就会自动触发服务器的request请求事件,然后执行第二个参数:回调处理函数
server.on('request',function(){
console.log("收到客户端的 请求了")
})
// 4.绑定端口号,启动服务器
server.listen(3000,function(){
console.log("服务器启动成功了,可以通过http://127.0.0.1:3000/来进行访问")
})
意思就是收到客户端请求但是没有给反馈所以浏览器会一直转圈圈
node的res请求和响应
var http =require('http')
var server= http.createServer()
// request请求事件处理函数,需要接受两个参数:
// Request 请求对象
// 请求对象 可以用来获取客户端 的一些 请求信息,列如请求路径
// Response 响应对象
// 响应对象可以用来客户端发送响应消息
server.on('request',function(request,Response){
console.log("收到客户端的 请求了,请求路径是" + request.url)
// response 对象有一个方法:write 可以用来给客户端发送响应数据
// write可以使用多次,但是一定要使用end来结束响应,否则客户端会一直等待。
// Response.write('hello')
// Response.write('node.js')
// 上面的方式比较麻烦,推荐使用更简单的方式,直接end的同时发送数据
// Response.end("hello,world")
// 根据不同的请求路径发送不同的响应结果
// 1.获取请求路径
// request.url 获取到的是端口号之后到的那一部分路径,也就是说所有的url都是以 /开头的
// 2.判断路径处理响应
var url =request.url
if(url ==="/"){
Response.end('index page')
}else if(url ==="/login"){
Response.end("login page")
}else{
Response.end("404 Not Found")
}
})
server.listen(3000,function(){
console.log("服务器启动成功了,可以通过http://127.0.0.1:3000/来进行访问")
})
注意:json.parse()可以转化 为对象
json.stringify()可以转成字符串json
node中的JavaScript
核心模块
node为JavaScript提供了很多服务器级别的API ,这些API绝大多数 都被包装到了一个具名的核心模块中了。
列如文件操作的fs核心模块,http服务构建的http模块,path路径操作模块,os操作系统信息模块。。。。
只要是核心模块就必须引入
var fs = require("fs")
请上node的官网查看
列如:
简单的模块化
**在node中,没有全局作用域,只有模块作用域
**
外部访问不到内部,内部也访问不到外部
简单的模块化加载与导出
ip地址和 端口号
在http的模块中使用
ip地址用来定位计算机
端口号用来定位具体的应用程序
所有需要联网通信的应用程序都会占用一个端口号。
var http =require('http')
var server= http.createServer()
server.on('request',function(request,Response){
console.log("收到客户端的 请求了,请求路径是" + request.url)
console.log("请求我的客户端的地址是:",request.socket.remoteAddress,request.socket.remotePort)
var url =request.url
if(url ==="/"){
Response.end('index page')
}else if(url ==="/login"){
Response.end("login page")
}else{
Response.end("404 Not Found")
}
})
server.listen(3000,function(){
console.log("服务器启动成功了,可以通过http://127.0.0.1:3000/来进行访问")
})
网页的响应内容类型Content-Type
var http =require('http')
var server= http.createServer()
server.on('request',function(req,res){
//在服务端默认发送的 数据,其实是utf8编码的内容
//但是浏览器不知道 是utf8编码内容
// 浏览器在不知道服务器响应内容的编码情况下 会 按照 当前操作系统的默认编码去解析
//中文操作系统默认是gbk
//解决方法就是正确的告诉浏览器我给你发送的内容是什么编码的。
// 在http协议中Content-Type就是用来告知对方我给你发送的数据内容是什么类型。
var url=req.url
if(url ==='/pain'){
// text/plain就是普通文本的意思
res.setHeader('Content-Type','text/plain; charset=utf8')
res.end('hello 世界')
}else if (url === '/html'){
// text/html就是html格式的意思
res.setHeader('Content-Type','text/html; charset=utf8')
res.end('<p>hello,world</p><a href="">点我</a>')
}
})
server.listen(3000,function(){
console.log('Server is running...')
})
发送文件中的数据以及Content-Type内容类型
//1.结合fs发送文件中的数据
//2.Content-Type
// http://tool.oschina.ent/commons
// 不同的资源对应的Content-Type是不一样的
//图片不需要指定编码
// 一般只为字符数据才指定编码
var http =require('http')
var fs =require('fs')
var server= http.createServer()
server.on('request',function(req,res){
var url=req.url
if(url ==='/'){
fs.readFile('./views/index.html',function(err,data){
if(err){
res.setHeader('Content-Type','text/plain; charset=utf8')
res.end('文件读取失败,请稍后重试!')
}else{
//res.end()支持两种数据类型支持,一种是二进制,一种是字符串
res.setHeader('Content-Type','text/html; charset=utf8')
res.end(data)
}
})
}else if(url === '/img'){
//url:统一资源定位符
//一个url最终其实是要对应到一个资源的
fs.readFile('./views/1.jpg',function(err,data){
if(err){
res.setHeader('Content-Type','text/plain; charset=utf8')
res.end('文件读取失败,请稍后重试!')
}else{
res.setHeader('Content-Type','image/jpeg')
res.end(data)
}
})
}
})
server.listen(3000,function(){
console.log('Server is running...')
})
像Apach一样的路径跳转方式
Apach默认有一个www目录,所有存放在www目录中的资源都可以通过网址来浏览
这个是文件的存放路径
这个是优化过后
注意:<meta charset="utf8>
就可以解析中文了
使用模板引擎art-template
art-template 不仅可以在浏览器使用也可以在node中使用
安装 install art-template
该命令在哪执行就会 把包 下载到哪里。默认会下载到node_modules目录中
node_modules不要改也不支持改
在node中使用了art-template模板引擎
模板引擎最早就是诞生于服务器领域,后来才发展到了前端。
在浏览器中使用模板引擎
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<!-- 注意在浏览器中需要引用文件 -->
<!-- 强调:模板引擎不关心你的字符串内容,只关心自己能认识的模板标记语法,例如{{}} -->
<script src="./template-web.js" type="text/javascript" charset="utf-8"></script>
<script type="text/template" id="tpl">
hello{{name}}
我喜欢:{{each hobbies}} {{$value}} {{/each}}
</script>
<script type="text/javascript">
var ret =template('tpl',{
name:"jack",
hobbies:[
'写代码',
'唱歌',
'打游戏'
]
})
console.log(ret)
</script>
</body>
</html>
在node中 使用模板引擎
//art-template
//art-template 不仅可以在浏览器使用也可以在node中使用
//安装 install art-template
//该命令在哪执行就会 把包 下载到哪里。默认会下载到node_modules目录中
//node_modules不要改也不支持改
//在node中使用了art-template模板引擎
//模板引擎最早就是诞生于服务器领域,后来才发展到了前端。
// 1.加载art-template
var template = require('art-template')
// 2.加载在fs模块
var fs=require('fs')
fs.readFile('./tpl.html',function(err,data){
if(err){
return console.log('读取文件失败了')
}
//默认读取到的 data是二进制数据
//而模板引擎的 render方法需要接受的是字符串
//所以我们这里需要把data二进制数据转为字符串,才可以 给模板引擎使用
var ret = template.render(data.toString(), {
name: "jack",
hobbies: [
'写代码',
'唱歌',
'打游戏'
]
})
console.log(ret)
})
客户端渲染和服务器渲染
客户端渲染
服务端渲染
注意:只要操作会使页面刷新的就是服务端渲染,不会刷新的就是客户端渲染。
处理网站中的静态资源
// app Application 应用程序
// 为了让目录结构保持统一清晰,所以我们决定,把所有的html文件都放在views中
//我们为了方便的统一处理这些静态 资源,所以我们约定吧所有的静态资源都存放在public目录中
//那些资源能被用户访问,那些资源不能被用户访问,我现在可以通过代码来进行非常灵活的控制
var http = require('http')
var fs = require('fs')
var server = http.createServer()
server.on('request',function(req,res){
var url = req.url
if (url === '/') {
fs.readFile('./views/index.html', function(err, data) {
if (err) {
return res.end('404 Not Found')
}
res.end(data)
})
}
else if (url.indexOf('/public/') === 0) {
// /publlic/css/main.css
// /public/js/main.js
// /public/lib/juqery.js
// //统一处理:
// // 如果请求路径是以/publi/开头的,则我认为你要获取public中的某个资源
// // 所以我们就直接可以把请求路径当做文件路径来直接进行获取。
// console.log(url)
fs.readFile('.'+url,function(err,data){
if(err){
return res.end('404 Not Found')
}
res.end(data)
})
}
})
server.listen(3000, function() {
console.log('runing...')
})
在index中
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<!--
浏览器收到html响应内容之后,就要开始从上到下依次解析,
当在解析的过程中,如果发现
link
script
img
iframe
video
audio
等带有src或者href(link)
属性标签(具有外链的 资源)的时候,浏览器会自动对这些资源发起新的请求。
-->
<!-- <link rel="stylesheet" type="text/css" href="../../views/main.css"/> -->
<!--
注意:在服务端中,文件中的路径就不要去写相对路径了。
因为这个时候所有的资源都是通过url标识来获取的
我的服务器开放了/public/目录
所以这里的请求路径都写成:/pulic/xxx
/在这里就是url根路径的意思。
浏览器在真正发请求的时候回自动把http://127.0.0.1:3000拼上
-->
<!-- <link rel="stylesheet" type="text/css" href="/public/lib/bootstrp/dist/css/bootstrap.css"/> -->
</head>
<body>
<img src="/public/img/1.jpg" >
<h1>这是首页</h1>
</body>
</html>
关于留言板表单提交的小练习
里面涉及到的就是走通页面跳转 加入404处理
渲染评论 首页
处理表单get提交
表单提交重定向
1.创建一个反馈留言的文件夹(feedback)
依次创建如下 文件
2.给对应的文件创建内容
node_modules:下载art-template模板引擎
public:中放所有开放的资源例如css img js 还有一个lib文件夹 里放jquery之类的
views:放我们的html页面
app.js就是所有的入口
接下来开始写留言板首页和评论页面
首页:index.html页面
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<!--
浏览器收到html响应内容之后,就要开始从上到下依次解析,
当在解析的过程中,如果发现
link
script
img
iframe
video
audio
等带有src或者href(link)
属性标签(具有外链的 资源)的时候,浏览器会自动对这些资源发起新的请求。
-->
<!-- <link rel="stylesheet" type="text/css" href="../../views/main.css"/> -->
</head>
<body>
<img src="/public/img/1.jpg" >
<h1>这是首页</h1>
<ul>
{{each comments}}
<li>{{$value.name}}说:{{$value.message}}--{{$value.dataTime}}</li>
{{/each}}
<li>
</li>
</ul>
<script src="/public/js/main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
然后是评论区的页面:post.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
</head>
<body>
<h1>这是post页面</h1>
<h2><a href="/">首页</a></h2>
<!--
以前表单是如何提交的?
表单中需要提交的表单控件元素必须具有name属性
表单提交分为:
1.默认的提交行为
2.表单异步提交
action就是表单提交的地址,说白了就是 请求的url地址
method 请求方法
get
post
-->
<form action="/pinglun" method="get">
<label for="input_name">你的名字</label>
<input type="text" required minlength="2" maxlength="10" id="input_name" name="name"><br>
<!-- required minlength="2" maxlength="10"这是验证长度最长和最短 -->
<label for="form-message">留言内容</label>
<textarea required minlength="5" maxlength="20" rows="10" cols="30" id="form-message" name="message">
</textarea>
<button type="submit">发表 </button>
</form>
</body>
</html>
最后是所有的入口:app.js
// app Application 应用程序
// 为了让目录结构保持统一清晰,所以我们决定,把所有的html文件都放在views中
//我们为了方便的统一处理这些静态 资源,所以我们约定吧所有的静态资源都存放在public目录中
//那些资源能被用户访问,那些资源不能被用户访问,我现在可以通过代码来进行非常灵活的控制
var http = require('http')
var fs = require('fs')
var template =require('art-template')
var server = http.createServer()
var url =require('url')
var comments=[
{
name:"小叶",
message:"今天天气不错",
dataTime:"2020-11-12"
},
{
name:"小叶1",
message:"今天很困",
dataTime:"2020-11-12"
},
{
name:"小叶2",
message:"今天天气不错",
dataTime:"2020-11-12"
},
{
name:"小叶3",
message:"今天天气不错",
dataTime:"2020-11-12"
},
{
name:"小叶4",
message:"今天天气不错",
dataTime:"2020-11-12"
},
{
name:"小叶5",
message:"今天天气不错",
dataTime:"2020-11-12"
},
]
// /pinglun?name=你好&message=这是电动机%09%09%09
// 对于这种表单提交的请求路径,由于其中具有用户动态 填写的内容
//所以你不可能通过 去判断完整的url来处理这个请求
//结论:对于我们来讲,其实只需要判定,如果你的请求路径是/pinglun的时候,那我就认为你提交的 表单请求过来
server.on('request', function(req, res) {
//使用url.parse 方法将路径解析为一个方便操作的对象,第二个参数true表示直接将查询字符串3为一个对象(通过query属性来访问)
var parseObj=url.parse(req.url,true)
//单独获取不包括查询字符串的路径部分(该路径不包含?之后的内容)
var pathname=parseObj.pathname
if (pathname === '/') {
fs.readFile('./views/index.html', function(err, data) {
if (err) {
return res.end('404 Not Found')
}
var htmlStr=template.render(data.toString(),{
comments:comments
})
res.end(htmlStr)
})
} else if (pathname.indexOf('/public/') === 0) {
// /publlic/css/main.css
// /public/js/main.js
// /public/lib/juqery.js
// //统一处理:
// // 如果请求路径是以/publi/开头的,则我认为你要获取public中的某个资源
// // 所以我们就直接可以把请求路径当做文件路径来直接进行获取。
// console.log(url)
fs.readFile('.' + pathname, function(err, data) {
if (err) {
return res.end('404 Not Found')
}
res.end(data)
})
}else if (pathname === '/post') {
fs.readFile('./views/post.html', function(err, data) {
if (err) {
return res.end('404 Not Found')
}
res.end(data)
})
}else if (pathname==='/pinglun'){
//注意:这个时候无论/public?xxx之后是什么,我都不用担心了,因为我的pathname是不包含?的那个路径
//一次请求就对应一次响应若果有两次响应,就执行第一个响应,后面都不执行了
// res.end(JSON.stringify(parseObj.query))
//我们已经使用url模块的parse方法把请求路径中的查询字符串给解析成一个对象
//所以接下来要做的就是:
//1.获取表单提交的数据parseObj.query
//2.生成日期到数据对象中,然后存储到数组中
//3.让用户重定向跳转到首页/
// 当用户重新请求/的时候,我数组中的数据已经发生变化了,所以用户看到的页面也就变了
var comment=parseObj.query
comment.dataTime='2020-11-12-17:49:49'
comments.push(comment)
//服务端这个时候已经把数据 存储好了,接下来就是 让用户重新请求/首页 ,就可以看到最新的留言内容了
//如何通过服务器让客户端重定向?
//1.状态码设置为302临时重定向
// statusCode
//2.在响应头中通过Location告诉客户端往那儿重定向
// setHeader
//如果客户端发现收到服务器的响应的状态码是302就会自动去响应头中找Loction,然后对该地址 发起新的请求
//所以你就能看到客户端自动跳转了
console.log('收到表单请求了',parseObj.query)
res.statusCode=302
res.setHeader('Location','/')
res.end()
}else {
//其他都处理成 404
fs.readFile('./views/404.html', function(err, data) {
res.end(data)
})
}
console.log(pathname)
})
server.listen(3000, function() {
console.log('runing...')
})
关于状态码的小补充