node.js总结--(助你一臂之力,记的点赞哟)


typora-root-url: mynodeIMG


nodejs原生基础

知识点补充

node是什么

  • node是一个执行环境
  • node中的JavaScript
    • node没有BOM
    • 没有DOM
    • 含有基本ECMA语法
    • 含有服务器级别的API

静态与动态

  • 静态 : 直接从服务器返回的数据, 没有和服务器交互

控制命令行

打开方法

  • window + R 输入cmd
  • 打开指定文件夹 按住shift + 鼠标右键 ==> 打开控制命令行
  • 打开指定文件夹 在URL输入框内输入cmd

常用命令行

node -v  // 查看当前nodejs版本
dir      //  查看当前目录的所有文件夹
cd       // 进去当前的某文件夹
cd..     //返回上级目录
cls      // 清屏
exit     // 离开

网站图标 ico

  • 加载html页面默认会自动请求ico图标
  • 生成 ico图标 :比特虫 (http://www.bitbug.net/)
  • 将图标保存到静态资源根文件夹

HTTP协议

HTTP协议指的是服务器与浏览器之间通信要遵循一定的规则 :

  1. 浏览器请求服务器会向服务器发送请求报文,请求报文包括请求头和请求体
    • 请求头包括 : 请求的URL, 请求的方式(get,post)
    • 请求体
  2. 服务器和浏览器通信会向浏览器发送响应报文,包括响应头和响应体
    • 响应头 : 状态码, 请求的数据类型
    • 请求的内容

状态码

  • 下面是常见的HTTP状态码:
    • 200 - 请求成功
    • 301 - 资源(网页等)被永久转移到其它URL
    • 404 - 请求的资源(网页等)不存在
    • 500 - 内部服务器错误
  • HTTP状态码分类
状态码 说明
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误

跨域

  • 跨域指的是在不同源的情况下ajax异步请求返回的数据,浏览器会进行拦截,不会执行回调函数.从而提示报错.

    同源 : 相同的http或者https协议 / 相同的IP地址 / 相同的端口号

  • 解决办法 :

    1. response.setHeader('Access-Control-Allow-Origin','*'); 在服务端返回请求头

    2. 使用第三方模块 : cors (一个专门处理跨域的第三方包)

      const cors = require('cors');
      
      //注册 允许跨域请求的 中间件
      serverApp.use(cors())
      
    3. jsonp

    • 浏览器只是阻止ajax异步对象请求的跨域,并不会阻止script标签跨域请求的内容,因此,可以利用jsonp来请求数据
客户端  :

    // 1. 提前准备一个自定义函数,作为接收函数的内容   
		funtion makeLove(data){alert(data)}
    // 2. 点击按钮之后,动态创建一个script标签,标签的url为跨域请求服务器的URL,并且将自定义的函数名字绑定在URL上
        $('btn').click(function(){
			$('father').append('<secipt src="http://127.0.0.1:3000/add?funcName=showLove"></script>')	
        })
   
		

服务端  :	

    1. 当获取到客户端传递过来的数据后,用req.query 解析URL的函数名字
    2. res.send( 传递过来的函数名字(传递的参数) )


// jQuery的jsonp封装
$.ajax({
    url : url,
    datatype : 'jsonp',
    jsonp : 'funcName',   // 指定的参数名称
    jsonpCallback : 'showLove',  // 指定的回调函数
})

端口号的理解

  • 一句话 : ip定位计算机,端口号定位应用程序
  • 每个电脑都有对应的IP地址,但是不同软件都需要和不同的服务器传输数据,所以为了不同软件之间数据互不影响,则需要对不同软件的通信取不同的端口 号.
  • 取值范围是 0 - 65536 (3000,5000,8080等不常用,可以提供给自己使用)
  • 可以同时开启多个服务器,只需要让端口号不一致就可以了

模块化(exports 和 module.exports的区别)

  • Node中没有全局作用的概念,通过require来执行多个脚本文件
  • 作用: 不能功能对应不同的模块,需要用啥,调用啥. 每个模块都有不同的API. 模块化互不影响,不会有污染问题,模块完全封闭,外部与内部互相不能访问. 因此需要通过exports来暴露对象
  • 分类
    • 核心模块 : fs(文件操作) http(服务器操作) os(机器信息) path(路径操作)
    • 第三方模块 : 通过npm install *** --save
      1. 默认先找到node_modules/模块名
      2. 再找到package.json文件
      3. json中找到main属性, 属性通常为index.js : 入口模块
    • 自定义模块 : (通过exports或者 module.exports来暴露,通过require来导入)
      1. 自定义模块引入必须要加 ./ 就算是当前目录 !!! / 表示的是当前磁盘的根目录
      2. 可以省略后缀名 .js

exports 和 module.exports的区别

  1. 实际上 exports = module.exports

  2. 用法区别:

    • exports.name = name; ======> exports只能通过点语来暴露出去

    • mudule.exports.name = name || mudule.exports = name =====> module.exports可以通过两种方法来暴露(点语法 或者 直接暴露)

    • 通过点语法暴露的话只能通过点语法来调用 : let addlists = require(’./addlists’)

       let  addlists = require('./addlists')
       console.log(addlists.name)
      
    • 通过 module.exports 可以直接获取

      let  addlists = require('./addlists')
       console.log(addlists)
      
  3. 区别的原理

    • 了解堆栈的区别

       let num1 = 10;
      let num2 = num1;
      num2++;
      console.log(num1);    //  10
      console.log(num2);    //  11
      
      // 总结: 在普通变量之间,通过直接开辟新的空间并复制相等的值,复制之后两个变量之间就没有关系了,
      //各自之间互不影响
      
      //---------------------------------------------------------
      
      let obj1 = {}
      let obj2 = obj1
      
      obj2.name = '龚利明';
      console.log(obj1);    //  {name : '龚利明'}
      console.log(obj2);    // {name : '龚利明'}
      
      //总结 :  在对象之间,开辟新的空间,存储的是指向同一地方的地址. 当任一值的改变,两个变量的值都会改变.
      
      此时如果让obj2指向新的对象:
      
      如果让 obj2 = {}
      
      //name此时 obj1  和obj2是没有关联了的
      
      此时exports  和  mudule.exports就是上述的对象
      exports = module.exports
      当exports = {}  新的对象的时候,  exports和  module.exports就没有关联了,返回的肯定是module.exports,当中exports=XX, module.exports返回的就是underfine
      
      所以!!!!   :  exports不能直接暴露模块. 只能通过点语法.
      

npm命令行使用

简单介绍

  • npm 是nodejs自带的. 只要安装了nodejs,默认就有npm
  • npm是国外的一个服务器,里边有很多很多第三方的包(vue jQuery bootstrap等),需要用什么模块自己去调用就好

用法

npm -v     //查看当前npm的版本
npm install npm --global   //  升级当前npm   global表示全局

//----------------------------------------------------------------

npm init   //项目初始化   
npm init -y  // 项目初始化快捷键

npm install // 安装已经初始化的项目依赖包
npm install *** *** *** --save  //安装需要的 *** 依赖包,并把依赖包的名字记录在 package  
							 // 可以同时按照多个
npm uninstall *** --save //删除 *** 依赖包, 并且把记录从package中删除

cnpm

通过npm,但是从淘宝镜像下载(其实只是为了下载的速度),淘宝每十分钟和npm更新一次

安装方法

  • npm config set registry https:// registry.npm.taobao.org
  • 检查: npm config list

package.json 文件信息

name - 包名(项目名/模块名) - 必写
version - 包的版本号 - 必写
description - 描述
homepage - 官网地址
author - 作者,最好是 npmjs.org 的账户名(邮箱)
contributors - 包的其他贡献者
dependencies / devDependencies - 生产/开发环境依赖包列表
repository - 包代码的Repo信息,包括type和URL,type可以是git或svn,URL则是包的Repo地址。
main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件
            这个字段的默认值是模块根目录下面的 index.js。
keywords - 关键字

package-lock.json和package.json 的区别

  1. package.json只保存了当前的包和其依赖的模块,package-lock.json保存了这些模块的信息
  2. package-lock.json能加速包的下载速度

nodemon模块

  • 作用 : 不用每次写了js代码重新 node app.js了
  • 安装好后 : nodemon app.js就可以了
npm i nodemon -g 

fs模块

读文件 readFile

  • 传输成功的时候 err为null
let fs = require('fs');
fs.readFile(URL,(err, data)=>{
    if(!err){
        console.log(data.toString())    //如果不转成String   则显示的是 buffer的16进制的文件
        							 //如果不读取  那就不要转啦!!!!
    }
} )

读取文件目录 readdir

let fs = require('fs');
fs.readdir(URL,(err, data)=>{
    if(!err){
        console.log(data)   
    }
} )

写入 writeFile

let fs = require('fs');
fs.writerFile(URL,data,(err)=>{
    if(!err){
        console.log(err)
})

最简单服务器搭建

let http = require('http');   //导入 http\模块
      
let server = http.createServer((req, res)=>{        // 创建服务器
    // req.url 默认是获取到端口号后面的内容
    if(req.url == '/'){
        res.writeHead(200,{'Content-Type':'text/html;charset=UTF-8'});  //charset是用的  = 号
        res.write('hello');
        res.end('world!');
    }
    else if(req.url == '/css/index.css'){
        fs.readFile('./css/index.css',(err,data)=>{
            if(!err){
                res.writeHead(200,{'Content-Type':'text/css'}); 
                 res.end(data)
            }
        })
    }
    else{
         res.end('访问出错了!!!')
    }
})

server.listen(3000,'127.0.0.1');         //监听端口号和设置服务器的ip地址并启动服务器

  • 注意点 :

    1. 端口号默认为80, 当修改成3000的时候,访问服务器必须加上端口号,80的时候可以不用
    2. req.url 默认是获取到端口号后面的内容
    3. res.end返回的必须是字符串或者二进制数据(布尔,数字,变量啥的都不行!)
  • Content-Type

    1. text/plain 普通文本
    2. text/html html文件
    3. text/css css文件
    4. 注意 : 我们的浏览器默认是gbk编码模式,请求头中需要添加文件格式为UTF-8 html文件默认就有meta标签来声明编码格式,因此不需要再设置charset=‘UTF-8’

    总结 :

    ​ 1. 其实在实际中,服务器传递过来htm文件的数据,浏览器会自动解析成html文件,(智能识别)

    ​ 2. 在html文件中, 通过标签上的src或者href获取到的数据,因为是在标签中请求的嘛,所以数据也是能够自动解析的

url模块

为什么要用url模块

http://127.0.0.1:3000/nihao?name='naaa'

  • 上边最简单的服务器中 : 直接通过 res.url返回的是 : /nihao?name=%27naaa%27 当我们只需要/nihao时,或者只需要传递过来的数据就很尴尬了. 还要自己对URL进行字符串操作,特别的麻烦
  • 用了url模块,能够把url里边需要各个部分都提取出来

使用方法

let http = require('http');
let url = require('url');

let server = http.createServe((req, res)=>{
    let my_url = url.parse(req.url);    //   用url模块 初始化url
    //打印 my_yrl
    console.log(my_url)
})

server.listen(3000,'127.0.0.1')

//------------------------------------

//输入的URL为:http://127.0.0.1:3000/nihao?name=%27naaa%27
//结果 为:   
/*
            Url {
              protocol: null,
              slashes: null,
              auth: null,
              host: null,
              port: null,
              hostname: null,
              hash: null,
              search: '?name=%27naaa%27',
              query: 'name=%27naaa%27',
              pathname: '/nihao',
              path: '/nihao?name=%27naaa%27',
              href: '/nihao?name=%27naaa%27' }

*/

- 注意 :  1. 通过my_url.pathname 来用于if判断   
		 2. query为字符串   并没有像express框架一样直接转成了对象!!!
             所以  let my_url = url.parse(req.url,true);  加个true!!!!!



queryString模块

js文件

let http = require('http');
let queryString = require('queryString');       //用于处理post提交的数据转换成对象
let fs = require('fs');
http.createServer((req, res)=>{
    // 先让'/'为html文件
    if(req.url === '/'){
        fs.read('posttest',(err,data)=>{
            if(! err){
                res.writeHead(200,{'Content-Type':'text/html;charset=UTF-8'});
                res.end(data)
            }
        })
    }
    
    //接下来做post请求响应
    
    if(req.url === 'posttest' && req.method.toLowerCase() === 'post'){
        let shuju = '';
        req.on('data',(data)=>{            // 监听 data变化    有点下vue中的watch方法,data每变化一次会										//执行一次函数  
            shuju += data;                 //数据流逐渐添加到shuju中,异步添加
        })    
        req.once('end',()=>{               // req的传递都结束时,执行下边的函数
            console.log(queryString.parse(shuju))     // 此时,数据都是字符串,需要让queryString来转成                                                       // 对象来使用
            res.end('上传完成');
        })
    }
    
}).listen(3000,'127.0.0.1')

js文件总结

1.    req.on('data',function(data){})
作为监听的回调函数.  执行异步操作!!    分批次的将data数据传输进来

2.   req.once('end',function(){})
当所有的数据传输完毕时,执行这个函数

req.once 和req.on 的异同:
  -  相同:   都是用于事件监听
  - 不同:    once只执行一次     on可以无限次监听  

html文件

<body>
<form action="/nodetest" method="post">
    <input type="text" name="name" value=""><br>
    <input type="password" name="psw" value=""><br>
    <input type="radio" name="sex" value="1">:男
    <input type="radio" name="sex" value="0">:女 <br>
    <input type="file" name="img"> <br>
   <input type="submit" value="提交">
</form>
</body>

原生get 和 post 表单提交总结

  • get :通过url来来传值, 那么直接通过 req.url(这不算模块,默认就有的)l就可以获取传递过来的全部字符串信息… 只需要用 url模块 来提取各个功能的字符串对象,通过true来将字符串转成对象… **let data = url.parse(req.url, true)**让字符串转成对象, 然后 data.query就可以求取post传递的值
  • post : post比较复杂. 不能通过url来得到需要的值, 那么就需要通过监听来获取传输文件**req.on(‘data’,(data)=>{})**来分批次获取传递的值,类似于vue中的watch方法. 总有全部传递完毕的时候,那么此时就需要对数据进行操作 req.once(‘end’,function(){ 传完时,做啥?? });

模板引擎

  • npm art-template install --save
var template = require('art-template');

var str = ` 
{{each}}
 {{ $value }}
{{/each}}
`
var nowrender = template.render(str,['你好','我不好'])


express框架

hello world

安装方法

  1. 安装node
  2. npm init -y ( 初始化packjson) -y是缩写
  3. npm install express --save 安装框架
let express = require('express');
let app = express();

app.get('/', (req, res)=>{
   res.send('ok') 
});

app.listen(3000,'127.0.0.1',()=>{
    console.log('running!')
})


路由

api介绍

  1. app.get(’/’, function(req, res, next))
  2. app.post()
  3. app.use() : 接收get/post ajax请求

next()

  • 中间件的前提条件
  • next()就是一个函数,意思是这个函数代表执行下一个相同路由的内容,执行完成之后,又会回来执行next() 之后的内容,这个是原理 但是呢,一般也不会再next()函数之后写上代码!!!
let express = require("express");
let app = express();

app.get('/a',function(req, res, next){
    next()   // 当添加了这一行代码,才能够执行下边的get('/a')的代码块
})
app.get('/a',function(req, res, next){
    
})

express.Router()

const express = require('express');
const router = express.Router();

module.exports = router

/*************************************/
const router = require('./Router/router.js')
app.use(router)

// 当有多个路由js文件的时候,可以再次分开. 但是在url上就要加上/user  或者  /makesome了 
app.use('/user'router1)
app.use('/makeSome'router2)



中间件

什么是中间件

中间件是干啥的

​ 中间件的作用就是为了让ajax提交上来的信息先做一个预处理,不同的中间件预处理不同的信息,body-parser的作用是预处理常规post提交信息,multer处理的是FormDate上传的信息,express.static()处理的是判断你求取的是不是一个静态的文件,cookies-parser处理的是cookies过来的信息

中间件是怎么工作的

​ 中间件是对上传上来的信息预处理, 不同的中间件提取不同的相对应的信息, 处理的方式用app.use(), 在第三方包(中间件)内部实现的是将需要的信息绑定在request对象上,通过next() 传递给下一个路由作为参数使用

静态资源 static中间件

  • __filename : 当前执行的js文件
  • __dirname : 当前执行的js文件的文件夹
 app.use('/public' express.static(path.join(__dirname,'/publc')) )

  • 作用: 使用静态文件夹 让文件夹里的文件可以直接通过url来访问

  • 和原生的区别在于 : express会将相对路径自动转化为get请求,原生的并没有这个功能!!!

  • 使用注意 : app.use(express.static(path.join(__dirname,url))) 要放在路由的后面

    // express 
    var express = require('express');
    var app = express();
    app.use('/public',express.static('./public'))
    app.listen(3000,'127.0.0.1',function(){
        console.log('runing!!');
    })
    
    
    // 原生
    var http = require('http');
    var fs = require('fs');
    var url = require('url');
        var url1 = url.parse(req.url);
        var pathname = url1.pathname;
            fs.readFile('./public/index.html',function(err,data){
                res.end(data);
            })
        }
    }).listen(3000,'127.0.0.1',function(){
            console.log('runing!!');
        })
    
    

