node.js

一、安装 Nodejs

1、下载Nodejs

下载网址:https://nodejs.org

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZ5Fddk9-1660484273428)(E:\3.插入到md的图片\图片.png)]

2、npm 包管理器

安装好了 nodejs 后,npm 就已经在电脑中

npm 仓库地址:https://www.npmjs.com/

npm -v----查询版本号

3、切换 npm 源

3.1使用nrm 管理 npm 镜像源

nrm 是一个 npm 源管理器,允许你快速地在 npm 源间切换。npm 默认情况下是使用 npm 官方
源(npm config list 来查看),如果直接修改 npm 源,如果后续需要连接到官方源才能工作,
这样来回切换源就变得麻烦了,nrm 通过简单的命令就可以解决此问题。

# 全局安装
npm i nrm -g

# 查看可用源
nrm ls

# 切换
nrm use 名称(npm)

4、生成 JSON 配置文件

# 初始化生成 package.json 文件 → 项目中使用 npm 安装软件的记录文件
npm init -y[不询问]
packename 包名(包名也不能和已经存在的包同名 wu-jquery)
version 版本
description 描述
main 入口文件
scripts 支持的脚本,默认是一个空的 test
keywords 关键字,有助于在人们使用 npm search 搜索时发现你的项目
author 作者
license: 版权许可证(默认:ISC)
dependencies 在生产环境中需要用到的依赖 –- 项目上线时会将 dependencies 下的包一起打
包, 项目上线以后依然可用.
devDependencies 在开发、测试环境中用到的依赖 -- 在本机开发时此时需要用到, 项目上线时不会
将 devDependencies 下的包打包, 也就是项目上线后不需要使用.

5、安装模块

# 安装模块 最新版本
npm install 模块名 或 npm i 模块名
# 安装模块 指定版本
npm install 模块名@版本号 或 npm i 模块名@版本号
# 卸载已安装模块
npm uninstall 模块名 或 npm uni 模块名
# 查看全局 node_modules 的地址
npm root -g
## 安装参数
npm i 模块名 --save模块名
npm i 模块名 --S记录生产环境所需模块并写入 dependencies(没有指定该参数时默认使用该参数)

pm i 模块名 --dev模块名
npm i 模块名 --D记录生产环境所需模块并写入 dependencies(没有指定该参数时默认使用该参数)

6、查看当前安装的模块

# 查看本项目已安装模块
npm list

# 查看包可用版本
npm view jquery versions

npm i -S jquery@2.*

7、自定义脚本命令

通过 package.json 文件中的 scripts 自定义脚本命令

{
"scripts": {
"test": "echo hello"
}
}
# 运行命令
npm run test

8、自动重启应用

# 全局安装 nodemon
npm i -g nodemon
# 执行 node 脚本
nodemon app.js
// 一个 web 服务,启动后会在内存在运行,而我们修改的是磁盘中的文件
// 修改后的文件不会立即更新到服务中,手动重启,在生产环境中正常,开发环境如果频繁的这样操作,
开发效率无从谈起。需要一个能够监听文件的修改,一旦有修改文件就是自动更新到内存服务中
// 启动文件
// 使用 nodemon 之前运行 nodejs 文件 node 文件名.js
// 使用 nodemon 之后运行 nodejs 文件 nodemon 文件名.js

二、 模块化

➢ 核心模块 - 安装 nodejs 时自带的模块
➢ 第三方模块 - 需要手动通过(npm/yarn)来进行安装
➢ 自定义模块 - 开发者自己编写的模块 (一个文件就是一个模块)

1.模块导入导出

导出 module.exports/exports
导入 require require 导入是以单例模式,导入相同的对象,全局只有一个实例

2、 常用内置模块

2.1、path 模块

path 模块用于操作文件和文件夹的路径

var path = require('path');
//path 内置模块, 处理文件路径(拼接)
var str1 = 'day01-nodejs';
var str2 = '../static';
var str3 = 'css';
var res = path.join(str1,str2,str3)

//一个文件的全路径( D:/xx/yy/zz.html )
//__dirname 当前文件所在文件夹的路径( 默认从盘符开始 )
var res = path.join( __dirname,'static','index.html' );

//拼接json文件的全路径(加上盘幅的那种)
var jsonfile = path.join( __dirname,'json','index.json' );
2 2、 url 模块

