资讯详情

自我总结前端vue笔记

三阶段笔记

node基础(写作简单api接口)

  • node.js

    • javascript运行环境

    • javascript运行在浏览器的时候:操作DOM,操作BOM,语法ECMAScript

    • javascript运行在node的时候:

      • 操作文件

      • 操作数据库

      • 开启web服务 ...

      • 不能操作DOM,不能操作BOM

  • node.js的安装

    • 版本识别: 16.14.2 node -v

    • LTS: 建议安装稳定版 Current: 最新版本

    • 主版本号.子版本号.修订版本号 v16.14.2

      • 子版本号是偶数的稳定版本,是奇数的不稳定版本

      • 修订版本号的变化是内部bug的一些处理

      • 建议安装LTS的偶数版本

  • 在node环境中运行js代码

    • 方法一:(不推荐)

      • 直接在终端运行: node 回车

      • 进入js可以输入编辑环境js代码

    • 方法二:

      • 把你要在node在环境中运行js代码写在一个js文件

      • 终端运行: node js文件路径

    • node的版本管理

      • 我要在公司管理多个node项目

        • 项目一: node 10.16.0

        • 项目二: node 14.12.2

        • 需要在电脑上安装多个不同的node随时切换版本 就可以使用nvm这个node版本管理工具

  • API

    • (路径模块)

      • **path.join()**

        • 将所有给定的路径拼接成完整的路径

        • 标准化生成的路径

        • :path.join目录2',目录3/目录4',目录5'

        • :/目录1/目录2/目录3/目录4/目录5/目录

      • **path.resolve()**

        • 同path.join()

        • 区别:将路径或路径片段转换为绝对路径

        • path.resolve(__dirname,'static')

    • url模块

      • **url.parse()**

        • :将网站分析成对象

        • : url.parse(urlString[,parseQueryString, slashesDenoteHost])

        • urlString:表示url地址

        • parseQueryString:如果是布尔值true,和解析查询字符串,否则不分析

        • slashesDenoteHost:如果为true表示//后面,/前面是主机名(如果是完整的url地址不影响)

        • :url对象

      • **url.format()**

        • : 把url对象解析成url地址字符串

        • : url.format(url对象)

        • : url地址字符串

      • **url.resolve()**

        • :把两段url构成一个完整的片段url

        • : url地址字符串

    • querystring模块(对查询字符串进行更强的分析)

      • ** querystring.stringify() **

        • :将对象转换为查询字符串

        • :querystring.stringify(要转换的对象[,自定义分隔符,自定义键值之间的连接符])

        • 默认使用&分隔(由第二个参数决定)

          • var o1 = querystring.stringify({    name:'pipi',    course:[11,22,33] },',') //name=pipi,course=11,course=22,course=33
        • 键值用=连接(连接由第三个参数决定)

          • var o1 = querystring.stringify({    name:'pipi',    course:[11,22,33] },, //name:pipi,course:11,course:22,course:33

        • :查询字符串

        • var o1 = querystring.stringify({   name:'kimi',   course:['nodejs','vue','react'] }) //name=kimi&course=nodejs&course=vue&course=react

      • **querystring.parse()**

        • :将查询字符串转换为对象

        • :querystring.parse(查询字符串要转换[,自定义分隔符,自定义键值

        • :对象

        • var o1 = querystring.parse("name=kiki&pwd=1234") // { name: 'kiki', pwd: '1234' }
      • ** querystring.escape()**

        • 字符串url编码

        • var o1 = querystring.escape("http://www.baidu.com/search?wd=千锋教育"); //http://www.baidu.com/search?wd=?%8%83%E9%94%8B%E6%95%99%E8%82%B2
      • ** querystirng.unescape()**

        • 对url进行解码

        • var o1 = querystring.unescape('http://www.baidu.com/search?wd=千锋教育')
          //http://www.baidu.com/search?wd=千锋教育

    • fs模块

      • __filename:当前文件的绝对路径

      • __dirname: 当前文件所在目录的绝对路径

      • fs.stat(获取文件/文件夹信息)

        • fs.stat(__filename,(err,stats)=>{
            // err:是错误信息
            // stats:获取到的文件信息
            console.log(stats) ;// 对象
            // 判断是不是文件
            console.log(stats.isFile());
            // 判断是不是文件夹
            console.log(stats.isDirectory());
          })
      • fs.mkdir(创建文件夹)

        • fs.mkdir('./public',(err)=>{
            if(!err){
              // 如果没有错误信息
              console.log('创建文件夹成功')
            }
          })
          
      • fs.writeFile(向文件写入内容 异步)

        • fs.writeFile(filePath,text,(err)=>{
            if(!err){
              console.log('文件写入成功')
            }
          })
          
      • fs.appendFile (向文件追加内容 异步)

        • fs.appendFile(filePath,text,(err)=>{
            if(!err){
              console.log('成功写入文件')
            }
          })
          
      • fs.readFile(读取文件)

        • //方法一
          fs.readFile(filePath,(err,data)=>{
            if(!err){
              // 编码格式转换ss
              console.log(data.toString())ss
            }
          })
          
        • //方法二
          fs.readFile(filePath,'utf-8',(err,data)=>{
            if(!err){
              console.log(data)
            }
          })
          
      • fs.readdir(读取文件目录)

        • const dirPath = path.resolve(__dirname,'public')
          // 读取文件目录
          fs.readdir(dirPath,(err,files)=>{
            // err:错误
            // files:是一个数组,里面是读取到的文件夹里面的子文件/子文件夹名称
            if(!err){
              console.log(files)
            }
          })
          //返回一个s
          
      • fs.rename(文件名修改)

        • fs.rename("要重命名的文件地址","新名字",(err)=>{
            if(!err){
              console.log('文件名修改成功')
            }
          })
          
        • const fs = require('fs')
          const path = require('path')
          
          const filePath = path.resolve(__dirname,'public','js/a.js')
          const newName = path.resolve(__dirname,'public','js/index.js')
          
          fs.rename(filePath,newName,(err)=>{
            if(!err){
              console.log('文件名修改成功')
            }
          })
          
      • fs.rm(删除文件)

        • fs.rm(filePath,(err)=>{
            if(!err){
              console.log('文件删除成功')
            }
          })
          
      • fs.rm(删除文件夹)

        • s.rm(dirPath,{recursive:true},(err)=>{
            if(!err){
              console.log('文件夹删除成功')
            }
          })
          
        • 注:需要添加{recursive:true},表示递归删除文件夹里面的内容再删除文件夹

    • events模块

      • 创建事件触发器(第一步)

        • const EventEmitter = require('events');

        • const emitter = new EventEmitter()

      • 定义事件监听器(第二步)

        • emitter.on(可触发多次)

        • emitter.on('many',()=>{
            console.log('many事件发生了')
          })
          
        • emitter.once(只触发一次)

        • emitter.once('one',()=>{
            console.log('one事件发生了')
          })
          
        • 触发(emit)

          • emitter.emit('many')
            emitter.emit('one')
            
    • stream模块(流模块)

      • fs.createReadStream(fromPath) (inp)

      • fs.createWriteStream(toPath) (out)

        • once

          • inp.once('data',(chunk)=>{
            	//chunk获取到的数据流
            })
            
        • on

          • inp.on('data',(chunk)=>{
            	//chunk获取到的数据流
            })
            
          • inp.on('end',()=>{
              console.log('数据读取完成');
              out.end()
            })
            
          • inp.on('error',()=>{
              console.log('数据写入错误')
            })
            
        • pipe

          • inp.pipe(out) 
            //文件读取流(inp)与 文件写入流(out)之间建立一个管道
            
    • http模块

      • http.request()

        • 语法:

          • 第一步: 书写请求行

            • const req = http.request(url,callback) const req = http.request(options,callback)

          • 第二步: 书写请求体

            • req.write()

          • 第三步: 结束请求

            • req.end()

        • 例子

          • //方法一
            const https = require('https')
            const url = "https://www.lagou.com/"
            let html = "";
            const req = https.request(url,(res)=>{
              // 设置响应的编码集
              res.setEncoding('utf-8');
              // 当有数据可以读取的时候触发data事件
              res.on('data',(chunk)=>{
                html += chunk;
              })
              // 当数据读取完成的时候触发end事件
              res.on('end',()=>{
                console.log(html)
              })
              // 当有数据读取错误的时候触发error事件
              res.on('error',(err)=>{
                console.log(err)
              })
            })
            req.end()
            
          • 方式二
            const req = https.request({
              host:"www.lagou.com",
              ports:"443",
              method:'get',
              path:'/',
              headers:{}
            },(res)=>{
              // 设置响应的编码集
              res.setEncoding('utf-8');
              // 当有数据可以读取的时候触发data事件
              res.on('data',(chunk)=>{
                html += chunk;
              })
              // 当数据读取完成的时候触发end事件
              res.on('end',()=>{
                console.log(html)
              })
              // 当有数据读取错误的时候触发error事件
              res.on('error',(err)=>{
                console.log(err)
              })
            })
            req.end();
            

      • http.get()

        • 语法:同http.request()

        • 区别:

          • 不用设置method,是get请求

          • 不用书写req.write(),get请求没有请求主体

          • 不用调用req.end(),会自动调用

        • 例子:

          • https.get(url,(res)=>{
              // 设置响应的编码集
              res.setEncoding('utf-8');
              // 当有数据可以读取的时候触发data事件
              res.on('data',(chunk)=>{
                html += chunk;
              })
              // 当数据读取完成的时候触发end事件
              res.on('end',()=>{
                console.log(html)
              })
              // 当有数据读取错误的时候触发error事件
              res.on('error',(err)=>{
                console.log(err)
              })
            })
            

      • http.createServer()

        • 作用:开启服务器

        • nodejs实现webServer

          • 原理:根据req.url来区分客户的请求路径,根据不同的访问路径,给用户响应不同的资源

          • const http = require('http');
            const fs = require('fs')
            const path = require('path')
            let num = 0;
            const server = http.createServer((req,res)=>{
              // 只要有客户端请求,就会执行这个函数
              // req:请求对象
              // res:响应对象
              // 获取请求路径
              let url = req.url;
              if(url!="/favicon.ico"){
                if(url=="/"){
                  url = "/index.html"
                }
                // 设置响应头
                res.setHeader('content-type',"text/html;charset=utf-8")
            
                // 通过请求路径,拼接出文件的本地地址
                const  filePath = path.resolve(__dirname,'public'+url)
                fs.stat(filePath,(err,stats)=>{
                  // 文件路径不存在
                  if(err){
                    res.statusCode = 404;
                    res.end(`${url} 不存在`)
                  }
                  // 如果是一个文件
                  else if(stats.isFile()){
                    res.statusCode = 200;
                    fs.createReadStream(filePath).pipe(res)
                  }
                  // 如果是一个文件夹
                  else if(stats.isDirectory()){
                    fs.readdir(filePath,(err,files)=>{
                      res.statusCode = 200;
                      res.end(files.join('/'));
                    })
                  }
                })
              }
              
            })
            
            server.listen(8080,()=>{
              console.log('服务器开启在:http://10.20.158.132:8080')
            })
            
        • : 没有http.post方法

    • cheerio(第三方模块)

      • 安装:npm install cheerio -D

      • 使用方法和jquery类型

      • jquery操作的是dom节点

      • cheerio操作html字符串

      • 可用于爬虫(具体看E:\2022资料\tree-grup\资料\01node-api\源代码\spider.js)

    • express(web 开发框架)

      • :npm install express -S

      • 使用三步走

        • //导入:
          const express = require('express');
          const path = require('path')
          const app = express()
          //静态资源中间件函数: express自己写好的,你可以直接使用
          //express.static(root, [options])
          app.use(express.static(path.resolve(__dirname,'文件夹名')))
          //监听
          app.listen(9090,()=>{
              console.log("http://10.20.158.121:9090")
          })
          
          • [利用 Express 托管静态文件 - Express 中文文档 | Express 中文网 (expressjs.com.cn)](https://www.expressjs.com.cn/starter/static-files.html)

      • app.use('路由',中间件函数)

        • 如果不写路由,就可以匹配所有的请求

        • 如果写路由,就必须以路由开头的才能匹配

        • app.use('/abc',(req,res)=>{
              //只要有请求,就会执行这个函数是经过express封装的请求对象,可以使用原生node的方法,也有自己的方法
          	//req:是经过express封装的请求对象,可以使用原生node的方法,也有自己的方法
              //res:响应对象,可以使用原生node的方法,也有自己的方法
              res.end('all')
          })
          
      • 路由中间件

        • 如何实现?

        • 一个主js文件(main.js)

          • const express = require('express');
            // 这个包是为了解析请求主体(要安装)
            const bodyParser = require('body-parser')
            const app = express()
            
            app.use(bodyParser.json()) // 解析 application/json 格式的请求主体
            app.use(bodyParser.urlencoded({ extended: true })) // 解析 application/x-www-form-urlencoded 格式的请求主体
            
            
            app.use('/user',require('./routers/user.js'))
            
            
            app.listen(8080)
            

        • 一个专门存储接口api的文件夹(routers),里面放接口文件(user.js)

          • 根据需求写接口

            • // 用户相关接口
                // /user/login?un=xxx&pw=xxx
                // /user/register?un=xxx&pw=xxx
              
          • // 路由中间件
            const express = require('express');
            const router = express.Router();
            
            // 登录接口
            router.get('/login',(req,res)=>{
              // 获取请求的查询字符串
              console.log(req.query);
              res.json(req.query)
            })
            
            // 注册接口
            router.post('/register',(req,res)=>{
              // 如果要使用req.body获取请求主体
              // 需要安装: npm install body-parser -S
              // 获取请求的请求主体
              console.log(req.body)
              res.json(req.body)
            })
            
            注意:导出
            module.exports = router;
            
      • app.get('路由',中间件函数)

        • 匹配get请求,路由要求精确匹配

        • 如果有写*,表示匹配所有路由

        • app.get('/login',(req,res)=>{
            // express封装的res上的方法
            // res.send('字符串')
            res.send('hello world')
          
            // res.json(对象)
            res.json({a:1,b:2})
          })
          
        • 响应:(选其一)

          • res.send('字符串')

          • res.json(对象)

      • app.post('路由',中间件函数)

        • 匹配post请求,路由要求精确匹配

        • 如果有写*,表示匹配所有路由

        • app.post('/api',(req,res)=>{
            res.json({path:'/api',message:"post"})
          })
          

      • app.all('路由',中间件函数)

        • 匹配所有请求,路由要求精确匹配

        • 如果有写*,表示匹配所有路由

        • 专门用于处理404的

        • app.all('*',(req,res)=>{ 
            res.json({code:404})
          })
          
      • 模板中间件(后端把html拼接好,直接返回给前端可以使用ejs模板引擎进行文件渲染)

        • : npm install ejs -S

        • :(在当前这js文件的同级下有一个views的文件夹,里面存储list.ejs文件用来写模板中间件)

          • app.set('views',path.resolve(__dirname,'views'));告诉app,模板文件所在的根目录

          • 告诉app,模板文件用哪个包解析 app.set('view engine','ejs');

          • res.render('在设置的模板文件目录中的模板文件路径',要在模板文件中使用的变量集合)

          • const express = require('express');
            const path = require('path')
            const app = express();
            
            // 后端把html拼接好,直接返回给前端
            // 可以使用ejs模板引擎进行文件渲染
            // 下载: npm install ejs -S
            // 配置:
            // 告诉app,模板文件所在的根目录
            app.set('views',path.resolve(__dirname,'views'));
            // 告诉app,模板文件用哪个包解析
            app.set('view engine','ejs');
            
            app.get('/data',(req,res)=>{
              // 在配置了模板引擎以后,res就多了一个方法 : 
              // res.render('在设置的模板文件目录中的模板文件路径',要在模板文件中使用的变量集合)
              // 在views/list.ejs中可以使用变量:age和arr和count
              // 把解析完的结果返回
              res.render('list',{
                age:"<h1>hello world</h1>",
                arr:[
                  {name:'吴波',task:'纪律委员'},
                  {name:'海文',task:'学习委员'},
                  {name:'小磊',task:'班级班长'},
                ],
                count:100
              })
            })
            app.listen(9090)
            
    • 路由

      • 运行跨域请求

        • 下载: npm install cors -S

        • 导入: const cors = require('cors')

        • 使用:app.use(cors())

      • 解析请求主体

        • npm install body-parser

        • app.use(bodyParser.json()) // 解析 application/json 格式的请求主体
          app.use(bodyParser.urlencoded({ extended: true })) // 解析 application/x-www-form-urlencoded 格式的请求主体
          
    • mongodb

      • mysql:关系型数据库 -- 表结构

      • mongodb:非关系型数据库 -- 数据库里面是一个一个的json文件

      • 在术语上

        • 数据库: database

        • mysql => 数据库里面有表: table

        • mongodb => 数据库里面有集合: collection

        • mysql => 表里面有数据行: row

        • mongodb => 集合里面有文档: document

      • 常用的shell命令:

        • 1、帮助命令

          -->help

          -->db.help()

          2、数据库操作命令

          -->show dbs

          -->use dbname 切换数据库

          -->db / db.getName() 查看当前数据库名称

          -->db.stats() 显示当前DB的状态

          -->db.version() 查看当前DB的版本

          -->db.getMongo() 查看当前DB的连接的主机地址

          -->db.dropDatabase() 删除当前DB

          3、创建数据库和集合

          -->use project 不存在就创建,存在就切换至

          -->db.createCollection('user') // 创建user集合

          -->show dbs

          -->show collections / db.getCollectionNames()

          -->db.getCollection('music') 获取指定集合

          -->db.printCollectionStats() 打印指定集合的状态

          4、集合中的文档操作:

          -->db.user.insertOne({}) 向集合中插入文档

          -->db.user.insertMany([{},{}])

          -->db.user.save({})

          -->db.user.updateOne({"name":"cyr"}, {$set:{"age":100}})

          -->db.user.updateMany({},{$set:{}})

          -->db.user.deleteOne({"name":"jiaming"})

          -->db.user.deleteMany({})

          -->db.user.remove({}) // 要指出删除的条件

          -->save和insert的区别:

          + 新增的数据中存在主键,则再次插入相同的主键时insert() 会提示错误

          + 而save() 则更改原来的内容为新内容

          + 没有saveMany命令

          5、聚集集合查询

          -->db.集合名.find({查询条件对象},{显示对象})

          -->db.user.find() 查询所有记录

          -->db.user.find({age:22}) 查询age=22的记录

          -->db.user.find({age:{$gt: 22}}) 查询age>22的记录

          -->db.user.find({age:{$lt: 22}}) 查询age<22的记录

          -->db.user.find({age:{$gte: 22}}) 查询age>=22的记录

          -->db.user.find({age:{$lte: 22}}) 查询age<=22的记录

          -->db.user.find({age:{$gte:20, $lte:30}}) 查询age>=20 && age<=30的记录

          -->db.user.find({name:/cyr/}) 查询name中包含'cyr'的记录

          -->db.user.find({name:/^cyr/}) 查询name以'cyr'开头的记录

          -->db.user.find({},{name:1,age:1}) 查询所有记录,只返回name和age字段(1-显示 0-不显示)

          -->db.user.find({age:{$gt:20}},{name:1,age:1}) 查询age>20的记录,只返回name和age字段

          -->db.user.find().sort({age:1}) 按age进行升序排列

          -->db.user.find().sort({age:-1}) 按age进行降序排列

          -->db.user.find({},{name:1,age:1,_id:0}).sort({age:1})

          -->db.user.find({name:'cyr',age:22}) 查询name='cyr' && age=22的记录

          -->db.user.find().limit(5) 只查询前5条记录

          -->db.user.find().skip(10) 查询10条以后的所有数据

          -->db.user.find().skip(5).limit(5) 查询第6~10条记录

          -->db.user.find({$or:[{age:20},{age:25}]}) 查询age=20或者age=25的记录

          -->db.user.findOne() 查询满足条件的第一条记录

          -->db.user.find({age:{$gte:25}}).count() 查询满足条件的记录的总条数

        • 常用:

          • use 数据库名

          • db.createCollection('user') 创建集合

          • db.user.insertOne({}) 向集合中插入文档

    • node操作mongodb数据库

      • 使用第三方模块: mongoose

      • 下载:npm install mongoose -S

      • 入门创建五步骤

        • const mongoose = require('mongoose');

        • 链接数据库 mongodb://localhost/数据库名 mongoose.connect('mongodb://localhost/qf');

        • 创建表(第一个参数:表名尽量用复数,第二个参数:定义表里面的字段)mongoose.model('表名',表结构

          • const Users = mongoose.model('users', {
              name:String,
              age:Number,
              pw:String,
              create_time:Number
            });
            
        • 创建一条数据

          • const student = new Users({ 
              name: '程磊',
              age:12,
              pw:'123456',
              create_time: Date.now()
            });
            
        • 把创建好的数据插入集合中

          • student.save().then((doc)=>{
              console.log('文档插入集合成功')
              console.log(doc)
            })
            
      • 链接数据库

        • // 1 导入mongoose模块
          const mongoose = require('mongoose');
          
          // 2 链接数据库,pinxixi是要链接的数据库名称
          mongoose.connect('mongodb://127.0.0.1:27017/pinxixi')
          
          // 3 获取数据库链接
          const db = mongoose.connection;
          
          // 4 事件监听,判断是否链接成功
          db.once('open',()=>{
            console.log('数据库链接成功')
          })
          
          db.on('error',(err)=>{
            console.log(err)
          })
          
          
      • 创建数据集合

        • require('./01');
          
          // 导入mongoose模块
          const mongoose = require('mongoose');
          // 创建集合的字段名和数据类型的规范
          const articleSchema = mongoose.Schema({
            title:String,
            content:String,
            createTime:Number,
            author:String
          })
          // 根据上面的规范创建一个articles表
          const articles = mongoose.model('articles',articleSchema)
          
          // 导出创建好的articles表
          module.exports = articles;
          
          
      • 插入数据

        • //导入要操作的表
          const articlesModel = require('./02')
          articlesModel.insertMany([
              {
                  title:'tree',
                  content:'mongoose 进行插入操作指南3',
                  createTime:Date.now(),
                  author:'多多'
              },
              {
                  title:'four',
                  content:'mongoose 进行插入操作指南4',
                  createTime:Date.now(),
                  author:'次次'
              }
          ]).then((doc)=>{
              console.log(doc);
          })
          
          

      • 查询数据

        • //导入要操作的表
          const articlesModel = require('./03')
          //查询title:'tree'的数据
          articlesModel.find({title:'tree'}).then((doc)=>{
              console.log(doc);
          })
          //查询时间在2022/5/11 13:23:00之前的数据
          articlesModel.find({createTime:{$lt:new Date('2022/5/11 13:23:00').getTime()}}).then((doc)=>{
              console.log(doc);
          })
          //查询 id
          articlesModel.findById('627b46c08f5a4300fc74fe7c').then((doc)=>{
              console.log(doc);
          })
          
      • 更新数据

        • //更新一条
          articlesModel.updateOne({author:"张三"},{$set:{title:"1111"}}).then(result=>{
            console.log(result);
            // 查看更新以后的数据
            articlesModel.find({}).then(doc=>{
              console.log(doc)
            })
          })
          
        • //更新多条
          articlesModel.updateMany({author:'次次'},{$set:{title:'danger'}}).then(res=>{
              console.log(res);
              articlesModel.find({}).then(res=>{
                  console.log(res);
              })
          })
          

      • 删除数据

        • //删除一条
          articlesModel.deleteOne({title:'tree'}).then(res=>{
              console.log(res);
              articlesModel.find({}).then(doc=>{
                  console.log(doc);
              })
          })
          
        • //删除多条
          articlesModel.deleteMany({title:'four'}).then(res=>{
              console.log(res);
              articlesModel.find({}).then(doc=>{
                  console.log(doc);
              })
          })
          

    • 注意:

      • 使用模块请先导入

      • 如果一个请求经过多个中间件,多个中间的req和res是共享的

npm包管理工具

  • 什么是npm

    • 是基于commonjs规范的包管理工具

    • node安装完成以后,npm同步安装 npm -v

    • nrm可以切换仓库镜像源,建议使用淘宝镜像

  • 管理模块

    • npm init 生成package.json文件

    • 作用: 便于模块管理 便于代码转移

    • 项目依赖 和 开发时依赖的区别

  • 模块安装

    • 查看指定包信息: npm info name

    • 查看安装了哪些包: npm list

    • 全局安装: npm install name --global

      • 简写: npm i name -g

    • 本地安装项目依赖: npm install name --save

      • 简写: npm i name -S

    • 本地安装开发时依赖: npm install name --save-dev

      • 简写: npm i name -D

    • 安装指定版本

      • npm install name@版本号 --save

    • 模块安装完成,在node_modules文件夹里面

      • 这个文件夹一般不随项目转移

    • 模块卸载

      • npm uninstall name -g

      • npm uninstall name -S

  • yarn:另一个包管理工具

    • 安装yarn: npm install yarn -g

    • yarn和npm二选一,即可

重要概念

  • BSR 客户端渲染(可异步渲染)

    • 前端利用ajax等数据交互方式向后端请求数据

    • 把数据变成html字符串,进行页面的局部刷新

    • 方法:ajax/jsonp/fetch -> 获取数据 -> html节点/html字符串 -> 插入页面

    • 优点:灵活,前后端分离,方便前后端更新维护

    • 缺点:对SEO不友好,增加http请求次数,减缓了页面加载速度

  • SSR 服务端渲染

    • 在后端把数据从数据库取出来以后,直接通过模板引擎渲染成html字符串

    • 客户端请求页面的时候,直接返回这个页面拼接好的html字符串

    • 也就是说后端可以把数据直接插入html字符串

    • 优点:对SEO友好,减少http请求次数,加快了页面加载速度

    • 缺点:不灵活,前后端耦合性太高

  • Rest风格的api设计

    • 每一个url代表一种资源

    • 客户端使用GET,POST,DELETE,PUT,PATCH等方式请求资源

    • 从客户端到服务端的每个请求必须包含理解请求所必要的信息

      • get类型 /user 获取所有用户信息

      • post类型 /user 插入用户信息

      • delete类型 /user/1 删除id=1用户信息

      • put类型 /user/1 更新id=1用户的所有信息

      • patch类型 /user/1 更新id=1用户的部分信息

    • 安装:npm install -g json-server

      • 创建一个db.json文件,并写入一个接收的数组

        • {
          “user”:[]
          }
          
      • json-server --watch db.json

      • 使用postman访问(http://localhost:3000/user)

        • post请求即为添加数据 参数写在body中

跨域问题

  • 出现:协议/端口/域名有一个不同就是跨域

  • 解决

    • cors跨域

      • 在目标服务器设置跨域请求头

        • res.header("Access-Control-Allow-Origin", "*");
          res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,== OPTIONS");
          res.header("X-Powered-By",' 3.2.1')
          res.header("Content-Type", "application/json;charset=utf-8");
          
      • 一般不自己写,引入一个(给目标文件引入)

        • npm install cors -S

        • const cors = require('cors')

        • app.use(cors())

    • jsonp

      • 不是xhr请求,是利用script的src可以跨域的特点

      • 提前准备一个函数,通过src请求后端接口返回这个函数的调用,实参就是需要的数据,函数名通过callback传递: callback=函数名

      • 如果a文件需要访问b中的数据

        • a文件中需要准备一个返回的函数,并一个script标签连接请求地址

        • function getList(data){
            console.log(data)
          }
          插入一个script标签请求后端接口,后端返回一个函数调用
          通过callback参数告诉后端要函数名
          <script src="http://localhost:9090/list?callback=getList"></script> 
          
        • b文件则调用

        • const express = require('express');
          const app = express();
          app.get('/list',(req,res)=>{
          res.jsonp({host:"b server",port:9090})
          }
          
    • 代理

      • 引入包 http-proxy-middleware

      • 使用:

        • 导入:const express = require('express');

          const { createProxyMiddleware } = require('http-proxy-middleware');

        • 设置 app.use('路径',createProxyMiddleware({

          }))

          • app.use("/list",createProxyMiddleware({
              target:'http://localhost:9090/',
              changeOrigin:true
            }))
            

token

  • token引入

    • 客户端频繁向服务器发送请求,大量的接口需要权限验证,就需要大量的数据库查询用户名和密码是有有效,服务器压力大,有没有一种办法可以不用频繁进行数据库验证,token就是为此产生的

  • token长什么样?

    • LKJjLHhlHwerJlkhl324HyiyHhIUYiyGkgIUYG234kgIUYTGKgIUYiuyG

  • token的目的

    • 减轻服务器的压力

    • 减少频繁的查询数据库

  • token从哪里来

    • token是在服务器产生的,当客户端登录或者调用接口的时候,会返回token,客户端用户收到token以后,保存在前端(比如保存在localStorage中),之后请求其他有访问权限的后端接口时,需要把token携带上传递给后端进行验证

  • 如何把token传递给后端呢?

    • 这要根据后端的需要,通常会把token放在headers中进行传递

  • 使用:

    • 下载包: npm install jsonwebtoken

    • [jsonwebtoken - npm (npmjs.com)](https://www.npmjs.com/package/jsonwebtoken)

WebSocket

  • 是什么

    • 用于建立服务器和客户端的双向交互通信,打开一条通道,客户端可以主动给服务器发消息,服务器也可以主动给客户端发消息,这个链接的一端就被称为socket

  • 主要功能

    • 向对方发送消息

    • 基于事件驱动接收对方发送的消息

  • WebSocket和socket.io之间的区别

    • socket.io是一个开源库,他对WebSocket进行封装

    • 增强了浏览器的兼容性

    • 使用起来更方便功能更强大

    • 使用on绑定事件监听

    • 如果绑定的是自定义事件,用emit触

  • 案例(E:\2022资料\tree-grup\test\04-day\socketserver)

    • 聊天室开发

      • socket服务器开发(socket底层是基于net模块的)

        == 接收客户端的消息(基于事件驱动的)

        == 群发消息给所有客户

      • socket客户端开发

        == 接收服务端的消息(基于事件驱动的),要渲染在页面上

        == 把消息发送给服务器

      • 解释

        • socket:就是链接到socket服务器的另一端

        • 通过io可以群发

        • 通过socket可以私聊

      • 例子:

        • // const socket = io('http://10.20.158.121:9090')
                  const socket = io('http://192.168.0.106:9090')
                  let count = 0
                  socket.on('message-from-server',(message)=>{
                      count++
                      $('#top').append('<div class="row">'+message+'</div>')
                      $('#top').scrollTop(count*35)
                  })
                  
                  $('#send').click(()=>{
                      let val = $('#message').val().trim()
                      socket.emit('message-from-client',val)
                      $('#message').val('')
                  })
          
                  $('#message').keyup((e)=>{
                    if(e.keyCode == 13){
                        let val = $('#message').val().trim();
                        socket.emit('message-from-client',val)
                      $('#message').val('')
                    }
                  })
          
  • pm2部署项目

    • 管理多个node项目

    • 安装:npm install -g pm2

    • pm2管理单个node项目

      • 启动: pm2 start 启动服务器的入口js文件

      • 列出所有应用: pm2 list

      • 结束应用: pm2 stop id

      • 删除进程: pm2 delete id

    • pm2管理多个node项目

      • 使用命令PM2 ecosystem 或者 pm2 init,初始化配置文件ecosystem.config.js

      • 配置ecosystem.config.js文件

        • name 指定项目名称

        • script 指node项目的入口启动文件

      • 启动|重启|停止|删除多个node服务器

      • pm2 [start|restart|stop|delete] ecosystem.config.js

      • pm2 list

      • 下载两个包 npm i socket.io -s nom i socket socketserver public index.html socket.io.js(nodemoudel中的) app.js

        配置路由 并检测postman 写接口

vue2

  • vue: 渐进式JavaScript 框架

  • 选择vue的原因

    • 超快的虚拟dom,很多省心的优化

    • 繁荣的生态系统

    • vue@2+vue-cli+vue-router@3+vuex@3+element ui+vue-i18n@8+...

    • vue@3+vue-cli+vue-router@4+vuex@4+element pluse+vue-i18n@9+.. == 对开发人员友好 == 兼容性: Vue 不支持 IE8 及以下版本 == 我们使用的v版本2.6.14

  • 选项

    • data html标签中可以使用data里定义的变量,使用插值语法{ {表达式}},可以通过vue实例访问里面的data选项

      • data:{}

      • data:function(){return {}}

    • el 选项指定vue实例接管的根标签,书写根标签的css的选择器

      • methods 里面定义在html标签中可以使用的方法名

    • $mount方法 挂载

    • template选项 指定要替换el指定的标签的html字符串

      • template的优先级高于el指定标签本身的

      • vue实例在编译html字符串的时候如果现象有template, 就用template选项里面的html字符串,如果没有就用el指定标签本身的html字符串

      • 实际工作用一般都是用template,写在body里面的属性和标签名,遵循html标准,不区分大小写,写在template里面的属性和标签名,区分大小写

    • computed选项(计算属性)

      • 在computed里定义的函数,使用的时候直接写函数名,不要写函数名(),内部会自动执行这个函数,显示返回值

      • 计算属性的语法:

        • 属性名: 用于获取变量值的函数

        • 属性名: {get:获取变量值的函数,set:设置变量值的函数}

  • 指令:

    • 文本类指令

      • v-text

      • v-html

      • v-pre 加了这个指令的标签及其子元素不会被编译

      • v-once 加了这个指令的标签及其子元素只会被编译一次,后续就当静态内容

      • v-cloak vue编译完成以后,会把所有标签上看到的v-cloak移除(隐藏未编译的 Mustache 标签直到实例准备完毕)

        • [v-cloak]{ display:none; }配用

    • v-on

      • 语法

        • v-on:事件类型="事件处理函数名"

        • v-on:事件类型="事件处理函数名()"

        • v-on:事件类型="事件处理函数名(参数1,参数2,...)"

          • 有一个特别的参数$event

        • v-on:可以简写成: @

      • 事件修饰符

        • .prevent: 阻止事件默认行为

        • .stop: 阻止冒泡

        • .self: 只有事件的target是我自己,才触发事件,冒泡上来不触发 (大都用于父类)

        • .once:只发生一次

        • .enter v-on:keyup.enter="addTask"

        • .right

        • v-on:keydown.alt.67=""

        • v-on:mousedown.left=""

    • v-bind

      • 语法: v-bind:属性名="js表达式"

      • 简写::属性名="js表达式"

      • 使用:

        • 图片:src上 <img :src="imgSrc" alt="/>

        • class动态属性

          • 动态属性原始语法

            • <div v-bind:class="className"></div>

          • class数组语法

            • <div v-bind:class="['bg','border']"></div>

          • class对象语法

            • <div :class="{bg:false,border:true,r:false}"></div>

          • class数组语法和对象语言一起使用

            • <div :class="['border',{bg:false},{r:true}]"></div>

        • style动态属性

          • 动态属性原始语法

            • <div :style="style"></div>

          • style的对象语法

            • <div :style="{background:'red',border:'10px solid #ccc'}"></div'

          • style的数组语法

            • <div :style="[{background:'red'},{border:'10px solid #ccc'}]"></div>

    • 条件渲染指令: v-if

      • 通过控制节点的插入和销毁来控制显示隐藏

      • 语法: v-if="值为true就显示,值为false就隐藏"

      • 如果要切换显示隐藏的有多个元素可以把他们放在一起

        vue里面有一个标签标签叫做类似js里面的()

    • v-show 通过控制节点的样式的display来显示和隐藏

      • 语法: v-show="值为true就显示,值为false就隐藏

    • v-for循环渲染

      • 语法:

        • v-for="item in arr"

        • v-for="(item,index) in arr"

        • v-for="(val,key) in obj"

        • v-for="(val,key,index) in obj"

      • v-for和v-if强烈不推荐在同一个标签上使用

        • vue@2 : v-for 的优先级比 v-if 更高

        • vue@3 : v-if 的优先级比 v-for 更高

      • v-for推荐配合key属性使用

        • key必须是不能重复的

        • key建议使用字符串或者number

        • key属性是在比较不同的虚拟dom的时候起作用

        • 如果key相同,就是原来的那个节点

        • 如果key不相同,就不是同一个节点,就需要销毁不存在的key对应的节点

    • v-model

      • 双向绑定(text变量的变化会导致界面的更新,界面上文本框或者文本域的value的变化会导致text这个变量的更新)

      • 修饰符

        • .lazy

        • .trim

        • .number

      • 复选框:

        • <input type="checkbox" value="football" v-model="flag">

        • 如果flag初值是布尔值:复选框把选中的状态双向绑定到flag这个变量上

        • 如果flag初值是数组:把复选框选中元素的value同步到这个数组里面

      • v-model用于组件元素上

        • <son v-model="text"></son>等价于<son v-bind:value="text" @input="inputHandler"></son>

      • 总结:

        • v-model

          == 还可以使用在组件上

          == 用于双向数据绑定

          == 数据的变化导致界面更新

          == 界面更新导致数据的更新

          == v-model默认把变量绑定到value属性上

          == 变量值的变化会导致元素value的变化

          == v-model默认监听input事件

          == 把元素的value值更新到变量上

  • render选项

    • 优先级: render渲染函数>template模板字符串>el元素的html字符串

    • render(h){
                     return h('p',{
                         class:{
                             a:true,
                             b:true
                         },
                         style:{
                             fontSize:'100px'
                         },
                         attrs:{
                             id:'box',
                             index:123
                         }
                     },[
                     h('h3',"我是p里面的h3标签")
                     ])
                 }   
      

  • 过滤器

    • 过滤器可以在{ {}}和 v-bind:属性名="" 里面使用

    • 使用方法:

      • { {变量|过滤器|过滤器(实参1,实参2,....)}} 可接多个

      • v-bind:属性名="变量|过滤器|过滤器(实参1,实参2,....)"

    • 全局过滤器

      • 语法:Vue.filter('过滤器名称',function(val){})

        • val就是使用过滤器 | 前面的变量值

        • return 返回值就是经过处理以后新值

    • 局部过滤器

      • 语法:

        • new Vue({
                filters:{
                 "过滤器名称":function(val,arg1,arg2,...){
                   // val就是使用过滤器 | 前面的变量值
                  // arg1,arg2,...给过滤器函数传递的其他参数
                 }
                }
              })
          

  • 侦听器(watch)

    • 定义变量的侦听器,一旦被侦听的变量的值发生改变,就会触发侦听器

    • 语法:

      • {要侦听的变量名: 数据变化的处理函数}

      • {要侦听的变量名:{

        handler:数据变化的处理函数,

        deep:是否深度监听,

        immediate:定义函数的时候立即执行一次

        }}

    • 对象类型如何侦听?

      • 当侦听的变量为一个对象(复杂数据类型)时,直接改变对象中的值,由于监听的对象,比较的是地址,地址没有变化无法监听到,需要监听地址里面内容的变化,需要

      • 如果对象list的地址变了,那这个对象的值就变化(也可以侦听到)

        • this.list = {
                     ...this.list,
                     name:this.newName
                   }
          

  • 自定义指令

    • 指令都是v-开头的,所以我们自定义指令的时候,不用写v-, 用的时候要加上

    • - 所有vue实例都能使用

      • 语法:

        • Vue.directive('指令名',{
          
          ​     // 当被绑定的元素插入到 DOM 中时执行inserted这个钩子函数
          
          ​     inserted:()=>{},
          
          ​     // 只调用一次,指令第一次绑定到元素时调用
          
          ​     bind:()=>{},
          
          ​     // 所在组件的 VNode 更新时调用
          
          ​     update:()=>{}
          
          ​    })
          
      • 简写语法:

        • Vue.directive('指令名',(el,binding)=>{
                    // bind和update的时候会执行
                  })
          
    • - 只有定义指令的vue实例可以使用

      • new Vue({
                 directives:{
                   '指令名': {钩子函数},
                   '指令名': 钩子函数简写
                 }
               })
        
      • 例子:

        • Vue.directive('pos',(el,binding)=>{
               // bind和update的时候会执行
               console.log(el);// 指令所在的节点
               console.log(binding);// 书写的修饰符的细节信息
               console.log(binding.value);// =后面表达式的值101
               console.log(binding.arg);// :后面的left
               console.log(binding.modifiers);// 指令的修饰符集合
               // pos这个指令可以设置元素的定位
               // el.style.left = '100px'
               el.style[binding.arg] = binding.value+"px"
             })
          
  • 混入:mixin

    • 定义一个对象,这个对象包含一些vue选项

      • Vue.mixin(要混入的对象)

      • 所有实例都能使用混入的对象里面的vue选项

    • :

      • new Vue({mixins:[要混入的对象1,要混入的对象2,...]})

      • 只有定义混入的vue实例可以使用混入的vue选项

    • 注意:

      • 混入对象的选项和实例选项有冲突,用实例的选项的

      • 全局混入:慎用,一般用于做插件

      • vue@2 在mixin合并data的时候是深合并

      • vue@3 在mixin合并data的时候是浅合并

      • 生命周期函数在混入的时候,不会冲突,都执行

  • 中央事件总线

    • 即借助vue的一个实例去提供一个’电信公司‘,其他组件可借助这个vue的实例来通信

      • 实现

        • let bus = new Vue()

        • bus.$emit('其他组件自定义函数名',要传的数据) (通过事件 发送消息的人)

        • mounted(){ bus.$on('自定义函数名',(data)=>{ console.log(data) }) } (接收信息的人,即去bus这个电信公司办卡的人)

  • $refs

    • 使用(通常在mounted中获取)

      • 如果给一个普通的标签添加 ref=’xxx‘属性,使用vm.$refs.xxx 获取其真实DOM节点

      • 如果v-for循环出的标签有ref='xx'属性,我就可以通过 vm.$refs.xx 获取这个真实的dom节点的集合

      • 如果一个组件有ref='xx'属性,我就可以通过 vm.$refs.xx 获取这个组件实例对象

  • provide与inject选项

    • 在祖先实例中通过provide选项定义的变量,可以在其后代中通过inject选项引入来进行使用

    • 使用:

      • 祖先实例中: provide:{ num:100 }

      • 子孙组件中:inject:[ ’num‘ ] 直接{ { num }}使用

  • axios https://unpkg.com/axios/dist/axios.min.js

    • 基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中

    • 请求方法的简写方法

      • axios.get(url[, config])

      • axios.post(url[, data[, config]])

    • 请求方法完整

      • axios(config)

      • aixos(url,config)

    • axios的实例

      • 在实例中设置配置,后面直接用实例发请求,就所有的请求的baseURL都是设置好的,发请求的时候如果用server发请求,和axios发请求的方法是一样的,只不过用server发就都设置好了baseURL和responseType

      • const server = axios.create({
              // axios的config怎么写,这里的配置就怎么写
              baseURL:"http://localhost:8888",
              responseType:'json',
              headers:{
                token:localStorage.getItem('token')||''
              }
            })
        
    • 请求响应拦截器

      • 请求拦截器(给axios实例添加请求拦截器)

        • erver.interceptors.request.use(function(config){
                // 请求发送成功
                // config请求的配置项目,是一个对象
                // 你对config做一些事情,做完以后给回去
                config.headers.token = localStorage.getItem('token')||"";
                return config;
              },function(error){
                // 请求发送失败
                return Promise.reject(error);
              })
          
      • 响应拦截器(给axios实例添加响应拦截

标签: cn槽型连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台