body-parser中间件

  • express中可以直接使用req.query来获取上传get数据,但是post却不行,需要用到中间件

  • 通过在app.use来预处理数据,再通过next()传递给app.post()来直接使用,使用的过程中要遵循别人框架的规则

    const express = require('express');
    const body = require('body-parser');
    
    let app = express()
    
    app.use(body.urlencoded({
        extended : false
    }))
    
    app.post('/reg',(req, res)=>{
        console.log(req.body)
    })
    app.listen(3000,'127.0.0.1')
    
    

    body-parser底层原理

    var queryString = require('querystring')   //parse()方法时把字符串转化成对象
    // app.use这代表所有的路由都要经过这,接着用next()传递下去
    app.use((req, res, next)=>{
        let str = '';
        req.on('data',buffer=>{
            str += buffer;
        })
        req.on('end',()=>{
            req.body = querystring.parse(str.toString())  // 把解析出来的值赋值给req.body
            next()  // 传递到下一个路由
        })
    })
    
    app.post('/login',(req,res)=>{
        console.log(req.body)
    })
    
    
    

multer中间件

  • 获取上传的文件中间件

  • multer处理Form-data数据的

    // 导入中间件模块
    const multer = require('multer');
    
    let upload = multer({dest : './static/upload'})   // 设置上传到哪里
    								// avatar代表上传文件的name的名字
    app.post('/profile', upload.single('avatar'), function (req, res, next) {
      console.log(req.file )       // req.file : 上传的文件  req.file.filename ===> 上传文件后的名字
      console.log(req.body )       // 代表除了file中的其它信息
    })              
    
    
    
    