url 模块用于解析 url 地址字符串,URL 字符串是结构化的字符串,包含多个含义不同的组成
部分。 解析字符串后返回的 URL 对象,每个属性对应字符串的各个组成部分

var url = require('url');
//url 是内置模块, 解析url地址
//http://baidu.com/xxx/index.html?user=admin&pass=1234
var str = 'http://baidu.com/xxx/index.html?user=admin&pass=1234&email=1788847773@qq.com';
var res = url.parse( str );//得到的是一个对象形式的,找到里面的search
res.search======//?user=admin&pass=1234&email=1788847773@qq.com';
var res = querystring.parse( res.search.slice(1) )//user=admin&pass=1234&email=1788847773@qq.com';
console.log(res.user,res.pass);

//自己封装的函数
//?user=admin&pass=1234&email=1788847773@qq.com';
function parseSearch(data){
    var arr1 = data.split('&'); //['user=aedmin','pass=1234']
    var obj = {};
    arr1.forEach((item)=>{
        var arr2 = item.split('='); //['user','admin']
        obj[arr2[0]] = arr2[1];//给obj对象添加新属性
    })
    return obj;
}
console.log( parseSearch( res.search.slice(1) ) );

2.3 、querystring 模块

用于解析和格式化 URL 查询字符串, 可以方便将 url 查询字符串解析为对象,或者将对象转
换为查询字符串形式.

const querystring = require('querystring')
# query 字符串转为对象
querystring.parse('foo=bar&abc=xyz')
# 对象转为 query 字符串
querystring.stringify({ foo: 'bar',abc: 'xyz'})
2.4 、fs 模块

fs 模块提供了用于与文件进行交互相关方法(读取文件内容,写入数据到文件)

const fs = require('fs')

