IINde

代码格式化网站

vueuse函数库

axios

sass

修改伪类元素

vuepc适配

HTTP协议

post: 提交数据的方法​get: 获取数据的办法​md转换成index.htmli5ting_toc -f 代码格式化规范.md​​// js更改 root 里的变量document.documentElement.style.setProperty(`root变量`, 更改的值)document.documentElement.style.setProperty// 移除css一些属性document.documentElement.style.removeProperty("color");​    date = new Date(date)    var year = date.getFullYear()    var month = date.getMonth() + 1    var day = date.getDate()    var hour = date.getHours()    var minute = date.getMinutes()    var second = date.getSeconds()

鼠标点击事件

快速判断变量的类型

Object.prototype.toString.call(变量)

typeOf // typeOf []

instanceof // [] instanceof Array

Array.isArray([])

constructor // {}.constoructor

对调俩个变量的方法

// 简单的, 三个变量互调​// 数组, 将俩个数存入数组中然后, a=数组[0], b=数组[1] ​// 对象法, 跟数组类似​// 数组运算法    let a = 3 , b = 5    a = [b, b = a][0]​// 解构赋值法    let a = 3, b = 5    [a, b] = [b, a]

正则表达式

​var str = 'hello'    var pattern = /x/    const regxp = new RegExp(input, 'gi') // 全局匹配,并大小写    var result = pattern.exec(str)    console.log(result)​​String的扩展    includes(str)        判断字符串中是否包含5    startsWith(str)        判断字符串是否以str开头    endsWith(str)        判断字符串是否以str结尾    repeat(count)        重复字符串       字符串.match(正则) // 一个在字符串中执行查找匹配的 String 方法,它返回一个数组,在未匹配到时会返回 null。         替换正则表达式    字符串.replace(‘12’, ‘#’) // 12换成#匹配正则    var str = 'hello'    var pattern = /x/    var result = 正则.exec(字符串) // 一个在字符串中执行查找匹配的 String 方法,    // 他返回一个对象, 匹配到第一个的匹配内容。    //它返回一个数组,在未匹配到时会返回 null。    var result = 字符串.match(正则) // 一个在字符串中执行查找匹配的 String 方法,它返回一个数组,在未匹配到时会返回 null。    var result = 正则.test(字符串) // 判断是否在字符串中, 返回 true 或者 false    字符串.replace(/ok/g, '**')// 讲text 中的 ok 替换成 **     console.log(result)​let text = 'ssss'let a = /^a/ // 以a开头的字符串​let a = /a$/ // 以a 结尾的字符串​text.replace(/ok/g, '**') // 讲text 中的 ok 替换成 **text.replace(/ok/g, '**').replace(/jsg/g, 'jpg') // 讲text 中的 ok 替换成 ** 在吧 png 换成 jpg​输入框替换        const regxp = new RegExp(input)            if (this.souAll.username !== 'id') {              item[this.souAll.username] = item[this.souAll.username].replace(regxp, `<mark slot="one">${input}</mark>`)            }​​// 例子:     const str = 'XXXX 123 45345'    const number = str.replace(/D/g, '') // 他将会把所有的非数字转换成 ''

深拷贝和浅拷贝

浅拷贝只复制指向某个对象的指针, 而不是复制对象本身, 新旧对象还共享同一块内存

深拷贝复制出来了一个一模一样的对象, 修改新对象不会更改原有的对象

// 利用JSON.parse(JOSN.stringify(对象)),来进行深拷贝  let shen = { o: '你好' }    // let shen2 = Object.create(shen)    let shen2 = JSON.parse(JSON.stringify(shen))    // shen2.o = 'heoo'    console.log(shen)    console.log('-----');    console.log(shen2.o);// object.assign倒是完美一些,即使function还有set什么的都可以拿到,但是对于引用的,如果拷贝的对象里面有一个属性值是另一个对象,那么这一个    Object.assgin({}, author)  //author 是个对象​// 拷贝之后, 深拷贝用的Object.create 深拷贝的对象要用__proto__进行获取Object.create() 方法    let shen = { o: '你好' }    let shen2 = Object.create(shen)    console.log(shen)    console.log('-----');    console.log(shen2.__proto__);​​// JSON.string('zhi') 他的值中对象若要有一个, toJSON() 函数的话,那么他将不会被转换成字符串 let person = {     name: '我的',     toJSON(){        return 'XXXXX不能对改变量进行转换'     } } JSON.string('变量') 

防抖

  1. JSON.parse // 转换成js对象
  2. JSON.stringify // 转换成JSON格式