cookie-parser中间件

什么是cookie

  1. cookie是做啥的?

    用于保存用户信息(通常指登录信息 / 购物车)

    • 例子 : 当访问网易云课堂,第一次账户密码登录. 服务器会向浏览器发送cookie信息, 这个cookie会存储在浏览器,存储什么信息由服务器自己决定,当下次再次访问这个网站的时候,浏览器会自动带上cookie发送到浏览器.用于验证你是否在规定的期限内登录过.要是没有携带cookie或者cookie的保存时间已经过了,那么就需要重新登录,重新让服务器向你的浏览器发送信息.

      注意点 :

      1. cookie必须要设置存放的时间,不设置的话默认关闭浏览器就自动消失
      2. cookie的大小不能超过4K

例子1 : hello world — 验证简单的账号密码

const express = require('express');
 // 导入中间件模块
const cookieParser = require('cookie-parser');  
const app = express();
 // 设置静态文件
app.use(express.static('./public'))             
  //  设置中间件
app.use(cookieParser())                        

  // 声明用户存储的数据
let obj = {                                      
    龚利明 : {username : '龚利明',age: 18,sex : '男'},
    江华   : {username : '江华',age: 28,sex : 'nv'}
         }

  // 提交登录按钮提交到这
app.get('/login',(req, res)=>{
    // 判断用户1 账号密码是否正确
   if(req.query.username == '龚利明' && req.query.psw == '123456'){
    // 正确返回cookie,及正确的提示
    res.cookie('username','龚利明',{maxAge : 100000})  
    res.send('登录成功!')
   }
    // 判断用户1 账号密码是否正确
   else if(req.query.username == '江华' && req.query.psw == '654321'){
    //res.cookie(传递对象,对象的值,属性操作) 
    res.cookie('username','江华',{maxAge : 100000}) 
    res.send('登录成功!')
 } // 账号密码不正确
    else{
    res.send('账号或者密码错误,请重新输入!')
 }
})

 // 登录主页面,默认执行ajax请求