# 读取文件中数据
fs.readFileSync(文件, 'utf8’)
# 写入数据
fs.writeFile(文件路径,数据)
# 检查文件是否存在 返回 true/false
fs.existsSync(path)
# 删除文件
fs.unlink(文件,err=>{})
var path = require('path');
var fs = require('fs'); // file system
//path 内置模块, 处理文件路径(拼接)
//fs 内置模块, 处理文件(做文件内容的读/写)
var str1 = 'day01-nodejs';
var str2 = '../static';
var str3 = 'css';
var res = path.join(str1,str2,str3)
//一个文件的全路径( D:/xx/yy/zz.html )
//__dirname 当前文件所在文件夹的路径( 默认从盘符开始 )
var res = path.join( __dirname,'static','index.html' );
//拼接json文件的全路径
var jsonfile = path.join( __dirname,'json','index.json' );
if( fs.existsSync( jsonfile ) ){ //如果条件成立, 说明 res 这个路径是正确的( 路径对应的文件是存在的 )
    //1.读取文件内容
    var jsondata = JSON.parse(  fs.readFileSync( jsonfile ) ) ; 
    //2.修改内容( 在计算机内存中修改 )
    jsondata.push( { "name":"张三"+(jsondata.length+1), age:20+jsondata.length+1 } );
    //3.写入新的内容到文件
    fs.writeFileSync( jsonfile, JSON.stringify( jsondata ) );//fs.writeFileSync() 会覆盖文件原有的内容
}
console.log(res);

运行node 文件名

[{"name":"张三01","age":21},{"name":"张三11","age":22},{"name":"张三21","age":23},{"name":"张三4","age":24}]

三、 页面渲染模式

3.1、ssr(服务器端渲染)

ssr (Server Side Rendering) :传统的渲染方式,由服务端把渲染的完整的页面响应给客户端。这样减少了一次客户端到服务端的一次 http 请求,加快相应速度,一般用于首屏的性能优化。

优缺点:
1、利用 SEO(搜索引擎)
2、页面渲染时间短
3、服务器压力过大

3.2、csr(客户端渲染)

CSR(Client Side Rendering):是一种目前流行的渲染方式,页面由 js 渲染,js 运行于浏览器端,所以称客户端渲染。

优缺点:
1、前后端并行开发,开发速度提升
2、首屏渲染时间比较长(首屏加载速度慢)
3、不利于 SEO

四、创建 web 服务

1.使用http模块创建web服务

// 引入http模块
// 如果要希望使用 http 模块创建 Web 服务器,则需要先导入它:
var http = require("http")
var path = require("path")
var fs = require("fs")
// 创建web服务并监听在指定端口,每当收到来自客户端的请求时候,都会自动调用回调函数
http.createServer((req, res) => {
  //req 请求对象 , 包含了和本地请求相关的所有信息
  //res 响应对象 , 用来给客户端响应数据
  // url发送请求的网址

  // 服务器的静态资源托管
  console.log(req.url);//-----返回/因为后面没有网址,默认就是/
  // 返回响应数据给客户端
  // res.end("hello client")//index.html    //favicon.ico
  // 判断前端发的什么请求,来返回什么数据
  // 返回响应数据给客户端,需要做一个if判断,来决定返回什么类型
  if (req.url != "/favicon.ico") {
    // if (req.url == "/index.html") {
    //   // 盘---文件夹地址,想要的url地址
    //   var filepass = path.join(__dirname, "static", req.url)
    //   // 用end发送给客户端
    //   res.end(fs.readFileSync(filepass))
    // }
    // else if (req.url == "/index.css") {
    //   var filepass = path.join(__dirname, "static", req.url)
    //   res.end(fs.readFileSync(filepass))
    // }
    // else if (req.url == "/font/iconfont.css") {
    //   var filepass = path.join(__dirname, "static", req.url)
    //   res.end(fs.readFileSync(filepass))
    // }
    // else if (req.url == "/font/iconfont.woff2?t=1638583891245") {
    //   var filepass = path.join(__dirname, "static", "/font/iconfont.woff2")
    //   res.end(fs.readFileSync(filepass))
    // }
      
//可以简写成这样-------------------------------------------------------------------------------------------------
    if (req.url == "/font/iconfont.woff2?t=1638583891245") {
      var filepass = path.join(__dirname, "static", "/font/iconfont.woff2")
      res.end(fs.readFileSync(filepass))
    } else {
      var filepass = path.join(__dirname, "static", req.url)
      //  用end发送给客户端
      res.end(fs.readFileSync(filepass))
    }
  }

  // 服务器api接口--打开网页之后,在操作的时候起作用
  if (req.url == "/useradd") {
    res.end({ code: 200, msg: "添加成功!" })
  } else if (req.url == '/login') {
    res.end({ code: 200, msg: "登陆成功!" })
  }

}).listen(3000, () => {//什么都没写,默认就是/
  console.log("服务器运行在http://localhost:3000");
})

2.使用express模块-创建服务

2.1托管项目
// 1.先用npm iinit -y生成package文件
// 2.再用npm i express安装这个包

// 引入express模块
var express = require('express');
var path = require('path');
var fs = require('fs');
const { arrayBuffer } = require('stream/consumers');

// 2.创建express实例对象
var app = express()
// 静态托管
app.use(express.static("static"))
// 处理post参数// 解析json参数
app.use(express.json());
app.use(express.urlencoded({ extended: false }));


//这里是注册用户----------------------------------------------------------------------------------------------
//这里是登陆代码-------------------------------------------------------------------------------------------


// 3.监听端口
app.listen(3000, () => {
  console.log("服务器监听在http://localhost:3000");
})
2.2.注册用户
//获取 注册按钮
var registerBtn = document.querySelector('button');
//获取 表单
var inputs = document.querySelectorAll('input');

//注册事件
registerBtn.onclick = function(){
    //获取表单数据,发起ajax请求
    if( inputs[0].value &&
        inputs[1].value &&
        inputs[2].value &&
        inputs[3].value  ){
            if( inputs[1].value == inputs[2].value )
            {
                ajax('post','/api/user/register',{ 
                    phone: inputs[0].value, 
                    pass: inputs[1].value, 
                    checkpass: inputs[2].value, 
                    email:inputs[3].value 
                }).then((res)=>{
                    if( res.code == 200 ){
                        // alert(res.msg);
                        // location.href = './login.html'
                    }else{
                        alert(res.msg);
                    }
                }).catch((error)=>{
                    console.log(error);
                })
            }else{
                alert('两次输入密码不一致')
            }
    }else{
        alert('注册信息不完整');
    }
}
备注:// 处理post参数// 解析json参数加上这两个代码
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

// 注册用户
app.post('/api/user/register', (req, res) => {
  // req:请求对象,用户新增数据
  // 怎么拿到参数,前段传过来的数据
  console.log("req.body", req.body);//undefined了
  var { checkpass, ...user } = req.body
  // 1.拼接路径
  var filepath = path.join(__dirname, "json", "user.json")
  // 读取出来是个二进制数据,所以要转换为JSON格式的对象
  var userlist = JSON.parse(fs.readFileSync(filepath))
  // 传过来的确认密码和密码是一个值,可以进行解构
  // 查看userlist里面有没有user
  //  使用数组提供的indexOf filter some find findIndex 方法
  // indexOf 不能比较对象
  var index = userlist.findIndex((item) => {
    return user.phone == item.phone
  })
  if (index != -1) {//代表找到了
    res.send({ code: 400, msg: "用户已存在,注册失败" })
  } else {
    userlist.push(user)
    // 写入要转为字符串
    fs.writeFileSync(filepath, JSON.stringify(userlist));
    // 响应对象
    res.send({ code: 200, msg: "注册成功!" });
  }
})
2.3.登陆账号
//获取 登陆按钮
var loginBtn = document.querySelector('button');
//获取 表单
var inputs = document.querySelectorAll('input');

//登陆事件
loginBtn.onclick = function(){
    //获取表单数据,发起ajax请求
    if( inputs[0].value && inputs[1].value  ){
        ajax('get','/api/user/login',{ 
            phone: inputs[0].value, 
            pass: inputs[1].value
        }).then((res)=>{
            if( res.code == 200 ){
                location.href =  './index.html';
            }else{
                alert(res.msg);
            }
        }).catch((error)=>{
            console.log(error);
        })
    }else{
        alert('注册信息不完整');
    }
}
// 登陆用户
app.get('/api/user/login', (req, res) => {
  //req 请求对象 , 从 req.query 获取get参数
  //res 响应对象 , 通过 res.send 发送数据到客户端(浏览器)
  // 怎么拿到参数
  // 解构一下账号和密码
  var { phone, pass } = req.query;
  // 1.先读取看数据库有没有
  var filepath = path.join(__dirname, 'json', 'user.json');
  var userlist = JSON.parse(fs.readFileSync(filepath));

  console.log("req.query", req.query);//req.query { phonde: '222', pass: '111' }
  // if (req.query.phone == "222" && req.query.pass == "111") {
  //   res.send({ code: 200, msg: "登陆失败" })
  // } else {
  //   res.send({ code: 400, msg: "登陆成功" })
  // }
  // 在userlist里面查找
  // phone和pass是前段传过来的
  var index = userlist.findIndex((item) => {
    return item.phone == phone && item.pass == pass;
  });
  if (index != -1) {
    res.send({ code: 200, msg: "登陆成功!" });
  } else {
    res.send({ code: 400, msg: "登陆失败!" });
  }

})
2.4.主页功能

tools封装函数

function ajax( method,url,data ){
    return new Promise((resolve,reject)=>{
        //1.创建xhr对象
        var xhr = new XMLHttpRequest();
        //2.设置请求参数
        xhr.open(method, method=='get'? (url+'?'+toSearchString(data) ) : url );
        console.log('参数', toSearchString(data) );
        //3.发送请求 
        xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
        xhr.send( method=='post' ? toSearchString(data) : null );
        //4.设置异步回调
        xhr.onreadystatechange = function(res){
            if( xhr.readyState == 4 && xhr.status == 200 ){
                resolve( JSON.parse( xhr.responseText ) );
            }
        }
    })
}

//对象转查询字符串
function toSearchString(obj){
    var str = '';
    for(var key in obj){
        str += (key + '=' + obj[key] + "&")
    }
    return str.slice(0,str.length-1);
}

//渲染数据到dom
function render(data,page,maxpage){
    //获取table-body
    var tableBody = document.querySelector('.table-body');
    //获取page页码标签
    var pageEle = document.querySelector('.page');

    //渲染数据到tableBody中
    tableBody.innerHTML = data.map((item,index)=>{
        return `<ul class="row">
                    <li>${item.email}</li> 
                    <li>张三</li>
                    <li>${item.phone}</li>
                    <li>编辑组</li>
                    <li>是</li>
                    <li>正常</li>
                    <li>
                        <span class="iconfont icon-bianji editicon" id="101"></span>
                        <span class="iconfont icon-shanchu deleteicon" id="101"></span>
                    </li>
                </ul>`
    }).join('')

    //渲染页码
    pageEle.innerHTML = page + '/' + maxpage;
}
//获取搜索按钮
var searchBtn = document.querySelector('.search');
//获取搜索输入框
var input = document.querySelector('.searchbox input');
//获取下一页按钮
var next = document.querySelector('.next');
//获取上一页按钮
var prev = document.querySelector('.prev');
//获取table-body
var tableBody = document.querySelector('.table-body');

var page = 1;//页码
var count = 5;//每页条数
var maxpage = 1;//最大页码

window.onload = function(){
    ajax('get','/api/user/search',{ phone: input.value,page,count }).then((res)=>{
        if( res.code == 200 ){
            maxpage = Math.ceil( res.total/count );
            render( res.list,page,maxpage );//渲染列表
        }
    })
}

//给 搜索按钮 绑定点击事件
searchBtn.onclick = function(){
    ajax('get','/api/user/search',{ phone: input.value,page,count }).then((res)=>{
        if( res.code == 200 ){
            maxpage = Math.ceil( res.total/count );
            render( res.list,page,maxpage  );//渲染列表
        }
    })
}

//给下一页按钮绑定点击事件
next.onclick = function(){
    if( page + 1 >= 1 && page + 1 <= maxpage )
    {
        ajax('get','/api/user/search',{ phone: input.value,page: ++page ,count }).then((res)=>{
            if( res.code == 200 ){
                render( res.list,page,maxpage  );//渲染列表
            }
        })
    }
}

//给上一页按钮绑定点击事件
prev.onclick = function(){
    if( page - 1 >= 1 && page - 1 <= maxpage )
    {
        ajax('get','/api/user/search',{ phone: input.value,page: --page ,count }).then((res)=>{
            if( res.code == 200 ){
                render( res.list,page,maxpage  );//渲染列表
            }
        })
    }
}

//给table-body绑定点击事件, 处理删除
tableBody.onclick = function(e){
    e = e || window.event;
    var ele = e.srcElement || e.target;
    //if( ele.className.indexOf('deleteicon') != -1 ){ //点击了 删除按钮
    if( ele.classList.contains('deleteicon') ){ //点击了 删除按钮
        ajax('post','/api/user/delete',{phone: ele.parentNode.parentNode.children[2].innerHTML  , page,count}).then((res)=>{
            console.log(res);
            maxpage = Math.ceil( res.total/count );
            render( res.list,page,maxpage  );//渲染列表
        })
    }
}
//1.引入express模块
var express = require('express');
var path = require('path');
var fs = require('fs');

//2.创建express实例对象
var app = express();

//app.use() 注册一个中间件(每个中间件的本质 是函数)

//自定义中间件(每个中间件的本质 是函数)
// app.use( (req,res,next)=>{
//     next(); //移交控制器给下一个 中间件
// } )

//处理post参数
app.use( express.json() );
app.use( express.urlencoded({extended:false}) );

//静态资源托管
app.use( express.static('static') )


//api接口,处理用户搜索的请求
app.get('/api/user/search',(req,res)=>{
    //req 请求对象 , 从 req.query 获取get参数
    //res 响应对象 , 通过 res.send 发送数据到客户端(浏览器)
    console.log( 'req.query', req.query );
    var {phone,page,count} = req.query;
    
    var filepath = path.join(__dirname,'json','user.json');
    var userlist = JSON.parse( fs.readFileSync(filepath) );
    //查找包含phone关键词的所有用户
    var list = userlist.filter( (item)=>{ 
        //return item.phone.indexOf(phone) != -1;
        return  new RegExp(phone,'i').test( item.phone )  ;
    } );

    //page 1   ,  0 , 5
    //page 2   ,  5 , 10
    //page 3   ,  10 , 15
    var finallist = list.slice( (page-1)*count, page*count );

    res.send( { code:200, msg:"查询成功!",list:finallist, total:list.length } );
   
})

//api接口,处理删除用户的请求
app.post('/api/user/delete',(req,res)=>{
    var {phone,page,count} = req.body;
    var filepath = path.join(__dirname,'json','user.json');
    var userlist = JSON.parse( fs.readFileSync(filepath) );

    //查找phone对应用用户在userlist中的下标
    var index = userlist.findIndex( (item)=>{ 
        return item.phone == phone;
    } );
    if( index != -1 ){
        userlist.splice(index,1);
        fs.writeFileSync( filepath, JSON.stringify( userlist ) )
    }

    //分页
    var finallist = userlist.slice( (page-1)*count, page*count );

    res.send( { code:200, msg:"删除成功!",list:finallist, total:userlist.length } );

})

//3.监听端口
app.listen(3000,()=>{
    console.log('服务器运行在 http://localhost:3000');
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-018vFOxn-1660484273430)(E:\3.插入到md的图片\微信截图_20220803231729.png)]

五、token

token是在服务端生成,浏览器关闭也会失效

1.在服务器端生成token------安装模块npm i jsonwebtoken (缩写jwt)

var jwt = require("jsonwebtoken")

app.get('/api/user/login',(req,res)=>{
    //req 请求对象 , 从 req.query 获取get参数
    //res 响应对象 , 通过 res.send 发送数据到客户端(浏览器)
    console.log( 'req.query', req.query );
    var {phone,pass} = req.query;
    
    var filepath = path.join(__dirname,'json','user.json');
    var userlist = JSON.parse( fs.readFileSync(filepath) );
    //查找 用户是否存在
    var index = userlist.findIndex( (item)=>{ 
        return item.phone == phone && item.pass == pass;
    } );

    if( index != -1 ){
        
//服务器端生成token-----------------------------------------------------------------------------------------------
        var token = jwt.sign({phone},'hello nodejs',{ algorithm: 'HS256', expiresIn: '1h' } );
        //{phone}要加密的对象
        //hello nodejs:秘钥:用它进行加密
        //algorithm: 'HS256',这个办法进行加密()加密的算法
        //expiresIn: '1h'--时间是一个小时
 //登陆成功就携带这个token,前端拿到这个代码,就要进行在本地保存-------------------------------------------------
        res.send( { code:200, msg:"登陆成功!", token } );
        
        
    }else{
        res.send( { code:400, msg:"登陆失败!" } );
    }
})

2.在登陆完成之后生成token,token代码写入到登陆完成后,写到localStorage中,设置进去

loginBtn.onclick = function(){
    //获取表单数据,发起ajax请求
    if( inputs[0].value && inputs[1].value  ){
        ajax('get','/api/user/login',{ 
            phone: inputs[0].value, 
            pass: inputs[1].value
        }).then((res)=>{
            if( res.code == 200 ){
                //保存token字符串到本地
  //保存到本地的localStorage,  登陆成功就会看到底下的加密字符串--------------------------------------------------------
                localStorage.setItem('token',res.token);//在这里设置token,后端返回的token
   //------------------------------------------------------------------------------------------------------
                location.href =  './index.html';
            }else{
                alert(res.msg);
            }
        }).catch((error)=>{
            console.log(error);
        })
    }else{
        alert('注册信息不完整');
    }
}
//这个代码写在服务器端
var expressjwt = require('express-jwt').expressjwt
//下载这个在服务器端express-jwt
//设置中间件 验证token的有效性
app.use( expressjwt({
    secret: 'hello nodejs',
    algorithms: ['HS256']
}).unless({ path: [ //接口白名单, 这里的接口时免除token验证的
    '/api/user/login',
    '/api/user/register'
] }) )

3.要点击分页搜索要发请求,要携带这个token发送给服务器,得携带在请求头中

function ajax( method,url,data ){
    return new Promise((resolve,reject)=>{
        //1.创建xhr对象
        var xhr = new XMLHttpRequest();
        //2.设置请求参数
        xhr.open(method, method=='get'? (url+'?'+toSearchString(data) ) : url );
        console.log('参数', toSearchString(data) );
        //3.发送请求
        xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
//设置请求头 Authorization----------------------------------------------------------------------------------
        xhr.setRequestHeader('Authorization','Bearer ' + localStorage.getItem('token'));
        //'Bearer '备注这里要加上空格
 //设置请求头 Authorization----------------------------------------------------------------------------------
        xhr.send( method=='post' ? toSearchString(data) : null );
        //4.设置异步回调
        xhr.onreadystatechange = function(res){
            if( xhr.readyState == 4 && xhr.status == 200 ){
                resolve( JSON.parse( xhr.responseText ) );
            }else if( xhr.status == 401 ){
                location.href = './login.html'
            }
        }
    })
}

4.在header里面查看
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwaG9uZSI6IjEzMzMzMzMzMzMiLCJpYXQiOjE2NTk1OTY3ODksImV4cCI6MTY1OTYwMDM4OX0.uWTM1bhkPFPPGh_bZSV4qNAlQ5I6FJPK8mISDK5Cx0E

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值