Node笔记
Node.js中的JavaScript
node中的JavaScript是没有bom和dom的.
在node中为JavaScript提供了一些服务器级别api,比如文件操作的能力,服务器的能力.
运行一个hello world文件
1.创建编写Javascript脚本文件
2.打开终端,定位到脚本文件所属目录
3.输入node 文件名
来执行对应的文件
Node读取文件
浏览器的JavaScript是没有操作文件的能力,但是node中JavaScript文件具有文件操作的能力.
在Node中如果想要进行文件操作,就必须引入fs这个核心模块,在fs这个核心模块中,就提供所有的文件操作的相关API.
使用require方法加载fs核心模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
var fs = require('fs');
fs.readFile('he.txt',function(error,data){ if(data){ console.log(data.toString()); }else{ console.log('文件读取失败',error); } })
|
Node写入文件
1 2 3 4 5 6 7 8 9 10
| var fs = require('fs');
fs.writeFile('被Node写入的文件.txt','你好,我是被写入的Nodejs文件',function(error){ //这里回调函数只有一个参数 if(error){ console.log('文件写入失败'); }else{ console.log('文件写入成功'); } })
|
创建http服务
使用Node构建一个Web服务器.
在Node中专门提供了一个核心模块:http
http模块帮你创建web服务器.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
var http = require('http');
var server = http.createServer()
server.on('request',function(request,response){ console.log('收到客户端的请求了,请求路径是:'+request.url)
response.write('hello Nodejs'); response.end(); })
server.listen(3000,function(){ console.log('服务器启动成功了,可以通过http://localhost:3000/进行访问') })
|
灵活的服务器
灵活的服务器相当于根据不同的请求路径返回不同的数据
根据request.url来判断即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| var http = require('http'); const { type } = require('os');
var server = http.createServer()
server.on('request',function(req,res){ console.log('收到客户端的请求了,请求路径是:'+req.url) console.log('请求我客户端的地址是:'+req.socket.remoteAddress,req.socket.remotePort);
var requestUrl =req.url; if(requestUrl === '/'){ res.end('index page'); }else if(requestUrl === '/login'){ res.write('this is a login page'); res.end('login page'); }else if(requestUrl === '/products'){ var prducts = [ { name:'iphone x', price:'8888', type:'elcetronics' }, { name:'refrigerator', price:4000, type:'elcetronics' }, { name:'computer', price:8000, type:'elcetronics' } ]; res.end(JSON.stringify(prducts)); }else{ res.end('404 Not Found'); } })
server.listen(3000,function(){ console.log('服务器启动成功了,可以通过http://localhost:3000/进行访问') })
|
Node中的核心模块
Node为js提供了很多服务器级别的api,这些api绝大多数都被包装到了一个具名的核心模块中.
比如文件操作的fs
核心模块,http服务构建的http
模块,path
路径模块,os
操作系统模块.
详情见https://nodejs.org/dist/latest-v14.x/docs/api/fs.html
Node中的模块系统
在Node中,模块有三种:
1.Node自带的模块
2.用户自己编写的文件模块,需要用require方法引入,引入的时候要用相对路径引入
3.第三方模块
在Node中,没有全局作用域,只有模块作用域.各个模块中的代码不相互影响.模块是完全封闭的,外部无法访问内部,内部无法访问外部。
模块之间的通信:在每个模块中都提供了一个对象:exports
,该对象默认是一个空对象,你要做的就是把需要被外部访问使用的成员手动的挂载到exports
对象中,然后使用require
方法来加载模块,就可以的得到模块内部的exports
接口对象。
CommonJs模块化规范
node中模块系统:
1.模块作用域
2.使用require方法来加载模块
3.使用exports接口对象来导出模块中的成员
加载require
1 2 3
| var 变量名 = require('模块');
|
导出exports
node是模块作用域,默认文件中的所有成员只在当前文件模块有效
对于希望被其他模块访问的成员,我们就需要把公开的成员挂载到exports接口对象中,就可以导出多个成员了。
导出多个成员写法:
1 2 3 4 5 6 7
| exports.a = 'hello'; exports.b = function(){ console.log('function') }; exports.c = { foo:'bar' }
|
导出单个成员的写法
1 2 3 4 5 6 7 8 9 10
| module.exports = 'hello'; module.exports = function add(x,y){ return x + y; }; module.exports = { add(x,y){ return x + y; }, str:hello }
|
exports和module.exports的区别
导出多个成员:exports.XXX = XXX或者module.exports={}
导出单个成员:module.exports = XXX
require加载规则
requre加载规则是有缓存的。
1.加载文件
加载自己创建的文件,require(‘./b’),要用绝对路径去引用
2.加载核心模块
核心模块的本质也是文件,核心模块文件已被编译到了二进制文件中,只需要按照名字来加载就行了。比如require(‘fs’); require(‘http’)
3.第三方模块
第三方模块都需要npm来下载,使用的时候通过require(‘包名’)来加载使用。
1
| var template = require('art-template')
|
说以下以上导入第三方模块的过程:
1.先找到当前文件所处目录中的node_modules目录(如果当前目录中没有node_modues文件,那么系统会自动往上层目录寻找)
2.然后找到node_modules/art-template
3.然后找到node.modules/art-template/package.json文件
4.然后找到node.modules/art-template/package.json文件中的main.js
5.main.js中就记录了art-template的入口模块,即可使用
它会找当前模块的node_module目录。
npm init
命令用来初始化package包。
- dependencies属性用来保存第三方包的依赖信息。
- 在安装第三包的时候加上–sava。
npm install
命令通过package.json文件来安装之间已经安装但是不小心删除了的node_modules。
npm
常用命令:
npm install –save 包名
npm uninstall –save 包名
npm help
npm install –save -dev
ip地址和端口号
一般计算机的端口号的范围是0-65536之间
我们可以同时开启多个服务,但是要确保不同服务占用的端口号不一致才行。
关于解决中文编码识别不出问题
中文会出来乱码,原因是服务端默认发送的数据其实是utf8编码的内容,而浏览器是解析不了,所以我们要设置服务器响应的头部:
Content-Type:服务器最好把每次响应的数据的类型告诉浏览器。
1
| res.setHeader('Content-Type','text/plain;charset=utf-8');
|
在http协议中,Content-Type就是用来告诉对方我给你发送的数据是什么类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| var http = require('http'); const { type } = require('os');
var server = http.createServer()
server.on('request',function(req,res){ console.log('收到客户端的请求了,请求路径是:'+req.url) console.log('请求我客户端的地址是:'+req.socket.remoteAddress,req.socket.remotePort);
var requestUrl =req.url; if(requestUrl === '/'){ res.end('index page'); }else if(requestUrl === '/login'){ res.setHeader('Content-Type','text/plain;charset=utf-8'); res.write('这是登录页面'); res.end('login page'); }else if(requestUrl == '/html'){ res.setHeader('Content-Type','text/html;harset=utf-8'); res.end('<p>Hello world</p>点我<a href="#"></a>'); }else if(requestUrl === '/products'){ var prducts = [ { name:'iphone x', price:'8888', type:'elcetronics' }, { name:'refrigerator', price:4000, type:'elcetronics' }, { name:'computer', price:8000, type:'elcetronics' } ]; res.end(JSON.stringify(prducts)); }else{ res.end('404 Not Found'); } })
server.listen(3000,function(){ console.log('服务器启动成功了,可以通过http://localhost:3000/进行访问') })
|
引入html
引入html文件,我们使用读取文件的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| var http = require('http'); var fs = require('fs');
var server = http.createServer();
server.on('request',(req,res) => { var url = req.url; if(url === '/'){ fs.readFile('./index.html',function(err,data){ if(err){ res.setHeader('Content-Type','text/plain;charset=utf-8'); console.log('读取文件失败'); }else{ res.setHeader('Content-Type','text/html;harset=utf-8'); res.end(data); } }) }else if(url === '/pic'){ fs.readFile('./MVVM.jpg',function(err,data){ if(err){ res.setHeader('Content-Type','text/plain;charset=utf-8'); console.log('读取文件失败'); }else{ res.setHeader('Content-Type','image/jpeg'); res.end(data); } }) } })
server.listen(3000,function(){ console.log('服务器启动成功了,可以通过http://localhost:3000'); console.log('来访问'); })
|
读取目录
读取目录使用readdir方法进行读取
在Node中使用模板引擎
什么是模板引擎?模板引擎是为了使用户界面与业务数据(内容)分离而产生,它可以生成特定格式的文档,用于网站的的模板引擎就会生成一个标准的文档。
自己制作模板引擎:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| var http = require('http'); var fs = require('fs'); var server = http.createServer()
var WWW = './www'
server.on('request',(req,res) => { requestUrl = req.url; if(requestUrl == '/'){ fs.readFile('./template.html',(err,data) => { if(err){ return res.end('404,Not Found'); } fs.readdir(WWW,function(err,files){ if(err){ return res.end('Can not find directory'); }else{ var content = ''; files.forEach(function(item){ content += ` <tr> <td>${item}/</td> <td>46kb</td> <td>2020-5-30</td> </tr>` }) data = data.toString(); data = data.replace('main',content); res.end(data); } }) })
}else if(requestUrl == '/register'){ res.end('this is a register page'); }else{ res.end('404 Not Found'); } })
server.listen(3000,() => { console.log('service is runing,please click http://localhost:3000 to access'); })
|
art-template模板
安装模板:
1
| npm install art-template --save
|
引用模板:
1
| var template = require('art-template')
|
模板引擎解析出来的都是字符串,所以模板引擎是不关心内容的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var template = require('art-template'); var fs = require('fs');
fs.readFile('./tpl.html',function(err,data){ if(err){ return console.log('读取文件失败'); } data = data.toString(); var result = template.render(data,{ name:'xhh', age:20, address:'云南大理' }) console.log(result); })
|
tpl.html文件:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <!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> <h1>{{name}}</h1> <h1>{{age}}</h1> <h1>{{address}}</h1> </body> </html>
|
最终渲染结果:
所以模板引擎是不关心内容的,它解析的都是字符串。
使用art-template
模板替换先前写的原生模板引擎:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| var http = require('http'); var fs = require('fs'); var server = http.createServer(); var template = require('art-template');
var WWW = './www'
server.on('request',(req,res) => { requestUrl = req.url; if(requestUrl == '/'){ fs.readFile('./apache-file.html',(err,data) => { if(err){ return res.end('404,Not Found'); } fs.readdir(WWW,function(err,files){ if(err){ return res.end('Can not find directory'); }else{ var htmlresult = template.render(data.toString(),{ title:'哈哈', files:files }) res.end(htmlresult); } }) })
}else if(requestUrl == '/register'){ res.end('this is a register page'); }else{ res.end('404 Not Found'); } })
server.listen(3000,() => { console.log('service is runing,please click http://localhost:3000 to access'); })
|
apache-file.html文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{title}}</title> <style> table,th, td{ border: 1px solid black; text-align: center; } </style> </head> <body> <h2>F:\Node文件\第二天\www的索引</h2> <table style="border: 1px solid blue;width: 500px;"> <tr> <th>名称</th> <th>大小</th> <th>修改日期</th> </tr> {{each files}} <tr> <td>{{$value}}/</td> <td>46kb</td> <td>2020-5-30</td> </tr> {{/each}} </table> </body> </html>
|
客户端渲染和服务端渲染
客户端渲染不利于SEO搜索引擎优化
服务端渲染是可以被爬虫抓取到的,客户端渲染(异步)是很难被爬虫抓取的
所以真正的网站不是纯异步也不是纯服务端渲染出来的。
服务端渲染:在服务端使用模板引擎
静态资源的引入
统一把静态资源放到public目录下,然后再readFile()方法来进行访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| var http = require('http') var fs = require('fs')
http .createServer(function(req,res){ var url = req.url; if(url === '/'){ fs.readFile('./views/index.html',(err,data) => { if(err){ return res.end('404 Not Found') } res.end(data); }) }else if(url.indexOf('/public/') === 0){ fs.readFile('.'+url,function(err,files){ if(err){ return res.end('文件不存在'); } res.end(files); }) }else{ fs.readFile('./views/404.html',(err,data) => { if(data){ res.end(data) } }) } })
.listen(3000,function(){ console.log('Service is running,please access http://localhost:3000') })
|
Express
Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。
先安装Express框架:
1
| npm install --save express
|
使用框架后的写服务器代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var express = require('express')
var app = express();
app.use('/public/',express.static('./public/'));
app.get('/',function(req,res){ res.send('hello world') })
app.get('/login',function(req,res){ res.send('这是关于页面') })
app.listen(3000,function(){ console.log('service is running,please access '+ 'http://localhost:3000 '+' to access') })
|
express中使用模板引擎
安装art-template
1 2
| npm install --save art-template npm install --save express-art-template
|
使用art-template
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| var express = require('express')
var app = express();
app.use('/public/',express.static('./public/'));
app.engine('html',require('express-art-template'));
app.get('/',function(req,res){ res.render('hello.html',{ title:'管理系统' }); })
app.get('/login',function(req,res){ res.send('这是登录页面') }) app.get('/about',function(req,res){ res.send('这是关于页面') })
app.listen(3000,function(){ console.log('service is running,please access '+ 'http://localhost:3000 '+' to access') })
|
如果想要修改默认的views目录,则使用app.set(‘views’,render函数的默认路径)
在express中获取表单GET请求参数
在express中获取表单POST请求体数据
在express中没有内置获取表单请求体的api,这里我们需要使用一个第三方包:body-parser
。
安装:
1
| npm install --save body-parser
|
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var express = require('express')
var bodyParser = require('body-parser')
var app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(function (req, res) { res.setHeader('Content-Type', 'text/plain') res.write('you posted:\n') res.end(JSON.stringify(req.body, null, 2)) })
|
修改完代码自动重启服务器
nodemon
是一个基于nodejs开发的一个第三方命令行工具,作用是解决每次修改完代码后重启服务器的问题。
安装:
1 2
| npm install --global nodemon //全局安装就是在任意目录都可以安装
|
通过nodemon 文件名
来启动服务,当文件发生修改的时候,自动重启服务器。
回调函数
1 2 3 4 5 6 7 8 9 10 11
| function test(callback){ var a; setTimeout(function(){ a = 10; callback(a) },1000) } test(callback) function callback(result){ console.log(result) }
|
1 2 3 4 5 6 7 8 9 10 11
| function add(x,y,callback){ var ret; setTimeout(function(){ ret = x+y callback(ret) },1000) console.log(ret) } add(10,20,function(ret){ console.log(ret) })
|
js异步在于单线程。如果不异步得卡死掉。
ajax是如何分装的?
1 2 3 4 5 6 7 8 9
| <script> var xhr = new XMLHttpRequest(); xhr.onload = function(){ console.log(xhr.responseText) } xhr.open("get","data.json",true) xhr.send() </script>
|
经过异步操作之后:
核心:往里传回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script> function get(url,callback){ var xhr = new XMLHttpRequest(); xhr.onload = function(){ callback(xhr.responseText) } xhr.open("get",url,true) xhr.send() }
get('data.json',function(data){ console.log(data) }) </script>
|
输出结果是一样的。
ES6 find和findIndex源码的封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var user = [ {id:1,name:'xhh',age:12}, {id:2,name:'xhh2',age:12}, {id:3,name:'xhh3',age:12}, {id:4,name:'xhh4',age:12}, ] Array.prototype.myFind = function(condition){ for(var i=0;i<this.length;i++){ if(condition(this[i])){ return this[i] } } }
var ret = user.myFind(function(item){ return item.id === 4 }) console.log(ret)
|
1 2 3 4 5 6 7 8 9 10 11 12
| Array.prototype.myFind = function(condition){ for(var i=0;i<this.length;i++){ if(condition(this[i])){ return i } } }
var ret = user.myFind(function(item){ return item.id === 4 }) console.log(ret)
|
MongoDB数据库
关系型数据库与非关系型数据库
关系型数据库
- 所有的关系型数据库都需要通过
sql
语言来执行
- 所有的关系型数据库在操作之前都需要设计表结构
- 数据表支持约束
非关系型数据库
启动和关闭数据库
mongoDB默认执行mongod命令所处盘符根目录下的 /data/db 作为自己的数据存储目录。所以在第一次执行该命令之前先自己手动创建一个 /data/db。
如果想要修改默认的数据存储目录,可以
1
| mongod --dbpath=数据存储路径目录
|
基本命令
在node中操作mongoDB
使用第三方包mongooes来操作mongoDB数据库。
Node操作mysql数据库
安装:npm install mysql
用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| var mysql = require('mysql');
var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : 'admin', database : 'nodetest' });
connection.connect();
connection.query('SELECT * FROM `users`', function (error, results, fields) { if (error) throw error; console.log('The solution is: ', results); });
connection.end();
|
回调地狱
回调地狱的形成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var fs = require('fs')
fs.readFile('./file/a.txt','utf8',function(err,data){ console.log(data) })
fs.readFile('./file/b.txt','utf8',function(err,data){ if(err) throw err console.log(data) })
fs.readFile('./file/c.txt','utf8',function(err,data){ if(err) throw err console.log(data) })
|
因为js的readFile方法是异步代码,所以执行文件之后,它并不是按顺序输出的。
解决的方法是进行嵌套,按顺序执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var fs = require('fs')
fs.readFile('./file/a.txt','utf8',function(err,data){ if(err) throw err console.log(data); fs.readFile('./file/b.txt','utf8',function(err,data){ if(err) throw err console.log(data); fs.readFile('./file/c.txt','utf8',function(err,data){ if(err) throw err console.log(data) }) }) })
|
如果出现嵌套过多的话,代码会没有可读性,不易维护。
Promise
为了解决以上编码方式代码的问题(回调地狱嵌套),所以在ES6中新增了一个API:Promise
。
Promise的使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| var fs = require('fs')
var p1 = new Promise(function(resolve,reject){ fs.readFile('./file/a.txt','utf8',function(err,data){ if(err) reject(err) resolve(data) }) })
var p2 = new Promise(function(resolve,reject){ fs.readFile('./file/b.txt','utf8',function(err,data){ if(err) reject(err) resolve(data) }) })
var p3 = new Promise(function(resolve,reject){ fs.readFile('./file/c.txt','utf8',function(err,data){ if(err) reject(err) resolve(data) }) })
p1.then(function(data){ console.log(data) return p2 },function(err){ console.log(err) }).then(function(data){ console.log(data) return p3 },function(err){ console.log(err) }).then(function(data){ console.log(data) },function(err){ console.log(err) })
|
封装Promise方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| var fs = require('fs')
function pReadFile(filePath){ return new Promise(function(resolve,reject){ fs.readFile(filePath,'utf8',function(err,data){ if(err) reject(err) resolve(data) }) }) }
pReadFile('./file/a.txt') .then(function(data){ console.log(data) return pReadFile('./file/b.txt') },function(data){ console.log(data) }) .then(function(data){ console.log(data) return pReadFile('./file/c.txt') },function(err){ console.log(err) }) .then(function(data){ console.log(data) },function(err){ console.log(err) })
|
Promise案例
data.json文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| { "users":[ { "id":1, "username":"admin", "age":18, "job": 3 }, { "id":2, "username":"admin2", "age":18, "job": 2 }, { "id":3, "username":"admin3", "age":18, "job": 1 } ], "jobs":[ { "id":1, "name":"学生" }, { "id":2, "name":"程序员" }, { "id":3, "name":"司机" }, { "id":4, "name":"画家" }, { "id":5, "name":"医生" } ] }
|
主文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| <!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 id="user_from"> </form> <script type="text/template" id="tpl"> <div> <label for="">用户名</label> <input type="text" name="" id="" value="{{user.username}}"> </div> <div> <label for="">年龄</label> <input type="text" name="" id="" value="{{user.age}}"> </div> <div> <label for="">职业</label> <select name="" id=""> {{each jobs}} {{if user.job === $value.id}} <option value="{{$value.id}}" selected>{{$value.name}}</option> {{else}} <option value="{{$value.id}}">{{$value.name}}</option> {{/if}} {{/each}} </select> </div> </script>
<script src="node_modules/art-template/lib/template-web.js"></script>
<script>
get('http://localhost:3000/users/3',function(userData){ get('http://localhost:3000/jobs',function(jobsData){ user = JSON.parse(userData) jobs = JSON.parse(jobsData) console.log(user) console.log(jobs) var htmlStr = template('tpl',{ user:user, jobs:jobs }) console.log(htmlStr) document.querySelector('#user_from').innerHTML = htmlStr }) })
function get(url,callback){ var xhr = new XMLHttpRequest(); xhr.onload = function(){ callback(xhr.responseText) } xhr.open("get",url,true) xhr.send() } </script> </body> </html>
|
渲染结果:
以上方式容易产生回调地狱,所以使用Promise改进:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| <!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 id="user_from"> </form> <script type="text/template" id="tpl"> <div> <label for="">用户名</label> <input type="text" name="" id="" value="{{user.username}}"> </div> <div> <label for="">年龄</label> <input type="text" name="" id="" value="{{user.age}}"> </div> <div> <label for="">职业</label> <select name="" id=""> {{each jobs}} {{if user.job === $value.id}} <option value="{{$value.id}}" selected>{{$value.name}}</option> {{else}} <option value="{{$value.id}}">{{$value.name}}</option> {{/if}} {{/each}} </select> </div> </script>
<script src="node_modules/art-template/lib/template-web.js"></script> <script src="node_modules/jquery/dist/jquery.js"></script>
<script> var data = {} $.get('http://localhost:3000/users/2') .then(function(user){ data.user = user return $.get('http://localhost:3000/jobs') }) .then(function(jobs){ data.jobs = jobs var htmlStr = template('tpl',{ user:data.user, jobs:data.jobs }) console.log(data) console.log(htmlStr) document.querySelector('#user_from').innerHTML = htmlStr }) </script> </body> </html>
|
封装Promise版的ajax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function get(url,callback){ return new Promise(function(resolve,reject){ var xhr = new XMLHttpRequest(); xhr.onload = function(){ resolve(JSON.parse(xhr.responseText)) callback && callback(JSON.parse(xhr.responseText)) } xhr.onerror = function(err){ reject(err) } xhr.open("get",url,true) xhr.send() }) }
|
然后直接以Promise的方式去调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var data = {} get('http://localhost:3000/users/2') .then(function(user){ data.user = JSON.parse(user) return $.get('http://localhost:3000/jobs') }) .then(function(jobs){ data.jobs = jobs var htmlStr = template('tpl',{ user:data.user, jobs:data.jobs }) console.log(data) console.log(htmlStr) document.querySelector('#user_from').innerHTML = htmlStr })
|
或者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var data = {} get('http://localhost:3000/users/2',function(user){ data.user = user return get('http://localhost:3000/jobs',function(jobs){ data.jobs = jobs var htmlStr = template('tpl',{ user:data.user, jobs:data.jobs }) console.log(data) console.log(htmlStr) document.querySelector('#user_from').innerHTML = htmlStr }) })
|
json-server
安装:npm install -g json-server
启动json-server
1
| json-server --watch json文件名
|
默认3000端口,当然我们也可以指定端口,这样就可以监听多个json文件:
1
| json-server --watch -port 8888 json文件名
|