app.get('/lists',(req, res)=>{  
    // 获取当前的cookie及上传的用户名
    const username = req.cookies.username        
    
    // 验证成功.返回数据
    if(username != undefined){                // 当cookie过期,或者没有注册值为underfine   
        res.send({                              
            code : 200,
            username : obj[username]
        })
    }
    // 验证失败
    else{                                    
        res.send({
            code : 404,
        })
    }
})

app.listen(3000,()=>{
    console.log('running!');
})


升级版本

const express = require('express')
const cookieParser = require('cookie-parser');

let app = express()
app.use(cookieParser(
'dasdaskdhaslkdjkl'   // 设置签名
));

app.get('/a',(req, res) => {
    console.log(req.cookies)   // 获取传递过来的cookies
    res.cookie('money',998,{   //返回设置cookie
        maxAge : 14 * 86400 * 1000    // 最大存储时间
        ,domain : 'baidu.com',      
        path : '/uesr',        // 当访问这个服务器且路由为/user才会携带cookie
        signed : true,     // 设置签名
        httpOnly : true,  //客户端将无法通过document.cookie读取到 COOKIE 信息,可防止 XSS 攻击产生
        secure : true     // 设置为true只能用https
    })    
})

signed 设置签名

  • cookie可以直接在浏览器中让人查看到,因此为了让别人看不懂服务器给你浏览器发送的信息的意义,就变相的把值进行转码,浏览器上的cookie值就是转码之后的值. 执行步骤的话主要是三步 :
    1. 设置 cookie 参数对象的 signed = true
    2. 设置签名标识用来对cookie数据做签名使用==> 在中间件中直接加入任意的字符串,不能为中文serverApp.use(cookieParser(‘签名用的 标识数据字符串’));
    3. 服务器端接收传过来的cookie的值得时候,要用新的API接收, 需要使用 request.signedCookies