防抖: 如果事件被频繁的触发, 防抖能保证只有最后一次才能触发生效! 前面的 N 多次都会被忽略​节流: 如果事件被频繁的触发, 节流能够减少事件触发的频率, 因此, 节流是有选择性的执行一部分事件!
 watch: {    input: {      immediate: true, deep: true,      handler(newVal) {        if (this.time) {          clearTimeout(this.time) // 清除定时器        }        this.time = setTimeout(() => {          this.changeBlian(newVal)        }, 1000)      }    }  },/** 输入框发生变化 */      changeBlian(e) {          console.log(e)      },​
// 防抖​var timer = null  // 防抖动的 timer​function debounceSeaarch(keywords){ // 定义防抖的函数    timer = setTimeout(() =>{        getSuggestList(keywords)    }, 500)}​$('#ipt').on('keyup', function(){  // 在触发 keyup 实践时, 立即清空 timer    clearTimeout(timer)    debounceSeaarch(keywords)})
// 使用节流优化鼠标跟随效果$(function () {    var angel = $('#angel')    var timer = null // 预定义一个 timer 节流阀    $(documone).on('mousemove', function(e){        if(timer) {return} // 判断节流阀是否为空, 如果不为空, 则证明距离上次执行事件不够, 把他清除掉        timer = setTimeout(function () {            $(angel).css('left', e.pageX + 'px').css('top', e.pageY + 'px')            timer = null // 设置了鼠标跟随效果后, 清空timer 节流阀, 方便下次继续开启        }, 16)    })})

闭包

//js是个单线程语言, 他会先执行全局作用域之后,在执行各个局部作用域的代码片段。一个作用域引用另一个作用域中的变量, 我用到的,闭包的语法主要是,()()

原型

每一个函数类型的数据,都有一个叫做prototype的属性,这个属性指向的是一个对象,就是所谓的原型对象

而原型对象有个 prototype.constructor 属性来指向构造函数

原型链

每一个实例对象又有一个 proto 属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有proto属性,这样一层一层往上找就形成了原型链。

普通函数和箭头函数

// 箭头函数他是匿名的,用完就废弃了。所以他不需要构造函数的原型了,箭头函数的 this 指向为父级作用域的this ,因为没有自己的this,所以没法通过bind、call、apply来改变this指向​// 普通函数的 this 指向  是谁调用函数,就指向谁。如果没调用,就默认指向window。在vue中可能指向 vue 的实例。

JS基础

操作数组

字符串

使用slice()函数 // 删除字符串, 不改变原数组​slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。​使用 start(包含) 和 end(不包含) 参数来指定字符串提取的部分。​start 参数字符串中第一个字符位置为 0, 第二个字符位置为 1, 以此类推,如果是负数表示从尾部截取多少个字符串,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。​end 参数如果为负数,-1 指字符串的最后一个字符的位置,-2 指倒数第二个字符,以此类推。var str="ab12345";  // 改变原数组    str.slice()// 复制一个数组    str.slice(1,2) // 截取数组    str.slice(-1, '数组的长度') // 截取最后几个内容console.log(str.slice(2))   //   =>  12345
    字符串.split(',') // 将字符串转换成数组    // 在字符串中有个迭代器是 Symbol.iterator(), 他可以使字符串像数组解构一样解开字符串    [...字符串]        const { length } = '123456' // lenght 会打印字符串的长度​    Number.isInteger(1.00) //  判断是否为整数​    字符串.chat(2) // 返回下标为2的字符​    Math.sign(x),负数返回-1,正数返回1​    1. string.search() // 返回当前下标    {        let searchVal = 'yyds'        let searchResult = searchVal.search('y')        console.log(searchResult) // 0     }​    string.includes() // 返回一个布尔值    {     let searchVal = 'yyds'     let searchResult = searchVal.includes('y', 1)     console.log(searchResult) // true    }​    字符串.replace('a', 'b') // 第一个值的原字符,第二个为a换成b 。 字符串    ​    字符串.padStart(2,0) //  前面补    字符串.padEnd(2,0) // 后面补        字符串.toUpperlase() // 字符串全部大写        字符串.toLowerlase() // 字符串全部小写            'x'.repeat(3)   // 将x这个字符串重复三次​    'sss'.startsWith('s') // 以 s 开头​    'sss'.endsWith('s') // 以 s 开头​    const res = Date.parse(new Date()) + '' // 将日期转换成时间戳    new Date().getTime()​    console.log(res);    let ress = res.substring(0, res.length - 3);  // 获取后三位之前的内容     console.log(ress);​    const shijian = new Date().toLocaleDateString() + " "+ new Date().toLocaleTimeString('chinese', { hour12: false }) // 获取时间          console.log(shijian); // '2022/9/25 16:37:38'        Number(new Date()) // 将日期转换成毫秒数

数组

    arr.push() // 添加数组,也可返回数组的长度        arr.unshift() // 在数组第一个值前添加        arr.pop() // 删除数组最后一个值, 并返回该元素        arr.shift() // 删除数组第一个值,并返回该元素        arr.reverse() // 翻转数组        arr.indexOf('') // 括号中的值为数组的值,可以得到索引,返回第一个符合条件的值        // arr.indexOf('查找的值')        arr.slice()// 复制一个数组,, 不改变原数组    arr.slice(1,2) // 截取数组    arr.slice(-1, '数组的长度') // 截取最后几个内容​    arr.concat() // 合并多个数组, 不改变原数组​    arr.join('') // 将数组转换成字符串, 括号里的为用什么隔开​    arr.splice(2,1)  // 将数组索引从第二个删,删除一个(索引删除数组的值)    arr.splice(1, 1, 'a', 'b') // 在数组删除第一个值并且插入俩个元素 、 a 和 b    arr.splice(1, 0, 'a', 'b') // 在数组第一个值插入俩个元素 、 a 和 b        arr.forEach(function(value, index, array) {       //参数一是:数组元素       //参数二是:数组元素的索引       //参数三是:当前的数组        })     //相当于数组遍历的 for循环 没有返回值​    
let a = arr.reduce( (sum, value) => {        return sum += value }, 0) // 累积数组的和, 返回一个数字    let a =  arr.every(value =>{        return 判断条件  }) // 找到数组中不符合条件的返回 false, 返回一个布尔值    ​arr.sort(function (a, b) {  // 冒泡排序        return a-b // 降序            b - a // 升序}) ​ const bands = ['The Plot in You', 'The Devil Wears Prada', 'Pierce the Veil', 'Norma Jean', 'The Bled', 'Say Anything', 'The Midway State', 'We Came as Romans', 'Counterparts', 'Oh, Sleeper', 'A Skylit Drive', 'Anywhere But Here', 'An Old Dog'];​    const sortedBands = bands.sort((a, b) => {      if (b > a) {  // 字符z-a 排序        return 1      } else { // 字符 a - b 排序        return -1      }    });    console.log(sortedBands);​​

判断数组有无该元素

arr.includes()    [1,2].includes(2) // 数组包不包含2    判断数组是否包含某个值,返回 true / false    参数1,必须,表示查找的内容    参数2,可选,表示开始查找的位置,0表示开头的位置                [a,d,v].findIndex((value) => value > 9) // 找到第一个符合条件的, 返回下标,返回一个新的值,从0开始查找    arr.findIndex(实参 =>表达式) 这个是遍历数组中的对象,可以把数组里的每一个元素遍历​     * indexOf :查找值作为第一个参数,采用 === 比较,更多的是用于查找基本类型,如果是对象类型,则是判断是否是同一个对象的引用​    * findIndex :比较函数作为第一个参数,多用于非基本类型(例如对象)的数组索引查找,或查找条件很复杂,遍历数组中的每个元素            //  some 查找数组中是否有满足条件的元素  var arr = [10, 30, 4]; var flag = arr.some(function(value,index,array) {    //参数一是:数组元素     //参数二是:数组元素的索引     //参数三是:当前的数组     return value < 3;  });console.log(flag);//false返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环​数组方法 find 过滤数组   var newArr = arr.find(function(value, index, array) {     //参数一是:数组元素     //参数二是:数组元素的索引     //参数三是:当前的数组     return value >= 20;  });  console.log(newArr);//[66] //找到第一个符合条件的,就返回改判断条件​  数组方法filter过滤数组   var newArr = arr.filter(function(value, index,array) {     //参数一是:数组元素     //参数二是:数组元素的索引     //参数三是:当前的数组     return value >= 20;  });  console.log(newArr);//[66,88] //返回值是一个新数组
数组查重var ter = ["科幻", "娱乐", "奇闻"]    var xin = []for (var i = 0; i < 500; i++) {      if (xin.indexOf(ter[i]) === -1) {        xin.push(ter[i]);      }  }​...new Set()​ const res = this.array        const aaaa = res.unshift(11112)        const p = [...new Set(res)]        this.array = p​// 数组中的用迭代器返回来了 3 个检索内容元素的方法 Array.from(数组.keys()) // 数组索引值Array.from(数组.vlaues()) // 数组本身Array.from(数组.entries()) // [[数组下标, 数组值]]

代码

// findIndex 比 indexof 高级, 可以自己去比较过程// 语法:// 数组对象.findIndex( (值变量名) => { return 判断条件 })// 返回值: 找到符合条件,当前值对应索引返回在原地// 执行过程(很多数组高级方法都是如此) : 对每个遍历的值, 传入函数体执行​let result = list.findIndex( (obj) =>{ // 返回第一个找到的下标    return obj.id === 101})​log(result)

Math

Math.max() // 最大值Math.min() // 最小值Math.ceil() // 向上佘入最接近的值、Math.floor() // 向下佘入Math.round() // 四舍五入‘Math.abs()  // z返回绝对值

时间

时间 --- 时间戳相互转换

var timestamp = Date.parse(new Date()); // 省略后三位var timestamp=new Date().getTime();// 返回精确毫秒​​//js中的日期时间函数var date = new Date();date.getYear();        //获取年份(2位)date.getFullYear();    //获取完整的年份(4位,1970-)date.getMonth();       //获取月份(0-11,0代表1月)date.getDate();        //获取日(1-31)date.getDay();         //获取星期?(0-6,0代表星期天)date.getTime();        //获取时间(从1970.1.1开始的毫秒数)date.getHours();       //获取小时数(0-23)date.getMinutes();     //获取分钟数(0-59)date.getSeconds();     //获取秒数(0-59)date.getMilliseconds();    //获取毫秒数(0-999)date.toLocaleDateString();     //获取日期date.toLocaleTimeString();     //获取时间date.toLocaleString();        //获取日期与时间​//数字时间戳转换成日期时间函数,time为传入的数字时间戳,如果数字时间戳先前作了/1000运算,请先*1000再传入function changeTimeFormat(time) {    var date = new Date(time);    var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;    var currentDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();    var hh = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();    var mm = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();    return date.getFullYear() + "-" + month + "-" + currentDate+" "+hh + ":" + mm;    //返回格式:yyyy-MM-dd hh:mm}
​// 聊天时间export const timeChange = timeValue => {          timeValue = new Date(timeValue).getTime()          var timeNew = new Date().getTime() // 当前时间          // console.log('传入的时间', timeValue, timeNew)          var timeDiffer = timeNew - timeValue // 与当前时间误差          // console.log('时间差', timeDiffer)          var returnTime = ''          if (timeDiffer <= 60000) { // 一分钟内            returnTime = '刚刚'          } else if (timeDiffer > 60000 && timeDiffer < 3600000) { // 1小时内            returnTime = Math.floor(timeDiffer / 60000) + '分钟前'          } else if (timeDiffer >= 3600000 && timeDiffer < 86400000 && isYestday(timeValue) === false) { // 今日            returnTime = formatTime(timeValue).substr(11, 5)          } else if (timeDiffer > 3600000 && isYestday(timeValue) === true) { // 昨天            returnTime = '昨天' + formatTime(timeValue).substr(11, 5)          } else if (timeDiffer > 86400000 && isYestday(timeValue) === false && isYear(timeValue) === true) { // 今年            returnTime = formatTime(timeValue).substr(5, 11)          } else if (timeDiffer > 86400000 && isYestday(timeValue) === false && isYear(timeValue) === false) { // 不属于今年            returnTime = formatTime(timeValue).substr(0, 16)          }          return returnTime        }            function isYestday (timeValue) { // 是否为昨天                  const date = new Date(timeValue)                  const today = new Date()                  if (date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth()) {                    if (date.getDate() - today.getDate() === 1) {                      return true                    } else {                      return false                    }                  } else {                    return false                  }                }                        function isYear (timeValue) { // 是否为今年                          const dateyear = new Date(timeValue).getFullYear()                          const toyear = new Date().getFullYear()                          // console.log(dateyear, toyear)                          if (dateyear === toyear) {                            return true                          } else {                            return false                          }                        }                            // 函数:formatTime  格式化时间 返回时间字符串如   2018-07-06 11:11:37                                                            function formatTime (date) {                                 var t = getTimeArray(date)                                  return [t[0], t[1], t[2]].map(formatNumber).join('-') + ' ' + [t[3], t[4], t[5]].map(formatNumber).join(':')                                }                                                               function getTimeArray (date) {                                 date = new Date(date)                                 var year = date.getFullYear()                                 var month = date.getMonth() + 1                                 var day = date.getDate()                                 var hour = date.getHours()                                 var minute = date.getMinutes()                                 var second = date.getSeconds()                                 return [year, month, day, hour, minute, second].map(formatNumber)                               }                                                              // 转化日期 如2018-7-6 -->(2018-07-06)                               function formatNumber (n) {                                 n = n.toString()                                 return n[1] ? n : '0' + n                               }​

迭代器和生成器

迭代器

在软件开发领域, 迭代是按照一定的顺序反复和多次的执行一段代码。通常有明确的终止条件。

实际上就是循环

迭代器 ,是某一种机制,迭代器对象可以通过 for..of 遍历和 [...arr] 展开运算符。还可以通过展开运算符的每一项

迭代器是按需创建的一次性对象,每个迭代器都会关联一个迭代器对象,然而迭代器会暴漏迭代器关联的API 接口。---可迭代接口(Interable) , 迭代器接口(Interator)    字符串、 数组、 映射、 集合、 arguments对象、 NodeList等DOM 集合类型    'a', [1,2], Map()、Set()、 DOM    log(值[Symbol.interator]()) // 调用这些工厂函数会生成一个迭代器​迭代器是一种一次性的对象, 用于迭代与其可关联的迭代对象。迭代器成功时都会返回一个next() 方法。next() 中会返回俩个属性: done(有值返回false, 没有返回true) 和 value(返回下一个的值)    let a = [1,2,3,4]    const item = a[Symbol.iterator]()​    console.log(item.next()); // {value: 1, done: false}    console.log(item.next()); // {value: 2, done: false}    console.log(item.next()); // {value: 3, done: false}    console.log(item.next()); // {value: 4, done: false}    console.log(item.next()); // {value: underfind, done: true} --- 此时数组有4个值,第五次调用没有就返回underfind这事​// 自己生成一个迭代器let obj = {    values: [1, 2, 3, 4, 5],    [Symbol.iterator]() {        let index = -1        return {            next: function () {                return index === this.values.length - 1                    ? { value: 'underfined', done: true }                : { value: this.values[++index], done: false }            }.bind(this)        }    }}

生成器

生成器的形式是一个函数, 函数名称前面加一个(*) 表示是一个生成器。只要可以定义函数的地方就可以定义生成器。

生成器函数会返回一个遍历器对象,可以返回多个值

箭头函数不可以定义生成器

每个生成器在调用执行时候, 不会相互影响

// 生成器内部有一个关键字 yield 表达式,定义不同的内部状态(yield 在英语里的意思是产出)// 下面代码定义了一个 hellWordGenerator() 的生成器, 它的内部有俩个 yield 表达式(hello 和 word), 即该函数有三个状态: hello, word 和 return 语句(结束语句)function* hellWordGenerator() {    yield 'hello';    yield 'word';    return 'ending'; // 他会代表最后一个执行的,返回{value: ending done: true}}let hw = hellWordGenerator() log(hw) // 他本身不会打印任何东西 // next() 的形参传入的值代表着 yield 返回的值log(hw.next()) // 生成器执行log(hw.next()) // 生成器执行log(hw.next()) // 生成器执行// 调用生成器函数, 返回迭代器对象, 生成器本身没有执行函数
function* hellWordGenerator() { // yield 本身并不会返回值  let a = yield x + 1;  let b = yield a + 1;  let c = yield b + 1;  return c}let hw = hellWordGenerator(1) // next() 的形参传入的值代表着 yield 返回的值log(hw.next(1)) // 生成器执行log(hw.next(2)) // 生成器执行log(hw.next(3)) // 生成器执行// 调用生成器函数, 返回迭代器对象, 生成器本身没有执行函数// 生成器也可以处理异步的, 在async 和 await 没有发布之前是用生成器,执行到 yield 时候等待function* gen(){    let res1 = yield ajx('地址')    log(res1)    let res2 = yield ajx('地址2')    log(res2)}// 调用生成器co(gen) // 这里传入的是整个 gen生成器function co(gen){    let generator = gen()        // result 是next 返回的结果 {done: '', value: ''}    function next(result) {  // 这里是个递归        if(result.done) return        result.value.then(v =>{            next(generator.next(v)) // 调用 next() 会返回给 res1        })    }    next(generator.next()) // 第一次调用生成器, 注意第一次使用 next() 函数不会被赋值}// 如果你的 yield 的输出是一个数组,那么你的 yield 后面加个 * 就可以遍历出来, 不加的话就原样返回function* shenhcgeng(initial) {    yield* [1, 2, 3, 4]    yield* [21, 22, 32, 24]}for (let i of shenhcgeng()) {    console.log(i);}

Class 类

类抽象了对象的公共部分。 它泛指某一个大类 Calss

class Star { // 创建了一个 class 类    constructor(unmae){ // 这个函数是类的构造函数调用后,立刻执行的        this.unmae = unmae // this 指向创造的实例 ,下方实例指向 ldh    }    sing(song){        log('我的唱歌' + song)    }}let ldh = new Star('我的') log(ldh.uname) // 打印了-- 我的log(ldh.sing('李香兰')) // 打印了 sing() 里面的代码

类的继承

class Father { // 创建了一个 class 类    constructor(x, y){     }    som(){        log(this.x + this.y)    }    money(song){        log('我的唱歌' + song)    }}​class Son extenbds Father{ // 儿子继承了父亲的类, extends 代表继承    constructor(x, y){         super(x, y) // 这个关键字代表调用了父亲的构造函数                // 注意 super 必须是在 this 之前        this.x = x         this.y = y    }}let ldh = new Son(1, 2) ldh.money() // 上面讲了继承, 就代表 Son 可以使用 Father 里的所有属性和方法ldh.som() // 因为 som 的值是根据父元素的初始化而改变的, 所以子要使用 super 关键字
​// 类的表达式的名称是可选的,把类表达式赋值给变量后, 可以通过 name 属性取得类表达式的名称字符串。但不能在类表达式作用域外部访问这个标识符let Person = class PersonName {    identify() {        log(Person.name, PersonName.name)    }}​let p = new Person()​p.identify() // PersonName PersonNamelog(person.name) // PersonNamelog(PersonName) // PersonName is underfind

1.1循环

if()if () {} else if (){}switch(表达式){      case 值1:       语句体:       break;}for () { }while () {}do {    // 循环体代码 - 条件表达式为 true 时重复执行循环体代码} while(条件表达式); continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)。break 关键字用于立即跳出整个循环(循环结束)。

3.函数

3.1函数有哪些

function 构造函数名(形参1,形参2,形参3) {     this.属性名1 = 参数1;     this.属性名2 = 参数2;     this.属性名3 = 参数3;     this.方法名 = 函数体;}var obj = new 构造函数名(实参1,实参2,实参3)

函数的调用

/* 1. 普通函数 */function fn() {	console.log('人生的巅峰');} fn(); /* 2. 对象的方法 */var o = {  sayHi: function() {  	console.log('人生的巅峰');  }}o.sayHi();/* 3. 构造函数*/function Star() {};new Star();/* 4. 绑定事件函数*/ btn.onclick = function() {};   // 点击了按钮就可以调用这个函数/* 5. 定时器函数*/setInterval(function() {}, 1000);  这个函数是定时器自动1秒钟调用一次/* 6. 立即执行函数(自调用函数)*/(function() {	console.log('人生的巅峰');})();

函数内部的this指向

改变函数内部 this 指向

call方法    方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的 this 指向    fn.call(o,1,2)//此时的this指向的是对象o,参数使用逗号隔开,运行结果为3​ apply方法     方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。    fn.apply(o,[1,2])//此时的this指向的是对象o,参数使用数组传递 运行结果为3  bind()    方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数    var f = fn.bind(o, 1, 2); //此处的f是bind返回的新函数    f();//调用新函数  this指向的是对象o 参数使用逗号隔开   

4.2 遍历对象

for (变量 in 对象名字) {    // 在此执行代码}for (var k in obj) {    console.log(k);      // 这里的 k 是属性名    console.log(obj[k]); // 这里的 obj[k] 是属性值}

获取对象的属性名/值

Object.keys(obj) // 名​Object.values(obj) // 值

5.2 复杂数据类型和基本数据类型在内存中的存储

堆 存放复杂数据类型:数组,对象,data时间 栈 存放简单数据类型:布尔值,Number,null,string,underfind

let var const 区别

let 和 const 是块级作用域也就是说,最近的一个花括号,包裹的内容不会被外部所发现const 定义的值不会被更改而,但对象可以 , 可以使用 Object.freeze({}) 来操作。​var 是函数级别的用户域。var会被挂载到window的实例上。存在变量提升

Web APIs

var el = document.querySelector('#demo');  el.style.setProperty('background-color', '#f00', 'important');
 document.addEventListener('keyup', function(e) {  
 // console.log(e);     console.log('up:' + e.keyCode);     // 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键     if (e.keyCode === 65) {         alert('您按下的a键');     } else {         alert('您没有按下a键')     } })

innerHTML 和 innerText 的区别是一个操作,html元素一个是,文本

img.className = 'a' 将 img 标签增加 a 这个class 类名

document.body.style.backgroundImage = 'url(' + this.src + ')';

添加类名

// 点击事件​let ls = document.getElementById('ldh')ldh.onclick = function(){   ls.style.width = '500px'    text.className = 'sadsa' // 修改class 类名    添加一个类名    获取元素名.classList.add("类名");    添加多个类名用逗号隔开    获取元素名.classList..add("类名1","类名2","类名3",...); 每个类名需要用引号引起来    移除一个类名    获取元素名.classList.remove("类名");    移除多个类名    获取元素名.classList.remove("类名1","类名2","类名3",...); 每个类名需要用引号引起来     //添加和删除类名    this.classList.toggle('open');}

排他思想

给五个元素绑定一个事件

<html>    <p></p>    <p></p></html><script>    let btns = document.ge..('p')    for(let i = 0; i < btns.lenght; i++){       btns.onclick = function() {            this.style.color = 'pink' //当前元素颜色添加            for(let y = 0; y < ; y++){                btns[i].style.color = ''            }       }    }</script>

1.1. 自定义属性操作

用这个方法, 以下的了解OK

div.dataset.index = 'om'.// 设置自定义属性div.dataset.index|| div.dataset[index] // 打印了自定义的index 属性俩个横岗用驼峰命名法div.setAttribute('data-time', 20) // 设置了一个自定义属性为20 console.log(div.getAttribute('data-p')); // 获取了自定义属性// class 不是className// 3 移除属性 removeAttribute(属性)    div.removeAttribute('index')
<div id="demo" index="1" class="nav"></div><script>    var div = document.querySelector('div');    // 1. 获取元素的属性值    // (1) element.属性    console.log(div.id);    //(2) element.getAttribute('属性')  get得到获取 attribute 属性的意思 我们程序员自己添加的属性我们称为自定义属性 index    console.log(div.getAttribute('id'));    console.log(div.getAttribute('index'));</script>

1.2. 设置属性值

element.属性 // 获取内置属性值element.setAttribute('属性', '值')​区别:​element.属性 // 获取内置属性值(元素本身自带的属性)element.getAttribute('属性') // 主要设置自定义的属性(标准) 
  // 2. 设置元素属性值        // (1) element.属性= '值'        div.id = 'test';        div.className = 'navs';        // (2) element.setAttribute('属性', '值');  主要针对于自定义属性        div.setAttribute('index', 2);        div.setAttribute('class', 'footer'); // class 特殊  这里面写的就是

主要用下面的方法

div.dataset.index = 'om'.// 设置自定义属性div.dataset.index|| div.dataset[index] // 打印了自定义的index 属性俩个横岗用驼峰命名法div.setAttribute('data-time', 20) // 设置了一个自定义属性为20 console.log(div.getAttribute('data-p')); // 获取了自定义属性// class 不是className// 3 移除属性 removeAttribute(属性)    div.removeAttribute('index');

1.3节点操作

while (ul.children.length) { // 删除父元素中的所有子元素    ul.removeChild(ul.firstElementChild) }
  // 1. 创建节点元素节点        var li = document.createElement('li');        // 2. 添加节点 node.appendChild(child)  node 父级  child 是子级 后面追加元素  类似于数组中的push        var ul = document.querySelector('ul');        ul.appendChild(li);        // 3. 添加节点 node.insertBefore(child, 指定元素);        var lili = document.createElement('li');        ul.insertBefore(lili, ul.children[0]);        // 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素1​    // 父元素最后一个子节点   .lastElementChild , 父.children[children.length - 1]    // 父元素第一个子节点    .firstElementChild , 父.children[0]    // 查找父节点    子.parentNode // 上一级父节点亲爸爸的    //下一个兄弟节点   .nextElementSibling    // 上一个兄弟节点  .previousElementSibling     // 删除子节点    node.removeChild(child)

创建节点

. 添加节点

node.appendChild(child) // 方法是将一个节点添加到指定节点的子节点的末尾, 类似于 css 的 after 伪元素​node.insertBefo(child) // 方法是将一个节点添加到指定节点的子节点的前面, 类似于 css 的 before 伪元素
    // 1. 创建节点元素节点        var li = document.createElement('li');        // 2. 添加节点 node.appendChild(child)  node 父级  child 是子级 后面追加元素  类似于数组中的push        var ul = document.querySelector('ul');        ul.appendChild(li);        // 3. 添加节点 node.insertBefore(child, 指定元素);        var lili = document.createElement('li');        ul.insertBefore(lili, ul.children[0]);        // 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素1

删除节点

node.removeChild(child)//ul.removeChild(ul.children[0]);

node.removeChild() 方法从 node节点中删除一个子节点,返回删除的节点。

复制(克隆)节点

node.cloneNode()// var lili = ul.children[0].cloneNode(true); ul.appendChild(lili);

BOM

获取元素的宽度高度

const linkCoords = this.getBoundingClientRect(); rectObject.top:// 元素上边到视窗上边的距离;rectObject.bottom:// 元素下边到视窗上边的距离;rectObject.right:// 元素右边到视窗左边的距离; rectObject.left:// 元素左边到视窗左边的距离;rectObject.width:// 是元素自身的宽度rectObject.height: // 是元素自身的高度 const coords = {        width: linkCoords.width, // 返回元素的宽度        height: linkCoords.height, // 返回元素的高度        top: linkCoords.top + window.scrollY, //  返回元素距离浏览器左侧的位置        left: linkCoords.left + window.scrollX//  返回元素距离浏览器顶部的位置      };
    // 获取 元素距离浏览器的位置     function getElementTop(el) {      if (el.offsetParent) {        return this.getElementTop(el.offsetParent) + el.offsetTop      }      return el.offsetTop    }    const res = getElementTop(sadsa)    console.log(res);

Loaction 对象

location.host // 拿到主机名和端口 ​location.href // 拿到整个的地址location.pathname//     返回的URL路径名。​
    <div id="box"></div>var object=document.getElementById('box');  rectObject = object.getBoundingClientRect();     rectObject.top:元素上边到视窗上边的距离;    rectObject.right:元素右边到视窗左边的距离;    rectObject.bottom:元素下边到视窗上边的距离;    rectObject.left:元素左边到视窗左边的距离;    rectObject.width:是元素自身的宽    rectObject.height是元素自身的高

js 的click

const divs = document.querySelectorAll('div')function log(e){  // e.stopPropagation();  // console.log(this);  console.log(e.target);}divs.forEach(item => item.addEventListener('click', log,{    capture: false, // true 的话是由外向里,捕获阶段, false 是磨人的由内向外    once: true// 被调用的次数,只会被触发一次  }))

事件对象的属性和方法

e.target 和 this 的区别

  • e.target 是事件触发的元素。
  • this 是事件绑定的元素(绑定这个事件处理函数的元素) 。
但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),    这时候this指向的是父元素,因为它是绑定事件的元素对象,    而target指向的是子元素,因为他是触发事件的那个具体元素对象。

事件委托

说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。

给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。

常用鼠标事件

  // 鼠标事件对象 MouseEvent        document.addEventListener('click', function(e) {            // 1. client 鼠标在可视区的x和y坐标            console.log(e.clientX);            console.log(e.clientY);            console.log('---------------------');​            // 2. page 鼠标在页面文档的x和y坐标            console.log(e.pageX);            console.log(e.pageY);            console.log('---------------------');​            // 3. screen 鼠标在电脑屏幕的x和y坐标            console.log(e.screenX);            console.log(e.screenY);​        })

调整窗口大小事件

计时器(两种)

window 对象给我们提供了 2 个非常好用的方法-定时器。

  • setTimeout() 几秒后执行
  • setInterval() 持续

同步任务和异步任务

同步

前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。

异步

你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

Cookie

一般是由服务器生成,可设置失效时间。如果在浏览器生成,则默认为浏览器关闭后失效。

本地存储

sessionStorage约5M、

存储数据:sessionStorage.setItem(key, value)获取数据: sessionStorage.getItem(key)删除数据: sessionStorage.removeItem(key)清空数据:(所有都清除掉):sessionStorage.clear()

localStorage约20M

存储数据:localStorage.setItem(key, value)获取数据: localStorage.getItem(key)删除数据: localStorage.removeItem(key)清空数据:(所有都清除掉): localStorage.clear()

location

location.assgin('地址') // 跳转页面,能后腿location.replace('地址') // 跳转页面,不能后腿

重新加载(刷新)

location.reload() // 刷新,加上ture强制刷新

navigator

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {    window.location.href = "";     //手机 } else {    window.location.href = "";     //电脑}

history

    navigator.go(1,-1) // 1 为前进, -1 后腿    history.back() 后退    history.forward() 前进

window

可视化区域 ​ 滚动距离 ​ scroll // 滚动事件 ​ 本身.scrollWidth //全部文字宽度,包括超出的 ​ 本身.scrollHeight // 全部文字高度,包括超出的 ​ 本身.scrollTop // 文字超出的高度 ​ 盒子加上overflow:auto,加上滚动条 ​ 不带边框,内容超出盒子 = 盒子大小+超出内容 ​ 页面被减去的头部 ​ window.pageYoffset

JS高级

创建类

  1. 语法:
//步骤1 使用class关键字class name {  // class body}     // 1. 创建类 class  创建一个类class Star {    // 类的共有属性放到 constructor 里面 constructor是 构造器或者构造函数    constructor(uname, age) {      this.uname = uname;      this.age = age;    }//------------------------------------------->注意,方法与方法之间不需要添加逗号    sing(song) {      console.log(this.uname + '唱' + song);    }}// 2. 利用类创建对象 newvar ldh = new Star('刘德华', 18);console.log(ldh); // Star {uname: "刘德华", age: 18}ldh.sing('冰雨'); // 刘德华唱冰雨

类的继承

  1. 语法
// 父类class Father{   } // 子类继承父类class  Son  extends Father {  }       class Father {      constructor(surname) {        this.surname= surname;      }      say() {        console.log('你的姓是' + this.surname);       }}class Son extends Father{  // 这样子类就继承了父类的属性和方法}var damao= new Son('刘');damao.say();      //结果为 你的姓是刘

原型

每一个函数类型的数据,都有一个叫做prototype的属性,这个属性指向的是一个对象,就是所谓的原型对象

而原型对象有个 prototype.constructor 属性来指向构造函数

原型链

每一个实例对象又有一个 proto 属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有proto属性,这样一层一层往上找就形成了原型链。

严格模式

'use strict'num = 10 console.log(num)//严格模式后使用未声明的变量--------------------------------------------------------------------------------var num2 = 1;delete num2;//严格模式不允许删除变量--------------------------------------------------------------------------------function fn() { console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined}fn();  ---------------------------------------------------------------------------------function Star() {	 this.sex = '男';}// Star();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.var ldh = new Star();console.log(ldh.sex);----------------------------------------------------------------------------------setTimeout(function() {  console.log(this); //严格模式下,定时器 this 还是指向 window}, 2000);  xxxxxxxxxx 'use strict'num = 10 console.log(num)//严格模式后使用未声明的变量--------------------------------------------------------------------------------var num2 = 1;delete num2;//严格模式不允许删除变量--------------------------------------------------------------------------------function fn() { console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined}fn();  ---------------------------------------------------------------------------------function Star() {     this.sex = '男';}// Star();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.var ldh = new Star();console.log(ldh.sex);----------------------------------------------------------------------------------setTimeout(function() {  console.log(this); //严格模式下,定时器 this 还是指向 window}, 2000);  

解构赋值(★★★)

ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构

数组解构let [a, b, c] = [1, 2, 3]; console.log(a)//1 console.log(b)//2 console.log(c)//3//如果解构不成功,变量的值为undefined
对象解构let person = { name: 'zhangsan', age: 20 };  let { name, age } = person; console.log(name); // 'zhangsan'  console.log(age); // 20 let {name: myName, age: myAge} = person; // myName myAge 属于别名 console.log(myName); // 'zhangsan'  console.log(myAge); // 20

伪数组

//转成数组Array.from(数组)

AJAX

$.ajax({          type: 'GET/post',          url: '地址',          data: {            数据          },          success: function (res) {            console.log(res)          }        })

模板引擎

中文官首页:http://aui.github.io/art-template/zh-cn/index.html

如何解决跨域

JSONP(JQ)只支持get不支持post

      $.ajax({            url: '地址',            // 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp            dataType: 'jsonp',            success: function (res) {                console.log(res)            }        })

git

git init - 初始化仓库。git add 文件名   ===添加到暂存区git add .   ===全部添加到暂存区git status   === 查看文件状态(修改文件)git checkout   文件名  === 恢复到原来文件  暂存区覆盖源文件git rm --cached  文件名 === 将文件从暂存中删除git commit -m "提交消息"  === 提交到库 git log  === 获取提交信息git rest --hard commitIDgit rm --cached 文件名  === 删除分支git branch  === 查看分支git branch  分支名 ===创建分支命令git checkout 文件名 ===切换分支命令$ git branch -d  分支名 ===  删除分支rankgit merge 分支名 === 合并分支   (创建分支 创建分支文件 切换分支工作区 添加到暂存区 提交到库  切换主分区  合并)git branch -d 分支名  ===删除合并分支git branch -D 分支名  === 强制删除分支git stash  ===储存临时改动git clone(git push http://github.com/xx/ooo)  远程地址 === 克隆远程数据git clone -b <分支名> <远程仓库地址>git pull  远程地址  分支名称   === 拉去远程仓库最新版本git push -u 地址 分之名称   // 此方法是记住提交的地址, 下次直接git push 即可 第一次提交: git push 远程地址(https://github.com/QuanGHub/git-deom.git) ==远程提交数据   (提交暂停区  提交库  远程提交数据 git push) 第二次提交git remote add 别名 远程仓库地址=》更改文件内容 =>提交到暂存区=>提交到库=>git push 别名 master第三次提交 git push -u 别名 master第四次提交 git pushcd-文件夹名字  === 切换到该文件夹master
// 拉去远程仓库所有分之git clone http://myrepo.xxx.com/project/.git ,这样在git_work目录下得到一个project子目录git branch -a //,列出所有分支名称如下:remotes/origin/devremotes/origin/releasegit checkout -b 分支名 origin/分支名 //,作用是checkout远程的dev分支,在本地起名为dev分支,并切换到本地的dev分支git checkout -b release origin/release //,作用参见上

分支合并

将本地的 tabbar 分支进行本地的 commit 提交:git add .git commit -m "完成了 tabBar 的开发"将本地的 tabbar 分支推送到远程仓库进行保存:git push -u origin tabbar将本地的 tabbar 分支合并到本地的 master 分支:git checkout mastergit merge tabbar删除本地的 tabbar 分支:git branch -d tabbar

pull 和 clone 的区别, pull 是拉去最新的代码, clone 是本地没有代码,全部拉去

// 执行操作, 多人协作开发流程git init - 初始化仓库。git add 文件名   ===添加到暂存区git add .   ===全部添加到暂存区git status   === 查看文件状态git commit -m '提交信息' === 向仓库提交代码git push 地址 分支 === 推送分支 git clone 地址 === 克隆仓库中的代码// 修改后, 提交到仓库中的代码// B若修改了代码, A在拉去最新的代码git pull 地址 分支名称// 发生冲突后解决办法

ssh 免密登陆

第一步: 在终端输入 ssh-keygen , 一路回车然后, 在系统盘下的用户文件下的 .ssh 文件夹下,下有 id_rsa 和 id_rsa.pub 俩个文件。将 id_rsa.pub 放入gitee的 ssh中

ES6模块化语法

概念

问题1: 什么是ES6?

答案: ECMAScript2015 (2015年指定的js标准)-语法标准, 规定了很多新的语法 (例如: let, const声明变量, 箭头函数....模块化语法)

==关键字==:

  • 导入: import
  • 导出: export (暴露给外面用, 不暴露外面用不了)
  • 每个js文件都是独立作用域的, 需要导出别人才能导入使用

nodejs体验ES6模块化

package.json中添加 type: 'module'

使用

默认导出和导入

默认导出语法: (==一次==)

export default 对象

默认导入语法:

import 变量名 from '目标js文件的路径' 

效果: 变量名的值就是导出的对象

按需导出和导入

好处: 需要什么才导入什么, 不必全都导入过来

按需导出语法: (==多次==)

export 声明变量关键字 变量名 = 值export 声明变量关键字 变量名 = 值export 声明变量关键字 变量名 = 值例:export const no = () => {    }export function getDepartment() {  }

按需导入语法:

import { export变量名一致 } from '目标js文件的路径'

注意(了解)

  1. 在导入的时候可以用as关键字重命名以后使用strA变量
  2. 可以混合使用

直接导出和导入

直接导出语法:

无导出, 直接写一些要执行的js代码

直接导入语法:

import '目标js文件路径'

Promise

概念: ES6标准时指定的一个新的对象

回调地狱: 异步任务的结果是在==回调函数==里接收, 在这里再次发起一个异步任务, 形成了回调地狱...

  • 缺点: 关联性太强, 难以维护, 可读性差
  • 解决: Promise的then的链式调用, 在外面并列的地方继续then来使用

使用

  1. 创建Promise对象实例 (包裹一个异步任务)
  2. .then() 用于等待异步任务的结果参数1: 函数体用于接收成功结果参数2: 函数体用于接收失败结果==口诀: .then()拿成功, .catch()拿失败==

进阶使用

  1. Promise.all([Promise对象, Promise对象]) - 所有顺序把多个Promise对象合并成一个大的Promise特点: 等待所有小Promise对象成功后, 触发最外面大的Promise对象.then()拿到的结果是数组, 顺序就是Promise对象顺序
  2. Promise.race([Promise对象, Promise对象]) - 赛跑把多个Promise对象合并成一个大的Promise特点: 只要有一个小的Promise对象成功后, 触发最外面大的Promise对象.then()

特点

  1. ==在Promise对象.then()里函数体中, return出来一个Promise对象, 返回在原地==promise例子
  2. JS代码里只要报错了, 你没有写代码进行错误捕获和处理, 代码就会停止往下执行
  3. 如果你不想让报错阻止代码往下走, 你需要自己捕获和处理错误

EventLoop

概念: 当JS主线程执行栈空闲时, 从任务队列里取出回调函数执行, 又空闲了, 接着再去任务队列里取出回调函数执行, 这样的一个过程就叫事件循环EventLoop

中文: 事件循环(辅助你来理解代码执行顺序)

JS是单线程的, 同一时间只能执行一行代码(一个任务)

代码/任务分类:

  • 同步任务必须等待当前代码结果
  • 异步任务不必等待当前代码结果, 直接继续向下执行计时器定时器fs读文件ajax事件绑定特点: 都是在宿主环境, 都有回调函数接收结果

宏任务和微任务(代码执行顺序)

宏任务:

  • ajax请求
  • setTimeout
  • setInterval
  • fs操作

微任务:

  • Promise.then() / Promise.catch() -> 既能在浏览器使用/nodejs环境
  • process.nextTick (nodejs环境)

Node

Web开发模式

客户端渲染(前后端分离)

渲染: 浏览器运行html文件(js代码+ajax请求回来) 动态创建DOM+数据渲染页面

前端ajax -> 请求数据

后端-> 返回只是json数据 -> 数据接口地址

优点: 开发体验好, 效率高(前端任务比较多), 减轻了服务器端压力

缺点: 不利于SEO, 解决方案( Vue->SSR技术 )

服务器端渲染

概念: 在后端把数据+DOM标签拼接生成好. 页面标签返回给前端渲染

前端 -> 请求网页

后端 -> 网页所需要的所有标签数据填充完了

优点: 前端耗时少, 有利于SEO (搜索引擎排名) -百度搜索排名

缺点: 占用服务器资源多, 不利于==前后端分离==, 效率低

==JWT(JSON Web TOKEN)==

跨域:

网页打开时所在地址栏的地址和内嵌ajax请求的地址

协议/域名/端口号 有一个对应不上 就会跨域访问

浏览器默认不支持跨域的, 但是现代浏览器已经支持跨域资源共享(前提: 后端开启cors)

Cookie缺点: 遇到跨域问题很麻烦, 所以解决方案是用jwt

工作过程

jwt字符串是保存在前端的

之前cookie是保存在服务器端内存里

组成

一大串字符串中间用.分隔开, 分为3段

Header部分

Payload(载体)部分-> 包含了用户的身份信息

Sign(签名加密)部分

使用

前端使用: 拿到Jwt字符串保存在LocalStorage/SessionStorage本地, 以后发请求的时候, 添加到请求头上, 拼接发给后台

后端使用:(了解)

  • jsonwebtoken: 后端生成jwt字符串jwt.sign(用户信息对象, 加密秘钥, 配置对象) -> 返回jwt字符串
  • express-jwt: 后端用于解析前端发来的jwt字符串, 还原成json数据对象expressJWT({secret: '解密和加密用同一个秘钥'})一定要写在其他接口的上面, 先接收先解析再使用.unless() 排除不需要验证接口的规则解密后, 把JSON数据挂载到==req.user==属性上

需要自己随便定义一个秘钥在后端 (秘钥作用: 一些列的数学算法, 把原本的明文->加密后的字符)

a -> 7 -> 加密后 abcdefg (h)

a -> 5 -> 加密后 (f)

流程

登录接口调用: 前端->调用登录接口, 传递账号密码->后端接收后判断生成jwt字符串(包含{username: '名字'} -> 返回给前端

获取用户信息接口调用: 前端要带上上一步jwt字符串在请求头里, 后端expressJwt解析, 挂载req.user, 返回给前端查看

找错

有错误提示, 先看关键信息

再看哪个是自己的文件, 多少行代码引发的错误

log的打印信息

// Regular    console.log('输入字符串');    // Interpolated    console.log('ssss%s','rive'); // %s 是第二个参数为值    // Styled    console.log('ssss%c','red'); // $c 是第二个参数是颜色和字体的变化    // warning!    console.warn('ss'); // 警告    // Error :|    console.error('Error')  // 报错的信息// Grouping together // 打印的分组    console.group();    console.log(333);    console.groupEnd();

HTTP协议

什么是通信协议

网页内容又叫超文本, 因此网页内容的传输协议又叫做超文本传输协议-----简称 HTTP 协议

由于HTTP 协议属于客户端浏览器和服务器之间的通信协议。因此,客户端发起的请求叫做HTTP 请求, 客户端发送到服务器的消息叫做 HTTP 请求消息

HTTP 请求消息由请求体,请求头部,空行和请求体4个部分组成// 请求头部请求头部用来描述客户端的基本信息, 从而把客户端的信息告知服务器例如: 	User-Agent: 用来说明当前是什么类型的浏览器    Contnet-Type: 用来描述发送到服务器的数据格式    Accept: 用来描述客户端能够接受什么类型的返回内容    Accept-Language: 用来描述客户端接收那种人类语言的文本内容
HTTP 响应消息的组成部分 ------- 就是服务器相应给服务端的内容

全部评论

相关推荐

牛客848095834号:举报了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务