注意:被篡改的签名 cookie 会被服务器拒绝,并且 cookie值会重置为它的原始值

// 第二步 :  设置任意的随机字符串
app.use(cookieParser('nihaowoshinibaba'))

let obj = {
    龚利明 : {username : '龚利明',age: 18,sex : '男'},
    江华   : {username : '江华',age: 28,sex : 'nv'}
         }

app.get('/lists',(req, res)=>{
    // 第三步 使用signedCookies来接收
    const username = req.signedCookies.username
    console.log(username);
    
    if(username != undefined){
        res.send({
            code : 200,
            username : obj[username]
        })
    }else{
        res.send({
            code : 404,
        })
    }
})

app.get('/login',(req, res)=>{
   if(req.query.username == '龚利明' && req.query.psw == '123456'){
       // 第一步  :  设置signed为true
    res.cookie('username','龚利明',{maxAge : 100000,signed:true})  
    res.send('登录成功!')
   }
   else if(req.query.username == '江华' && req.query.psw == '654321'){
    res.cookie('username','江华',{maxAge : 100000, signed:true}) 
    res.send('登录成功!')
 }else{
    res.send('账号或者密码错误,请重新输入!')
 }
})

hash密码保存

为啥要用 :

  • 直接在数据库中存储密码是非常不安全的,那么我们可以用类似于上边的signed来进行转码, 然后再存储到服务器保存,但是转换乱码之后转换不回来了,不过一样的值转换的效果是一样的,因此,每次从客户端接收到数据,都可以先进行转码,然后再去服务器作对比,然后进行操作

简单介绍 :

  • hash算法:可以将任意数据 生成 固定长度的16进制字符串 并且,只要数据一样,那么不管计算多少次都会获得同一个 16进制字符串

使用 :

  1. 安装第三包 : npm i hash.js -D

    const hash = require('hash.js');
    
    let password = 123456;
    //将 密码 转成 sha256 的hash值字符串 64位
    password = hash.sha256().update(password).digest('hex');
    // 结果:‘8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92’
    
    

模板引擎

  • __dirname 指的是当前目录的绝对路径
  • 通过path模块来拼接路径 path.join(__dirname + ‘views’)
// 1. 导入模板引擎包  
npm install ejs --save   

// 2. 创建views文件夹及.ejs文件

// 3. 在js入口文件设置模板引擎
let path = require('path')

app.set('views', path.join(__dirname + '/views'))    //设置模板引擎的文件夹所在的位置
app.set('view engine', 'ejs')               //设置使用的模板引擎为  ejs 

// 4. 调用 res.render()  

router.get('/',(req, res)=>{
    res.render(index,{lists:[1,2,3,4]})
})


  • ejs代码
<body>
    <% for(var i = 0; i < lists.length; i++){   %>
    <div><%= lists[i]  %></div>                   //   注意着有 = 号
    <% } %>
</body>

获取用户的ip地址

req.params

  • 作用: 获取url中的某一部分的后面url
url为:  127.0.0.1:3000/fuck/make/18

router.get('/fuck/:name/:age',(req, res)=>{
    console.log(req.params.name)      // 结果为  : make
    console.log(req.params.age)      // 结果为  : 18
})

response对象

res.redirect()

  • 重定向
  • 使用方法
    • res.redirect(URL) ==> URL 写上就好了,前提是之前定义了url的get请求

res.send()

  • 和原生的nodejs相比, send和end区别大大的!!!
    • 不同点 : res.send() 不再需要添加Content-Type,这里可以直接使用,能够自动识别 JSON / HTML 等都可以自己识别, 直接返回就好啦!
    • 相同点 : res.send()和res.end() 都只能使用一次

res.status()

  • 返回状态码

res.download()

  • 返回下载文件
res.download(传递的文件路径, 传递过去之后的名字)

--app.js代码------------------------------------------------------------
const express = require('express');

const app = express();
const path = require('path')


app.use(express.static(path.join(__dirname , './public')))


app.get('/down',(req,res)=>{

    res.download('./download/news.txt','你好.txt')
})

app.listen(3000,()=>{
    console.log('开启成功');
})

--html代码----------------------------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
    <script src="./jquery-1.12.4.js"></script>
</head>
<body>
    <button>
        下载
    </button>

    <script>
    $(function(){
        $('button').click(function(){
            // 不用通过ajax来请求,我也不懂为啥,ajax就是不行
            // $.ajax({
            //     type : 'get',
            //     url : 'http://127.0.0.1:3000/down',
            //     success : function(data){
            //         console.log(data);
                    
            //     }
            // })

            location.href = 'http://127.0.0.1:3000/down';
        })
    })
    </script>
</body>
</html>

generator 应用生成器

  1. npm i express-generator -g ==> 安装应用生成器在全局
  2. express --view=ejs demo ==> 设置模板引擎为ejs模式

路径总结

不管是绝对路径还是相对路径都是可以用的但是要遵循以下规则

假设服务器默认为http://127.0.0.1:3000

下图是层级结构,且public文件夹设置为静态文件夹

[外链图片转存失败(img-mNZEItvu-1568960271765)(/路径总结.png)]

  1. 当index.html文件要src引入img文件夹下的1.png时 :

    // 1. 使用绝对路径,绝对路径必须直接在端口号后边拼接
    //  http://127.0.0.1:3000 + /img/1.png     ===    http://127.0.0.1:3000/img/1.png 
    <img src="/img/1.png" alt="">  
     
    // 2. 使用相对路径,相对路径发送的url会自动将该文件补全成绝对路径,因为index.html已经处于
    // 一级目录了,因此发送的url为:    http://127.0.0.1:3000/img/1.png
    <img src="./img/1.png" alt="">
        
     // 3. 使用相对路径, 只要是已经达到了 一级目录,再多的../都是始终保持在一级目录   
    <img src="../../img/1.png" alt="">
    
    
    1. 当login.html文件要src引入img文件夹下的1.png时
    // 1. 使用绝对路径,发送的请求直接拼接在端口号后边
    //  http://127.0.0.1:3000 + /img/1.png     ===    http://127.0.0.1:3000/img/1.png 
    <img src="/img/1.png" alt="">
        
    // 2. 使用相对路径, 这里的 ../ 会退到上级目录, 此时发现这个url已经在一级目录了
    <img src="../img/1.png" alt="">
    
    

总结 :

  1. 当需要数据库存储文件路径的url作为数据时,也就是这个文件想在不同的html文件调用的时候,建议使用绝对路径.!!!
    因为不同层级目录下的html文件所指向需要的同一个文件的相对路径是不一样的
  2. 当这个文件并不是大家都需要加载引用的,仅仅是一个html文件要用的.也可以使用相对路径
  3. 作为文件路径方式打开的html页面只能使用相对路径,绝对路径是没用的, 但是VScode有live Server插件,打开的时候可以作为服务器静态文件打开

mysql

安装

  1. 安装mysql软件,结合Navicat可视化工具来使用,具体安装步骤在我的u盘说明文档有

可视化工具的使用

  1. 连接mysql 打开localhost3306 右键创建数据库 字符集和数据格式都选择utf-8的格式
  2. 右键表格,点击创建表格, id要加主键 并且不为null 而且勾选自动递增 点击保存
  3. 选中数据库 ==> 点击查询 ==> 新建查询 ==> 在这里编写sql代码

注意 : 主键 : 表示唯一性, 不可改变,当输入的id值重复时,会自动报错

sql语法

增加 insert

  • insert into Strdents (姓名,性别,出生日期) values (‘开心朋朋’,‘男’,‘1980/6/15’)
//添加单条
INSERT INTO student (name, age, sex, phone) VALUES('aaa',23,'a111','22223')
//添加多条
INSERT INTO student (name, age, sex, phone) VALUES('aaa',23,'a111','22223'),('bbb',23,'bbbb','44444')

删除

  • delete from 表名 where 删除条件
delete from a where name='龚利明'(删除表a中列值为开心朋朋的行)

更新

  • update 表名 set 列名=更新值 where 更新条件
//
update tongxunlu set 年龄=18,姓名='龚利明' where 姓名='蓝色小名'

查询

  • select 列名 from 表名 where 查询条件表达试 order by 排序的列名asc(升序)或desc(降序)
// 查询a中所有数据行和列
select * from a

// 查询表a中f=5的所有行,并显示i,j,k3列
select i,j,k from a where f=5

// 查询a表中性别为男的所有行,显示name列,并将name列改名为(姓名)显示
select name as 姓名 from a where xingbie='男'

// 查询表a中email为空的所有行,并显示name列;SQL语句中用is null或者is not null来判断是否为空行
select name from a where email is null

// 查询表a,显示列name的前6行,top为关键字
select top 6 name from a

// 查询显示表a中,name字段第一个字为赵的记录
select * from a where name like '赵%'

// 查询表a中address值为北京或者上海或者唐山的记录,显示name字段
select name from a where address in ('北京','上海','唐山')

nodejs中使用sql

  • 安装第三方模块
var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : 'localhost',    // ip地址
  user     : 'me',           // 用户名
  password : 'secret',       // 密码
  database : 'my_db'         // 数据库名字
});
 
connection.connect();
 
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
    if (!error) {
        console.log('The solution is: ', results);
    }
});
 
connection.end();

webpack

安装

  • npm i webpack -g
  • npm i webpack-cli -g

hello world

1.准备 :

  • 一个项目工程文件
  • 工程文件内一个webpack.config.js文件
  • 创建一个src用于存放想要打包的代码
  1. webpack.config.js代码如下
const path = require('path');

module.exports = {
    mode : 'development',    //(开发模式) 或者 production(生产模式)   或者  none(只打包就好)
    entry : {                  // 多入口
        login : './src/js/login.js',
        register : './src/js/register.js'
    }
    output : {
    path : path.resolve(__dirname,'build')   // 创建用于存放打包好的文件夹
    filename : '[name].min.js'               // 设置打包好的文件夹的名字
}
}

  1. 在项目工程化 cmd界面输入 webpack即可打包文件

loader

style-loader css-loader (css样式)

  • 上边的内容仅仅只能打包js代码,却不能打包css代码等, 要想打包css代码也必须要有相对应的包
  1. 安装
    • npm i style-loader -D
    • npm i css-loader -D
  2. 在m1.js文件下导入编写好的css
import $ from 'jquery';
import '../src/css/index.css'

  1. webpack.config.js代码如下
const path require('path');

module.exports = {
    mode : 'production',
    entry : './src/m1.js',
    output : {
        path : path.resolve(__dirname,'build'),
        filename : 'bundle.min.js'
    },
    module : {
        rules : [
            {test : /\.css$/, use : ['style-loader','css-loader']}   // 加载顺序必须是style在前
        ]
    }
}

  • css-loader的作用 : 为了让webpack能够识别这个是css文件
  • style-loader的作用 : 当html文件引入了m1文件时,能够在header中添加一个style标签,并且把样式放在里边

postcss-loader autoprefixer (css兼容处理)

  1. 导入包 :
    • npm i postcss-loader -D
    • npm i autoprefixer -D
  2. 介绍 :
    • postcss-loader : 为了能够读取css的样式,配合autoprefixer来编写兼容样式
    • autoprefixer : 实现css样式的兼容性
  3. 代码编写
  • webpack.config.js文件 :
 const path = require('path');

module.exports = {
    mode : 'development',
    entry : './src/js/main.js',
    output : {
        path : path.join(__dirname, 'build'),
        filename  :  'main.min.js'
    },
    module : {
        rules : [
			{test : /\.css$/, use : ['style-loader','css-loader','postcss-loader']}
            // 作用顺序从右到左,不能变
        ]
    }
}

  • postcss.config.js :
module.exports = {
    plugins : [
        require('autoprefixer')
    ]
}

less less-loader (less使用)

  • 安装包 : npm i less -D

    ​ npm i less-loader -D

  • webpack.config.js文件 :

const path = require('path')

module.exports = {
    mode : 'development',
    entry : './src/app.js'
    output : {
    	path : path.resolve(__dirname,'build'),
        filename : 'main.min.js'
	},
    module : {
        rules : [
            {test : /\.css/, use : ['style-loader','css-loader','postcss-loader']}
            {test : /\.less/, use :['style-loader','css-loader','less-loader']}
			// 顺序不能乱,从右边开始执行
        ]	        
    }
}

url-loader file-loader(文件处理)

  • 安装 : npm i file-loader -D

    ​ npm i url-loader -D

  • 使用说明 :

    1. 使用url-loader的前提是必须安装file-loader, file-loader能做的,url-loader都能做
    2. webpack打包只会将用的到的文件拿来打包,所以必须在css等文件中引入(待考证? js中通过字符串加载的如何使用? 获取还有其他loader包)
  • less文件路径 : src/main.less

body {background : url('./test.png') norepeat}

  • webpack.config.js 文件 :
const path = require('path')

module.exports = {
    mode : 'development',
    entry : './src/app.js',
    output : {
        path : path.resolve(__dirname, 'build'),
        filename : 'main.min.js',
    },
    module : {
        rules : [
            {test : /\.css$/, use : ['style-loader','css-loader','postcss-loader']},
            {test : /\.less$/, use : ['style-loader','css-loader','less-loader']},
            {
                test : /\.(png|jpg)$/i, use : {
                    loader : 'url-loader',
                    options : {
                        outputPath : 'imgs',
                        limit : 0
                    }
                }
            }
        ]
    }
}

发布了6 篇原创文章 · 获赞 23 · 访问量 1231

猜你喜欢

转载自blog.csdn.net/gongliming_qd/article/details/101059288