Web蓝桥真题笔记 
CSS 
练习题: 
1.flex 布局 
.container:{
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;  
  justify-content:space-between;
  align-item: center;
}
.item{
 align-self: flex-end; 
}.container:{
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;  
  justify-content:space-between;
  align-item: center;
}
.item{
 align-self: flex-end; 
}2.grid布局 
- 容器
 
.grid-container{
		display: grid;
    grid-template-columns: 100px 200px auto;
  	grid-template-rows: 80px auto 80px;
}.grid-container{
		display: grid;
    grid-template-columns: 100px 200px auto;
  	grid-template-rows: 80px auto 80px;
}- 子项
 
.grid-item {
  grid-column-start: 1; 
  grid-column-end: 3; 
  grid-row-start: 1; 
  grid-row-end: 3; 
}.grid-item {
  grid-column-start: 1; 
  grid-column-end: 3; 
  grid-row-start: 1; 
  grid-row-end: 3; 
}3.媒体查询 
@media (max-width: 800px){
  
}
@media (min-width: 800px){
  
}@media (max-width: 800px){
  
}
@media (min-width: 800px){
  
}4.父子定位 
position:relative
position:absolute
需要居中
left:50%;
transform: translateX(-50%);position:relative
position:absolute
需要居中
left:50%;
transform: translateX(-50%);5.补充一些不太熟悉的css 
opacity:
transform: rotate(45deg);/translate(x, y)/scale(sx, sy)/skew(x-angle, y-angle)/matrix(a, b, c, d, e, f)
opacity:
transform: rotate(45deg);/translate(x, y)/scale(sx, sy)/skew(x-angle, y-angle)/matrix(a, b, c, d, e, f)6.清楚浏览器自带的属性 
* {
  margin:0;
  padding:0;
  box-sizing:border-box;
}* {
  margin:0;
  padding:0;
  box-sizing:border-box;
}ES6语法 
Let 
- let 声明的全局变量不是全局对象window的属性
 
这就意味着,你不可以通过 window. 变量名 的方式访问这些变量,而 var 声明的全局变量是 window 的属性,是可以通过 window. 变量名 的方式访问的。
var a = 5
console.log(window.a) // 5
let a = 5
console.log(window.a) // undefinedvar a = 5
console.log(window.a) // 5
let a = 5
console.log(window.a) // undefined- 用let定义变量不允许重复声明
 
这个很容易理解,使用 var 可以重复定义,使用 let 却不可以。
var a = 5
var a = 6
console.log(a) // 6var a = 5
var a = 6
console.log(a) // 6如果是 let ,则会报错
let a = 5
let a = 6
// VM131:1 Uncaught SyntaxError: Identifier 'a' has already been declared
//   at <anonymous>:1:1let a = 5
let a = 6
// VM131:1 Uncaught SyntaxError: Identifier 'a' has already been declared
//   at <anonymous>:1:1- let声明的变量不存在变量提升
 
function foo() {
    console.log(a)
    var a = 5
}
foo() //undefinedfunction foo() {
    console.log(a)
    var a = 5
}
foo() //undefined而对于 let 而言,变量的调用是不能先于声明的,看如下代码:
function foo() {
    console.log(a)
    let a = 5
}
foo()
// Uncaught ReferenceError: Cannot access 'a' before initializationfunction foo() {
    console.log(a)
    let a = 5
}
foo()
// Uncaught ReferenceError: Cannot access 'a' before initialization- let声明的变量具有暂时性死区
 
只要块级作用域内存在 let 命令,它所声明的变量就绑定在了这个区域,不再受外部的影响。
var a = 5
if (true) {
    a = 6
    let a
}
// Uncaught ReferenceError: Cannot access 'a' before initializationvar a = 5
if (true) {
    a = 6
    let a
}
// Uncaught ReferenceError: Cannot access 'a' before initializationES6 明确规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
- let 声明的变量拥有块级作用域
 
let实际上为 JavaScript 新增了块级作用域
{
    let a = 5
}
console.log(a) // undefined{
    let a = 5
}
console.log(a) // undefinedConst 
const 除了具有 let 的块级作用域和不会变量提升外,还有就是它定义的是常量,在用 const 定义变量后,我们就不能修改它了,对变量的修改会抛出异常。
const PI = 3.1415
console.log(PI)
PI = 5
console.log(PI)
// Uncaught TypeError: Assignment to constant variable.const PI = 3.1415
console.log(PI)
PI = 5
console.log(PI)
// Uncaught TypeError: Assignment to constant variable.Array的For.. of 
for (let val of [1, 2, 3]) {
    console.log(val);
}
// 1,2,3for (let val of [1, 2, 3]) {
    console.log(val);
}
// 1,2,3for (variable of iterable) {
}for (variable of iterable) {
}看下这个伪代码,of 后面是 iterable 既不是 for 循环规定的 array,也不是 for...in 规定的 Object,而是 iterable。如果查查 iterable 的含义就很直观的感受到 for...of 遍历的是一切可遍历的元素(数组、对象、集合)等,不要小瞧这个功能,因为在 ES6 中允许开发者自定义遍历,换句话说任何数据结构都可以自定义一个遍历,这个遍历是不能被 for、for...in 理解和实现的。
for (let item of arr) {
    console.log(item)
}
for (let item of arr.values()) {
    console.log(item)
}
for (let item of arr.keys()) {
    console.log(item)
}
for (let [index, item] of arr.entries()) {
    console.log(index, item)
}for (let item of arr) {
    console.log(item)
}
for (let item of arr.values()) {
    console.log(item)
}
for (let item of arr.keys()) {
    console.log(item)
}
for (let [index, item] of arr.entries()) {
    console.log(index, item)
}for...of是支持 break、continue、return的,所以在功能上非常贴近原生的 for。
Array.from() 
数组是开发中经常用到的数据结构,它非常好用。在 JavaScript 的世界里有些对象被理解为数组,然而缺不能使用数组的原生 API,比如函数中的 arguments、DOM中的 NodeList等。当然,还有一些可遍历的对象,看上去都像数组却不能直接使用数组的 API,因为它们是伪数组(Array-Like)。要想对这些对象使用数组的 API 就要想办法把它们转化为数组,传统的做法是这样的:
let args = [].slice.call(arguments);
let imgs = [].slice.call(document.querySelectorAll('img'));let args = [].slice.call(arguments);
let imgs = [].slice.call(document.querySelectorAll('img'));基本原理是使用 call 将数组的 api 应用在新的对象上,换句话说是利用改变函数的上下文来间接使用数组的 api。在 ES6 中提供了新的 api 来解决这个问题,就是 Array.from,代码如下:
let args = Array.from(arguments);
let imgs = Array.from(document.querySelectorAll('img'));let args = Array.from(arguments);
let imgs = Array.from(document.querySelectorAll('img'));TIP
伪数组具备两个特征,1. 按索引方式储存数据 2. 具有length属性;如:
jslet arrLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 }let arrLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 }
Array.of() 
Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个长度为7的空数组(注意:这是指一个有7个空位(empty)的数组,而不是由7个undefined组成的数组)。
Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]
Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]
Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]语法:Array.of(element0[, element1[, ...[, elementN]]])
| 参数 | 含义 | 必选 | 
|---|---|---|
| elementN | 任意个参数,将按顺序成为返回数组中的元素 | Y | 
Class 
class Animal {
    constructor(type) {
        this.type = type
    }
    walk() {
        console.log( `I am walking` )
    }
}
let dog = new Animal('dog')
let monkey = new Animal('monkey')class Animal {
    constructor(type) {
        this.type = type
    }
    walk() {
        console.log( `I am walking` )
    }
}
let dog = new Animal('dog')
let monkey = new Animal('monkey')很明显,从定义上就很专业了,有构造函数、方法,但是 ES6 增加了新的数据类型 class 吗?
console.log(typeof Animal) //functionconsole.log(typeof Animal) //functionconsole.log(dog.hasOwnProperty('type')) //trueconsole.log(dog.hasOwnProperty('type')) //true这个表现也和 ES5 中直接使用 function 定义类的方式相同,所以得出一个结论:class 的方式是 function 方式的语法糖。
Getters & Setters
class Animal {
    constructor(type, age) {
        this.type = type
        this._age = age
    }
    get age() {
        return this._age
    }
    set age(val) {
        this._age = val
    }
}class Animal {
    constructor(type, age) {
        this.type = type
        this._age = age
    }
    get age() {
        return this._age
    }
    set age(val) {
        this._age = val
    }
}继承
class Animal {
    constructor(type) {
        this.type = type
    }
    walk() {
        console.log( `I am walking` )
    }
    static eat() {
        console.log( `I am eating` )
    }
}
class Dog extends Animal {
  constructor () {
    super('dog')
  }
  run () {
    console.log('I can run')
  }
}class Animal {
    constructor(type) {
        this.type = type
    }
    walk() {
        console.log( `I am walking` )
    }
    static eat() {
        console.log( `I am eating` )
    }
}
class Dog extends Animal {
  constructor () {
    super('dog')
  }
  run () {
    console.log('I can run')
  }
}Set 
生成 Set 实例
  let s = new Set()  let s = new Set()可以定义一个空的 Set 实例,也可以在实例化的同时传入默认的数据。
  let s = new Set([1, 2, 3, 4])  let s = new Set([1, 2, 3, 4])添加数据
  s.add('hello')
  s.add('goodbye')  s.add('hello')
  s.add('goodbye')或者
  s.add('hello').add('goodbye')  s.add('hello').add('goodbye')删除数据
删除数据分两种,一种是删除指定的数据,一种是删除全部数据。
  // 删除指定数据
  s.delete('hello') // true
  // 删除全部数据
  s.clear()  // 删除指定数据
  s.delete('hello') // true
  // 删除全部数据
  s.clear()统计数据
Set 可以快速进行统计数据,如数据是否存在、数据的总数。
  // 判断是否包含数据项,返回 true 或 false
  s.has('hello') // true
  // 计算数据项总数
  s.size // 2  // 判断是否包含数据项,返回 true 或 false
  s.has('hello') // true
  // 计算数据项总数
  s.size // 2数组去重
let arr = [1, 2, 3, 4, 2, 3]
let s = new Set(arr)
console.log(s)let arr = [1, 2, 3, 4, 2, 3]
let s = new Set(arr)
console.log(s)合并去重
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1, ...arr2])//先取所有元素然后去重
console.log(s)
console.log([...s])
console.log(Array.from(s))let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1, ...arr2])//先取所有元素然后去重
console.log(s)
console.log([...s])
console.log(Array.from(s))交集
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))//filter是遍历arr1,然后返回一个数组
console.log(Array.from(result))let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))//filter是遍历arr1,然后返回一个数组
console.log(Array.from(result))差集
let arr3 = new Set(arr1.filter(item => !s2.has(item)))//先得到arr1有arr2没有的
let arr4 = new Set(arr2.filter(item => !s1.has(item)))//再得到arr2中有arr1中没有的
console.log(arr3)
console.log(arr4)
console.log([...arr3, ...arr4])//将set转换为array数组let arr3 = new Set(arr1.filter(item => !s2.has(item)))//先得到arr1有arr2没有的
let arr4 = new Set(arr2.filter(item => !s1.has(item)))//再得到arr2中有arr1中没有的
console.log(arr3)
console.log(arr4)
console.log([...arr3, ...arr4])//将set转换为array数组遍历方式
- keys():返回键名的遍历器
 - values():返回键值的遍历器
 - entries():返回键值对的遍历器
 - forEach():使用回调函数遍历每个成员
 - for...of:可以直接遍历每个成员
 
  console.log(s.keys()) // SetIterator {"hello", "goodbye"}
  console.log(s.values()) // SetIterator {"hello", "goodbye"}
  console.log(s.entries()) // SetIterator {"hello" => "hello", "goodbye" => "goodbye"}
  s.forEach(item => {
      console.log(item) // hello // goodbye
  })
  for (let item of s) {
      console.log(item)
  }
  for (let item of s.keys()) {
      console.log(item)
  }
  for (let item of s.values()) {
      console.log(item)
  }
  for (let item of s.entries()) {
      console.log(item[0], item[1])
  }  console.log(s.keys()) // SetIterator {"hello", "goodbye"}
  console.log(s.values()) // SetIterator {"hello", "goodbye"}
  console.log(s.entries()) // SetIterator {"hello" => "hello", "goodbye" => "goodbye"}
  s.forEach(item => {
      console.log(item) // hello // goodbye
  })
  for (let item of s) {
      console.log(item)
  }
  for (let item of s.keys()) {
      console.log(item)
  }
  for (let item of s.values()) {
      console.log(item)
  }
  for (let item of s.entries()) {
      console.log(item[0], item[1])
  }Map 
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
  let map = new Map([iterable])  let map = new Map([iterable])Iterable 可以是一个数组或者其他 iterable 对象,其元素为键值对(两个元素的数组,例如: [[ 1, 'one' ], [ 2, 'two' ]])。 每个键值对都会添加到新的 Map。null 会被当做 undefined。
添加数据
  let keyObj = {}
  let keyFunc = function() {}
  let keyString = 'a string'
  // 添加键
  map.set(keyString, "和键'a string'关联的值")
  map.set(keyObj, '和键keyObj关联的值')
  map.set(keyFunc, '和键keyFunc关联的值')  let keyObj = {}
  let keyFunc = function() {}
  let keyString = 'a string'
  // 添加键
  map.set(keyString, "和键'a string'关联的值")
  map.set(keyObj, '和键keyObj关联的值')
  map.set(keyFunc, '和键keyFunc关联的值')删除数据
  // 删除指定的数据
  map.delete(keyObj)
  // 删除所有数据
  map.clear()  // 删除指定的数据
  map.delete(keyObj)
  // 删除所有数据
  map.clear()统计数据
  // 统计所有 key-value 的总数
  console.log(map.size) //2
  // 判断是否有 key-value
  console.log(map.has(keyObj)) // true  // 统计所有 key-value 的总数
  console.log(map.size) //2
  // 判断是否有 key-value
  console.log(map.has(keyObj)) // true查询数据
- get() 方法返回某个 Map 对象中的一个指定元素
 
  console.log(map.get(keyObj)) // 和键keyObj关联的值  console.log(map.get(keyObj)) // 和键keyObj关联的值Proxy(没弄明白具体使用场景) 
在 ES6 标准中新增的一个非常强大的功能是 Proxy,它可以自定义一些常用行为如查找、赋值、枚举、函数调用等。通过 Proxy 这个名称也可以看出来它包含了“代理”的含义,只要有“代理”的诉求都可以考虑使用 Proxy 来实现。
语法
let p = new Proxy(target, handler)let p = new Proxy(target, handler)解释
| 参数 | 含义 | 必选 | 
|---|---|---|
| target | 用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理) | Y | 
| handler | 一个对象,其属性是当执行一个操作时定义代理的行为的函数 | Y | 
MDN 给出的解释偏官方,通俗的讲第一个参数 target 就是用来代理的“对象”,被代理之后它是不能直接被访问的,而 handler 就是实现代理的过程。
let o = {
    name: 'xiaoming',
    age: 20
}
let handler = {
    get(obj, key) {
        return Reflect.has(obj, key) ? obj[key] : ''
    }
}
let p = new Proxy(o, handler)
console.log(p.from)let o = {
    name: 'xiaoming',
    age: 20
}
let handler = {
    get(obj, key) {
        return Reflect.has(obj, key) ? obj[key] : ''
    }
}
let p = new Proxy(o, handler)
console.log(p.from)get
拦截对象属性的读取,比如proxy.foo和proxy['foo']。
let arr = [7, 8, 9]
arr = new Proxy(arr, {
    get(target, prop) {
        // console.log(target, prop)
        return prop in target ? target[prop] : 'error'
    }
})
console.log(arr[1])
console.log(arr[10])
let dict = {
    'hello': '你好',
    'world': '世界'
}
dict = new Proxy(dict, {
    get(target, prop) {
        return prop in target ? target[prop] : prop
    }
})
console.log(dict['world'])
console.log(dict['imooc'])let arr = [7, 8, 9]
arr = new Proxy(arr, {
    get(target, prop) {
        // console.log(target, prop)
        return prop in target ? target[prop] : 'error'
    }
})
console.log(arr[1])
console.log(arr[10])
let dict = {
    'hello': '你好',
    'world': '世界'
}
dict = new Proxy(dict, {
    get(target, prop) {
        return prop in target ? target[prop] : prop
    }
})
console.log(dict['world'])
console.log(dict['imooc'])set
拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
let arr = []
arr = new Proxy(arr, {
    set(target, prop, val) {
        if (typeof val === 'number') {
            target[prop] = val
            return true
        } else {
            return false
        }
    }
})
arr.push(5)
arr.push(6)
console.log(arr[0], arr[1], arr.length)let arr = []
arr = new Proxy(arr, {
    set(target, prop, val) {
        if (typeof val === 'number') {
            target[prop] = val
            return true
        } else {
            return false
        }
    }
})
arr.push(5)
arr.push(6)
console.log(arr[0], arr[1], arr.length)has
拦截propKey in proxy的操作,返回一个布尔值。
let range = {
    start: 1,
    end: 5
}
//一个对象两个属性
range = new Proxy(range, {
    has(target, prop) {
        return prop >= target.start && prop <= target.end
    }//has方法前面的target即传入对象,后面的prop是参数,使用时作为in的逆向
})
console.log(2 in range)
console.log(9 in range)let range = {
    start: 1,
    end: 5
}
//一个对象两个属性
range = new Proxy(range, {
    has(target, prop) {
        return prop >= target.start && prop <= target.end
    }//has方法前面的target即传入对象,后面的prop是参数,使用时作为in的逆向
})
console.log(2 in range)
console.log(9 in range)字符串、函数、数组和对象的扩展(Spread Operator) 
字符串 
扩展运算符可以用来将字符串分解成单个字符的数组。这在需要操作字符串中的每个字符时非常有用。例如:
javascriptCopy code
let str = "hello";
let charArray = [...str]; // ['h', 'e', 'l', 'l', 'o']javascriptCopy code
let str = "hello";
let charArray = [...str]; // ['h', 'e', 'l', 'l', 'o']数组 
数组是扩展运算符使用最为频繁的地方。它可以用于合并数组、复制数组等场景。
合并数组
可以用扩展运算符来合并两个或多个数组。
let first = [1, 2];
let second = [3, 4];
let merged = [...first, ...second]; // [1, 2, 3, 4]let first = [1, 2];
let second = [3, 4];
let merged = [...first, ...second]; // [1, 2, 3, 4]复制数组
扩展运算符可以创建一个数组的浅拷贝。
let original = [1, 2, 3];
let copy = [...original]; // [1, 2, 3]let original = [1, 2, 3];
let copy = [...original]; // [1, 2, 3]插入元素
你还可以在新数组中使用扩展运算符来插入新元素。
let numbers = [2, 3, 4];
let newNumbers = [1, ...numbers, 5]; // [1, 2, 3, 4, 5]let numbers = [2, 3, 4];
let newNumbers = [1, ...numbers, 5]; // [1, 2, 3, 4, 5]在ES2018中,扩展运算符的用法被扩展到了对象。这使得合并对象或者复制对象变得更加简单。
合并对象
可以用扩展运算符来合并两个或多个对象。如果存在同名属性,则后者会覆盖前者的属性值。
let obj1 = { a: 1, b: 2 };
let obj2 = { b: 3, c: 4 };
let mergedObj = {...obj1, ...obj2}; // { a: 1, b: 3, c: 4 }let obj1 = { a: 1, b: 2 };
let obj2 = { b: 3, c: 4 };
let mergedObj = {...obj1, ...obj2}; // { a: 1, b: 3, c: 4 }复制对象
扩展运算符可以用来创建一个对象的浅拷贝。
let originalObj = { a: 1, b: 2 };
let copiedObj = {...originalObj}; // { a: 1, b: 2 }let originalObj = { a: 1, b: 2 };
let copiedObj = {...originalObj}; // { a: 1, b: 2 }箭头函数 
let hello = () => {
    console.log('say hello')
}let hello = () => {
    console.log('say hello')
}let hello = (name) => {
    console.log('say hello', name)
}
// 或者
let hello = name => {
    console.log('say hello', name)
}let hello = (name) => {
    console.log('say hello', name)
}
// 或者
let hello = name => {
    console.log('say hello', name)
}如果只有一个参数,可以省略括号,如果大于一个参数一定要记得带括号
- 如果返回值是表达式可以省略 return 和 {}
 
  let pow = x => x * x  let pow = x => x * x如果返回值是字面量对象
如果返回值是字面量对象,一定要用小括号包起来
  let person = (name) => ({
      age: 20,
      addr: 'Beijing City'
  })  let person = (name) => ({
      age: 20,
      addr: 'Beijing City'
  })异步编程和模块化 
Promise 
const promise = new Promise(function(resolve, reject) {
    // ... some code
    if ( /* 异步操作成功 */ ) {
        resolve(value)
    } else {
        reject(error)
    }
  
})const promise = new Promise(function(resolve, reject) {
    // ... some code
    if ( /* 异步操作成功 */ ) {
        resolve(value)
    } else {
        reject(error)
    }
  
})Async / Await 
前面添加了async的函数在执行后都会自动返回一个Promise对象:
function foo() {
    return 'imooc'
}
console.log(foo()) // 'imooc'function foo() {
    return 'imooc'
}
console.log(foo()) // 'imooc'相当于
async function foo() {
    return 'imooc' // Promise.resolve('imooc')
    // let res =  Promise.resolve('imooc')
    // console.log(res)
}
console.log(foo()) // Promise
foo()async function foo() {
    return 'imooc' // Promise.resolve('imooc')
    // let res =  Promise.resolve('imooc')
    // console.log(res)
}
console.log(foo()) // Promise
foo()await后面需要跟异步操作,不然就没有意义,而且await后面的Promise对象不必写then,因为await的作用之一就是获取后面Promise对象成功状态传递出来的参数。
function timeout() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(1)
            resolve() // resolve('success')
        }, 1000)
    })
}
// 不加async和await是2、1   加了是1、2
async function foo() {
    await timeout() // let res = await timeout() res是success
    console.log(2)
}
foo()function timeout() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(1)
            resolve() // resolve('success')
        }, 1000)
    })
}
// 不加async和await是2、1   加了是1、2
async function foo() {
    await timeout() // let res = await timeout() res是success
    console.log(2)
}
foo()对于失败的处理 
function timeout() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // resolve('success')
            reject('error')
        }, 1000)
    })
}
async function foo() {
    return await timeout()
}
foo().then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})function timeout() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // resolve('success')
            reject('error')
        }, 1000)
    })
}
async function foo() {
    return await timeout()
}
foo().then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})在async函数中使用await,那么await这里的代码就会变成同步的了,意思就是说只有等await后面的Promise执行完成得到结果才会继续下去,await就是等待。
示例:需要请求a.json后请求b.json接着c.json
// 把ajax封装成模块
import ajax from './ajax'
function request(url) {
    return new Promise(resolve => {
        ajax(url, res => {
            resolve(res)
        })
    })
}
async function getData() {
    let res1 = await request('static/a.json')
    console.log(res1)
    let res2 = await request('static/b.json')
    console.log(res2)
    let res3 = await request('static/c.json')
    console.log(res3)
}
getData()// 把ajax封装成模块
import ajax from './ajax'
function request(url) {
    return new Promise(resolve => {
        ajax(url, res => {
            resolve(res)
        })
    })
}
async function getData() {
    let res1 = await request('static/a.json')
    console.log(res1)
    let res2 = await request('static/b.json')
    console.log(res2)
    let res3 = await request('static/c.json')
    console.log(res3)
}
getData()Fetch 
fetch 函数至少需要一个参数:资源的 URL。它返回一个 Promise,该 Promise 解析为一个 Response 对象。使用 .then() 方法处理响应。
例如,从一个提供文本数据的 API 获取数据:
fetch('https://api.example.com/data.txt')
  .then(response => response.text())  // 将响应体转换为文本
  .then(text => console.log(text))    // 输出获取的文本
  .catch(error => console.error('Error:', error));  // 捕获并打印错误fetch('https://api.example.com/data.txt')
  .then(response => response.text())  // 将响应体转换为文本
  .then(text => console.log(text))    // 输出获取的文本
  .catch(error => console.error('Error:', error));  // 捕获并打印错误获取一个Json
fetch('https://api.example.com/items')
  .then(response => {
    if (!response.ok) {
        throw new Error('Network response was not ok');
    }
    return response.json();  // 解析 JSON
  })
  .then(data => console.log(data))  // 输出 JSON 数据
  .catch(error => console.error('Error:', error));fetch('https://api.example.com/items')
  .then(response => {
    if (!response.ok) {
        throw new Error('Network response was not ok');
    }
    return response.json();  // 解析 JSON
  })
  .then(data => console.log(data))  // 输出 JSON 数据
  .catch(error => console.error('Error:', error));发送一个 POST 请求并附带 JSON 数据:
fetch('https://api.example.com/data', {
  method: 'POST',  // 指定请求方法为 POST
  headers: {
    'Content-Type': 'application/json'  // 设置请求头部标明内容类型
  },
  body: JSON.stringify({
    name: 'John',
    age: 30
  })  // 将 JavaScript 对象转换为 JSON 字符串作为请求体
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));fetch('https://api.example.com/data', {
  method: 'POST',  // 指定请求方法为 POST
  headers: {
    'Content-Type': 'application/json'  // 设置请求头部标明内容类型
  },
  body: JSON.stringify({
    name: 'John',
    age: 30
  })  // 将 JavaScript 对象转换为 JSON 字符串作为请求体
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));JS 
练习题: 
1.随机数 
- 随机数 Math.random() 生成0-1之间的数
 
如果需要取一个数组中的值则✖️数组长度并使用Math.floor()
(Math.random()*(max-min)+min)+1
取到min+1~max+1之间的值
解析:
random取0-1
(Max-min)*[0-1]保证得到一个数在0-(Max-min)之间
在上面的基础上➕一个min+1,则范围变为 min+1~Max+1
2.抖动函数 
SetTimeout
ClearTimeout
function debounce(fn, delay = 0) {
  let timeoutId = null; // 用于存储 setTimeout 的返回值
  // 使用箭头函数来确保 this 指向不变
  return (...args) => {
    // 如果之前的计时器尚未完成,则取消它
    if (timeoutId !== null) {
      clearTimeout(timeoutId);
    }
    // 设置一个新的计时器
    timeoutId = setTimeout(() => {
      // 直接使用 ...args 传递所有参数
      fn(...args);
    }, delay);
  };
}
module.exports = debounce; // 检测需要,请勿删除function debounce(fn, delay = 0) {
  let timeoutId = null; // 用于存储 setTimeout 的返回值
  // 使用箭头函数来确保 this 指向不变
  return (...args) => {
    // 如果之前的计时器尚未完成,则取消它
    if (timeoutId !== null) {
      clearTimeout(timeoutId);
    }
    // 设置一个新的计时器
    timeoutId = setTimeout(() => {
      // 直接使用 ...args 传递所有参数
      fn(...args);
    }, delay);
  };
}
module.exports = debounce; // 检测需要,请勿删除- 箭头函数的this
 
const obj = {
  method: function() {
    // 传统函数表达式
    console.log("Traditional function:", this); // this 指向 obj
  },
  arrowMethod: () => {
    // 箭头函数
    console.log("Arrow function:", this); // this 指向定义 arrowMethod 时的上下文
  }
};
obj.method(); // Traditional function: obj
obj.arrowMethod(); // Arrow function: [Object global] 或在浏览器环境中是 window 对象const obj = {
  method: function() {
    // 传统函数表达式
    console.log("Traditional function:", this); // this 指向 obj
  },
  arrowMethod: () => {
    // 箭头函数
    console.log("Arrow function:", this); // this 指向定义 arrowMethod 时的上下文
  }
};
obj.method(); // Traditional function: obj
obj.arrowMethod(); // Arrow function: [Object global] 或在浏览器环境中是 window 对象3.数据类型 
- Set 集合[每种元素只出现一次]
 
const mySet = new Set();
// 用数组初始化 Set
const mySetWithValues = new Set([1, 2, 3, 4, 4, 5]);
console.log(mySetWithValues); // Set(5) {1, 2, 3, 4, 5}
// 新增
mySet.add(1);
mySet.add(2);
mySet.add(2); // 添加一个已存在的元素不会有任何效果
// 检查
console.log(mySet.has(1)); // true
console.log(mySet.has(3)); // false
// 删除
mySet.delete(2);
console.log(mySet.has(2)); // false
// 清空所有
mySet.clear();
console.log(mySet.size); // 0
// 获取大小
console.log(mySetWithValues.size); // 5
// 两种遍历方式
// forEach
mySetWithValues.forEach(value => {
  console.log(value);
});
// for循环
for (let value of mySetWithValues) {
  console.log(value);
}const mySet = new Set();
// 用数组初始化 Set
const mySetWithValues = new Set([1, 2, 3, 4, 4, 5]);
console.log(mySetWithValues); // Set(5) {1, 2, 3, 4, 5}
// 新增
mySet.add(1);
mySet.add(2);
mySet.add(2); // 添加一个已存在的元素不会有任何效果
// 检查
console.log(mySet.has(1)); // true
console.log(mySet.has(3)); // false
// 删除
mySet.delete(2);
console.log(mySet.has(2)); // false
// 清空所有
mySet.clear();
console.log(mySet.size); // 0
// 获取大小
console.log(mySetWithValues.size); // 5
// 两种遍历方式
// forEach
mySetWithValues.forEach(value => {
  console.log(value);
});
// for循环
for (let value of mySetWithValues) {
  console.log(value);
}4.排序函数Sort 
- 默认不使用参数
 
const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
console.log(fruits); // 输出: ["Apple", "Banana", "Mango", "Orange"]const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
console.log(fruits); // 输出: ["Apple", "Banana", "Mango", "Orange"]带参数的情况
- 如果返回值小于 0,那么 
a会被排在b前面; 
如果返回值大于 0,
b会被排在a前面;如果返回值等于 0,
a和b的相对位置不变。(但是在某些JavaScript引擎的实现中,相对位置可能会改变,因此最好不要依赖于相对位置不变的特性。)
- 如果返回值小于 0,那么 
 a-b (从小到大,升序排序)
b-a(从大到小,降序排序)
注意事项 
sort()方法会原地排序数组,并且返回对原数组的引用。这意味着它直接修改原数组,而不是创建一个新的排序后的数组。- 对非ASCII字符的字符串进行排序时,默认排序可能不会按照本地语言习惯来排序。在这种情况下,你可以使用 
Intl.Collator对象,这是一个基于国际化的比较器,可以作为sort()方法的比较函数来使用。 
- 箭头函数➡️记得 return 否则不要加大括号{}
 
5.reduce函数(复杂) 
array.reduce(function(accumulator, currentValue, currentIndex, array), initialValue)array.reduce(function(accumulator, currentValue, currentIndex, array), initialValue)- accumulator - 累加器累计回调的返回值;它是上一次调用回调时返回的累积值,或者是提供的初始值(
initialValue)。 - currentValue - 数组中正在处理的元素。
 - currentIndex(可选)- 数组中正在处理的当前元素的索引。如果提供了
initialValue,则起始索引号为0,否则为1。 - array(可选)- 调用
reduce的数组。 - initialValue(可选)- 作为第一次调用 
callback函数时第一个参数的值。 
function orderStudentGrade(students) {
  let r = students.reduce((t,v)=> (t[v.class] ? t[v.class].push(v) : t[v.class] = [v],t),{})
  for(let k in  r){
    r[k].sort((a,b)=> (b.math+b.language+b.english+b.physics+b.chemistry)-(a.math+a.language+a.physics+a.chemistry+a.english))
  }
  return r
}function orderStudentGrade(students) {
  let r = students.reduce((t,v)=> (t[v.class] ? t[v.class].push(v) : t[v.class] = [v],t),{})
  for(let k in  r){
    r[k].sort((a,b)=> (b.math+b.language+b.english+b.physics+b.chemistry)-(a.math+a.language+a.physics+a.chemistry+a.english))
  }
  return r
}reduce() 被用来对数组 students 进行操作,目的是根据学生所在班级将他们分组。这里的 reduce() 初始值是一个空对象 {},并逐步构建成一个以班级为键,班级中所有学生对象数组为值的对象。
每次迭代时,reduce() 的回调函数检查当前处理的学生 (next) 是否属于已经在累加器 (prev) 中存在的班级:
- 如果班级已存在,就将当前学生添加到该班级的数组中。
 - 如果班级不存在,就首先为该班级创建一个空数组,并将学生添加到数组中。
 
6.扩展运算符... 
- 遍历方法:
 
1. 使用 for 循环
```
function collectPuzzle(...puzzles) {
  for (let i = 0; i < puzzles.length; i++) {
    console.log(puzzles[i]); // 处理每个拼图
  }
}
```
2. 使用 for...of 循环
for...of 循环是ES6引入的,适用于遍历数组和其他可迭代对象。
```
function collectPuzzle(...puzzles) {
  for (let puzzle of puzzles) {
    console.log(puzzle); // 处理每个拼图
  }
}
```
3. 使用 forEach() 方法
forEach() 是数组的方法,可以为数组中的每个元素执行一次提供的函数。
```
function collectPuzzle(...puzzles) {
  puzzles.forEach(puzzle => {
    console.log(puzzle); // 处理每个拼图
  });
}
```1. 使用 for 循环
```
function collectPuzzle(...puzzles) {
  for (let i = 0; i < puzzles.length; i++) {
    console.log(puzzles[i]); // 处理每个拼图
  }
}
```
2. 使用 for...of 循环
for...of 循环是ES6引入的,适用于遍历数组和其他可迭代对象。
```
function collectPuzzle(...puzzles) {
  for (let puzzle of puzzles) {
    console.log(puzzle); // 处理每个拼图
  }
}
```
3. 使用 forEach() 方法
forEach() 是数组的方法,可以为数组中的每个元素执行一次提供的函数。
```
function collectPuzzle(...puzzles) {
  puzzles.forEach(puzzle => {
    console.log(puzzle); // 处理每个拼图
  });
}
```注意事项: 
在JavaScript中,for...in 循环是用来遍历对象的属性的一种方式。这种循环会遍历一个对象的所有可枚举属性,包括其原型链中继承的属性。因此,它通常用于对象,而不是用于数组,因为对数组使用 for...in 循环可能会带来意想不到的行为,如遍历出非索引属性或原型链上的属性。
const object = {a: 1, b: 2, c: 3};
for (const key in object) {
  console.log(key, object[key]);
}const object = {a: 1, b: 2, c: 3};
for (const key in object) {
  console.log(key, object[key]);
}7. setInterval 
let timer = setInverval(
	()=>{
		clearInterval(timer)  //进行消除
	}
)let timer = setInverval(
	()=>{
		clearInterval(timer)  //进行消除
	}
)8.dom操作 
document.querySelector(" ").addEventListener("click",()=>{
})
// 查询并监听点击事件
const spanEle = document.createElement("span")
spanEle.innerText = ""
spanEle.style.positon = "absolute"document.querySelector(" ").addEventListener("click",()=>{
})
// 查询并监听点击事件
const spanEle = document.createElement("span")
spanEle.innerText = ""
spanEle.style.positon = "absolute"9.正则表达式 
1: 匹配字符串 
假设你想在一段文本中查找单词 "apple"。
const text = "I have an apple.";
const regex = /apple/;
const matchResult = text.match(regex);
console.log(matchResult); // 输出: ["apple"]const text = "I have an apple.";
const regex = /apple/;
const matchResult = text.match(regex);
console.log(matchResult); // 输出: ["apple"]2: 使用标志 
在正则表达式中,你可以使用不同的标志。例如,i 表示忽略大小写,g 表示全局搜索(匹配所有结果而非停在第一个)。
const text = "Apples are tasty, and I like apples.";
const regex = /apples/gi;
const matchResult = text.match(regex);
console.log(matchResult); // 输出: ["Apples", "apples"]const text = "Apples are tasty, and I like apples.";
const regex = /apples/gi;
const matchResult = text.match(regex);
console.log(matchResult); // 输出: ["Apples", "apples"]3: 替换文本 
你也可以使用正则表达式替换文本中的某些部分。
const text = "Hello, world!";
const regex = /world/;
const newText = text.replace(regex, "JavaScript");
console.log(newText); // 输出: "Hello, JavaScript!"const text = "Hello, world!";
const regex = /world/;
const newText = text.replace(regex, "JavaScript");
console.log(newText); // 输出: "Hello, JavaScript!"4: 测试字符串是否匹配 
如果你只想检查一个字符串是否匹配一个正则表达式,可以使用 test() 方法。
const text = "JavaScript is fun.";
const regex = /javascript/i;
const isMatch = regex.test(text);
console.log(isMatch); // 输出: trueconst text = "JavaScript is fun.";
const regex = /javascript/i;
const isMatch = regex.test(text);
console.log(isMatch); // 输出: true5:使用捕获组 
捕获组可以帮助你从字符串中提取信息。
const text = "My birthday is 12/15/1997.";
const regex = /(\d{2})\/(\d{2})\/(\d{4})/;
const matchResult = text.match(regex);
console.log(matchResult);
// 输出: ["12/15/1997", "12", "15", "1997", index: 15, input: "My birthday is 12/15/1997.", groups: undefined]const text = "My birthday is 12/15/1997.";
const regex = /(\d{2})\/(\d{2})\/(\d{4})/;
const matchResult = text.match(regex);
console.log(matchResult);
// 输出: ["12/15/1997", "12", "15", "1997", index: 15, input: "My birthday is 12/15/1997.", groups: undefined]10.Object 
hasOwnProperty("key") 判断其是否存在属性
for in遍历 进行循环,必要时使用 []获取值
11.字符串相关函数 
charAt(index)- 返回指定位置的字符。concat(string2, string3, ..., stringN)- 连接两个或多个字符串,并返回新的字符串。includes(searchString, position)- 检查字符串是否包含指定的子字符串,返回布尔值。indexOf(searchValue, fromIndex)- 返回指定子字符串在字符串中首次出现的索引,如果没有找到,则返回-1。lastIndexOf(searchValue, fromIndex)- 返回指定子字符串在字符串中最后一次出现的索引,如果没有找到,则返回-1。match(regexp)- 对字符串执行一个正则表达式搜索,并返回一个包含结果的数组或null。replace(searchFor, replaceWith)- 替换与正则表达式或子字符串匹配的部分。replaceAll(searchFor, replaceWith)- 替换字符串中所有匹配项。slice(beginIndex, endIndex)- 提取字符串的某个部分,并以新的字符串返回被提取的部分。split(separator, limit)- 通过将字符串分割成子字符串来将其分割成一个字符串数组。substring(startIndex, endIndex)- 返回字符串中指定两个索引之间的字符。toLowerCase()- 将字符串转换为小写。toUpperCase()- 将字符串转换为大写。trim()- 从字符串的两端删除空白字符。trimStart()或trimLeft()- 从字符串的开头删除空白字符。trimEnd()或trimRight()- 从字符串的结尾删除空白字符。length- 属性,返回字符串的长度。
Vue2 
Options API 
<script>
export default {
  // Properties returned from data() become reactive state
  // and will be exposed on `this`.
  data() {
    return {
      count: 0
    }
  },
  // Methods are functions that mutate state and trigger updates.
  // They can be bound as event handlers in templates.
  methods: {
    increment() {
      this.count++
    }
  },
  // Lifecycle hooks are called at different stages
  // of a component's lifecycle.
  // This function will be called when the component is mounted.
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template><script>
export default {
  // Properties returned from data() become reactive state
  // and will be exposed on `this`.
  data() {
    return {
      count: 0
    }
  },
  // Methods are functions that mutate state and trigger updates.
  // They can be bound as event handlers in templates.
  methods: {
    increment() {
      this.count++
    }
  },
  // Lifecycle hooks are called at different stages
  // of a component's lifecycle.
  // This function will be called when the component is mounted.
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>watch 
<template>
  <div>
    <input v-model="inputDate" placeholder="输入日期,格式为 YYYY-MM-DD">
    <button @click="fetchData">获取数据</button>
    <div v-if="loading">正在加载...</div>
    <div v-else-if="error" class="error">加载错误: {{ error }}</div>
    <div v-else>
      <h3>数据结果</h3>
      <pre>{{ result }}</pre>
    </div>
  </div>
</template>
<script>
export default {
  name: 'DatePicker',
  data() {
    return {
      inputDate: '',
      result: null,
      error: null,
      loading: false
    };
  },
  methods: {
    fetchData() {
      this.loading = true;
      this.error = null;
      // 模拟从服务器获取数据
      setTimeout(() => {
        if (this.inputDate === '2020-01-01') {
          this.result = { message: '新年好!' };
        } else {
          this.result = { message: `数据为 ${this.inputDate}` };
        }
        this.loading = false;
      }, 1000);
    }
  },
  watch: {
    // 监听 inputDate 的变化
    inputDate(newVal, oldVal) {
      if (newVal.trim() && newVal !== oldVal) {
        console.log(`日期从 ${oldVal} 改变到 ${newVal}`);
        this.fetchData();
      }
    }
  }
}
</script>
<style scoped>
.error {
  color: red;
}
</style><template>
  <div>
    <input v-model="inputDate" placeholder="输入日期,格式为 YYYY-MM-DD">
    <button @click="fetchData">获取数据</button>
    <div v-if="loading">正在加载...</div>
    <div v-else-if="error" class="error">加载错误: {{ error }}</div>
    <div v-else>
      <h3>数据结果</h3>
      <pre>{{ result }}</pre>
    </div>
  </div>
</template>
<script>
export default {
  name: 'DatePicker',
  data() {
    return {
      inputDate: '',
      result: null,
      error: null,
      loading: false
    };
  },
  methods: {
    fetchData() {
      this.loading = true;
      this.error = null;
      // 模拟从服务器获取数据
      setTimeout(() => {
        if (this.inputDate === '2020-01-01') {
          this.result = { message: '新年好!' };
        } else {
          this.result = { message: `数据为 ${this.inputDate}` };
        }
        this.loading = false;
      }, 1000);
    }
  },
  watch: {
    // 监听 inputDate 的变化
    inputDate(newVal, oldVal) {
      if (newVal.trim() && newVal !== oldVal) {
        console.log(`日期从 ${oldVal} 改变到 ${newVal}`);
        this.fetchData();
      }
    }
  }
}
</script>
<style scoped>
.error {
  color: red;
}
</style>要点:
watch:{
 ”变量名“(newVal,oldVal){
 //操作
 }
}
//Vue3中
import {watch} from 'vue'
watch(inputDate, (newValue, oldValue) => {
      if (newValue.trim() && newValue !== oldValue) {
        fetchData();
      }
    });//Vue3中
import {watch} from 'vue'
watch(inputDate, (newValue, oldValue) => {
      if (newValue.trim() && newValue !== oldValue) {
        fetchData();
      }
    });computed 
//Vue2
computed: {
    formattedDate() {
      return `The entered date is: ${this.inputDate}`;
    }
  }//Vue2
computed: {
    formattedDate() {
      return `The entered date is: ${this.inputDate}`;
    }
  }要点:
computed:{
 "变量名"(){
 return 一个返回值
}
}
//Vue3中
// 创建计算属性
    const fullName = computed(() => {
      return `${firstName.value} ${lastName.value}`;
    });//Vue3中
// 创建计算属性
    const fullName = computed(() => {
      return `${firstName.value} ${lastName.value}`;
    });This.$emit() 
<!-- ButtonComponent.vue -->
<template>
  <button @click="handleClick">Click me!</button>
</template>
<script>
export default {
  methods: {
    handleClick() {
      // 发出 'clicked' 事件
      this.$emit('clicked', 'Button was clicked!');
    }
  }
}
</script><!-- ButtonComponent.vue -->
<template>
  <button @click="handleClick">Click me!</button>
</template>
<script>
export default {
  methods: {
    handleClick() {
      // 发出 'clicked' 事件
      this.$emit('clicked', 'Button was clicked!');
    }
  }
}
</script><template>
  <div>
    <button-component @clicked="handleButtonClicked"></button-component>
    <p v-if="message">{{ message }}</p>
  </div>
</template>
<script>
import ButtonComponent from './ButtonComponent.vue'
export default {
  components: {
    ButtonComponent
  },
  data() {
    return {
      message: ''
    };
  },
  methods: {
    handleButtonClicked(msg) {
      // 当 'clicked' 事件被触发时,这个方法被调用
      this.message = msg;
    }
  }
}
</script><template>
  <div>
    <button-component @clicked="handleButtonClicked"></button-component>
    <p v-if="message">{{ message }}</p>
  </div>
</template>
<script>
import ButtonComponent from './ButtonComponent.vue'
export default {
  components: {
    ButtonComponent
  },
  data() {
    return {
      message: ''
    };
  },
  methods: {
    handleButtonClicked(msg) {
      // 当 'clicked' 事件被触发时,这个方法被调用
      this.message = msg;
    }
  }
}
</script>props 
<!-- ChildComponent.vue -->
<template>
  <div>
    <h1>{{ title }}</h1>
  </div>
</template>
<script>
export default {
  props: {
    title: String
  }
}
</script><!-- ChildComponent.vue -->
<template>
  <div>
    <h1>{{ title }}</h1>
  </div>
</template>
<script>
export default {
  props: {
    title: String
  }
}
</script>父子通信,将父组件的值传递给子组件
<!-- ParentComponent.vue -->
<template>
  <div>
    <child-component :title="parentTitle"></child-component>
  </div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
  components: {
    'child-component': ChildComponent
  },
  data() {
    return {
      parentTitle: 'Hello from Parent'
    }
  }
}
</script><!-- ParentComponent.vue -->
<template>
  <div>
    <child-component :title="parentTitle"></child-component>
  </div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
  components: {
    'child-component': ChildComponent
  },
  data() {
    return {
      parentTitle: 'Hello from Parent'
    }
  }
}
</script>要点:
子组件: props: { title:string}(名称:类型)
父组件: : props名=“传递值“
Vue3 
Compositon API 
<script setup>
import { ref, onMounted } from 'vue'
// reactive state
const count = ref(0)
// functions that mutate state and trigger updates
function increment() {
  count.value++
}
// lifecycle hooks
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template><script setup>
import { ref, onMounted } from 'vue'
// reactive state
const count = ref(0)
// functions that mutate state and trigger updates
function increment() {
  count.value++
}
// lifecycle hooks
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>ref 
ref 用于定义一个响应式的数据引用。当你使用 ref 时,你实际上创建了一个响应式的对象,这个对象有一个 .value 属性指向实际的值。ref 通常用于基本类型数据,但也可以用于引用类型数据。
<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="count++">Increment</button>
  </div>
</template>
<script>
import { ref } from 'vue';
export default {
  setup() {
    const count = ref(0);
    return {
      count
    };
  }
}
</script><template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="count++">Increment</button>
  </div>
</template>
<script>
import { ref } from 'vue';
export default {
  setup() {
    const count = ref(0);
    return {
      count
    };
  }
}
</script>在模板中,我们可以直接使用 count,而在 JavaScript 中访问或修改它时,需要使用 count.value。
reactive 
reactive 用于创建响应式对象。它使得一个普通对象变为响应式的,所有嵌套的属性也都是响应式的。适合用于更复杂或结构化的数据对象。
<template>
  <div>
    <h1>{{ state.count }}</h1>
    <button @click="state.count++">Increment</button>
  </div>
</template>
<script>
import { reactive } from 'vue';
export default {
  setup() {
    const state = reactive({
      count: 0
    });
    return {
      state
    };
  }
}
</script><template>
  <div>
    <h1>{{ state.count }}</h1>
    <button @click="state.count++">Increment</button>
  </div>
</template>
<script>
import { reactive } from 'vue';
export default {
  setup() {
    const state = reactive({
      count: 0
    });
    return {
      state
    };
  }
}
</script>在这个例子中,我们使用 reactive 创建了一个响应式的对象 state,它包含一个属性 count。在模板中,我们通过 state.count 直接访问和修改 count 的值。
Props 和 Events 
Porps 
父
<template>
  <ChildComponent :message="parentMessage" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentMessage = ref('Hello from parent!');
</script><template>
  <ChildComponent :message="parentMessage" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentMessage = ref('Hello from parent!');
</script>子
<template>
  <div>{{ message }}</div>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
  message: String
});
</script><template>
  <div>{{ message }}</div>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
  message: String
});
</script>要点:
子:
const props = defineProps({
 变量名 : 类型
})
父:
引入组件后使用 :变量名="值"
Events 
子组件向父组件发送消息则通过 $emit 方法。Vue 3 支持在 <script setup> 中直接使用 defineEmits 或通过返回的方法使用。
子:
<template>
  <button @click="notifyParent">Click me!</button>
</template>
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['notify']);
const notifyParent = () => {
  emit('notify', 'Message from child!');
};
</script><template>
  <button @click="notifyParent">Click me!</button>
</template>
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['notify']);
const notifyParent = () => {
  emit('notify', 'Message from child!');
};
</script>父:
<template>
  <ChildComponent @notify="handleNotify" />
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
const handleNotify = (message) => {
  console.log(message); // 输出: Message from child!
};
</script><template>
  <ChildComponent @notify="handleNotify" />
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
const handleNotify = (message) => {
  console.log(message); // 输出: Message from child!
};
</script>要点:
子:
使用defineEmits(['函数名'])
const 触发的函数 = ( )=>{
 emit('绑定的函数名',"传递的值")
}
父:
引入子组件,@绑定函数名=”触发自己的函数(参数)“
再写函数进行使用
Provide / Inject 
Vue 3 仍然支持使用 provide 和 inject 进行跨组件层级的通信,这对于开发深层次嵌套的组件特别有用。这在 Vue 3 中得到了进一步的优化,尤其是在使用组合式 API 时。
祖先: provide ("kdy",value) 提供
<script setup>
import { provide } from 'vue';
const someData = 'secret data';
provide('key', someData);
</script><script setup>
import { provide } from 'vue';
const someData = 'secret data';
provide('key', someData);
</script>后代: inject("key")获取
<script setup>
import { inject } from 'vue';
const receivedData = inject('key');
</script><script setup>
import { inject } from 'vue';
const receivedData = inject('key');
</script>Router 
const router = createRouter({
  // TODO:待补充代码,为项目配置 history 模式的路由
  history: createWebHistory(),
  routes: [
    { path: "/", component: WalletPage },
    { path: "/deposit", component: DepositPage },
  ],
});const router = createRouter({
  // TODO:待补充代码,为项目配置 history 模式的路由
  history: createWebHistory(),
  routes: [
    { path: "/", component: WalletPage },
    { path: "/deposit", component: DepositPage },
  ],
});Piania 
创建 Pinia Store 
import { defineStore } from 'pinia'
//先定义一个store的用途,这里是作为主要的store
export const useMainStore = defineStore('main', {
  state: () => ({
    count: 0
  }),
  //sote里由2部分组成: actions & state
  //state负责保存状态
  //actions负责控制state
  actions: {
    increment() {
      this.count++
    }
  }
})import { defineStore } from 'pinia'
//先定义一个store的用途,这里是作为主要的store
export const useMainStore = defineStore('main', {
  state: () => ({
    count: 0
  }),
  //sote里由2部分组成: actions & state
  //state负责保存状态
  //actions负责控制state
  actions: {
    increment() {
      this.count++
    }
  }
})在 Vue 组件中使用 Store 
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()//先创建piania
app.use(pinia)//再app.use
app.mount('#app')import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()//先创建piania
app.use(pinia)//再app.use
app.mount('#app')<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>
<script setup>
import { useMainStore } from './store'
  //使用store时先导入
const store = useMainStore()
//然后定义一个store用
const { count, increment } = storeToRefs(store)
// 通过storeToRefs得到对应的变量
</script><template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>
<script setup>
import { useMainStore } from './store'
  //使用store时先导入
const store = useMainStore()
//然后定义一个store用
const { count, increment } = storeToRefs(store)
// 通过storeToRefs得到对应的变量
</script>模块化、插件、持久化...
Axios 
Get请求 
<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import axios from 'axios';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script><template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import axios from 'axios';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script>Post请求 
<template>
  <div>
    <button @click="addUser">添加用户</button>
    <p v-if="message">{{ message }}</p>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const message = ref('');
async function addUser() {
  const user = {
    name: '新用户',
    email: 'newuser@example.com'
  };
  try {
    const response = await axios.post('https://jsonplaceholder.typicode.com/users', user);
    message.value = '用户添加成功: ' + response.data.name;
  } catch (error) {
    console.error('添加用户失败', error);
    message.value = '添加用户失败';
  }
}
</script><template>
  <div>
    <button @click="addUser">添加用户</button>
    <p v-if="message">{{ message }}</p>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const message = ref('');
async function addUser() {
  const user = {
    name: '新用户',
    email: 'newuser@example.com'
  };
  try {
    const response = await axios.post('https://jsonplaceholder.typicode.com/users', user);
    message.value = '用户添加成功: ' + response.data.name;
  } catch (error) {
    console.error('添加用户失败', error);
    message.value = '添加用户失败';
  }
}
</script>混合Vue\TS使用 
<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import axios from 'axios';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script><template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import axios from 'axios';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script>- Post
 
<template>
  <div>
    <button @click="addUser">添加用户</button>
    <p v-if="message">{{ message }}</p>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';
interface User {
  name: string;
  email: string;
}
interface ResponseUser extends User {
  id: number;
}
const message = ref<string>('');
async function addUser() {
  const user: User = {
    name: '新用户',
    email: 'newuser@example.com'
  };
  try {
    const response = await axios.post<ResponseUser>('https://jsonplaceholder.typicode.com/users', user);
    message.value = '用户添加成功: ' + response.data.name;
  } catch (error) {
    console.error('添加用户失败', error);
    message.value = '添加用户失败';
  }
}
</script><template>
  <div>
    <button @click="addUser">添加用户</button>
    <p v-if="message">{{ message }}</p>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';
interface User {
  name: string;
  email: string;
}
interface ResponseUser extends User {
  id: number;
}
const message = ref<string>('');
async function addUser() {
  const user: User = {
    name: '新用户',
    email: 'newuser@example.com'
  };
  try {
    const response = await axios.post<ResponseUser>('https://jsonplaceholder.typicode.com/users', user);
    message.value = '用户添加成功: ' + response.data.name;
  } catch (error) {
    console.error('添加用户失败', error);
    message.value = '添加用户失败';
  }
}
</script>创建和使用Axios实例(默认配置) 
步骤1: 创建Axios实例
首先,你需要创建一个Axios实例,并对其进行配置。这通常在一个单独的文件中完成,以便于管理和复用。
// src/api/client.js
import axios from 'axios';
// 创建axios实例
const apiClient = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com', // API的基础URL
  headers: {
    'Content-Type': 'application/json', // 默认内容类型
  },
  timeout: 1000, // 请求超时时间
});
export default apiClient;
// src/api/client.js
import axios from 'axios';
// 创建axios实例
const apiClient = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com', // API的基础URL
  headers: {
    'Content-Type': 'application/json', // 默认内容类型
  },
  timeout: 1000, // 请求超时时间
});
export default apiClient;步骤2: 在Vsue组件中使用Axios实例
接下来,在Vue组件中导入并使用这个实例来发起HTTP请求。
<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import apiClient from '@/api/client';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await apiClient.get<User[]>('/users'); // 使用自定义Axios实例
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script><template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import apiClient from '@/api/client';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await apiClient.get<User[]>('/users'); // 使用自定义Axios实例
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script>使用自定义Axios实例的好处包括:
- 一致性:通过统一配置如基础URL、头信息等,你可以确保所有的HTTP请求都遵循相同的标准。
 - 可维护性:当你需要更改如超时时间、头信息等全局HTTP设置时,你只需在一个地方进行修改。
 - 复用性:你可以创建多个不同配置的Axios实例,分别对应不同的后端服务。
 
请求配置选项 
method:指定请求的HTTP方法,例如GET、POST、PUT、DELETE等。
url:指定请求的URL。
params:指定请求的查询参数,以对象的形式提供。
data:指定请求的主体数据,适用于POST、PUT等请求。
headers:指定请求的头信息,以对象的形式提供。
timeout:指定请求的超时时间,单位为毫秒。
auth:指定身份验证信息,可以是一个包含username和password的对象,也可以是一个{ username, password }形式的数组。
withCredentials:指定是否发送跨域请求时携带身份验证凭据(如cookies)。
responseType:指定响应的数据类型,例如json、blob、document等。
示例
<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import axios from 'axios';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await axios.get<User[]>('/users', {
      params: {
        // 设置查询参数
        page: 1,
        limit: 10
      },
      headers: {
        // 设置请求头
        'X-Requested-With': 'XMLHttpRequest'
      },
      timeout: 5000, // 设置超时时间为5秒
      withCredentials: true, // 发送跨域请求时携带凭据
    });
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script><template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import axios from 'axios';
interface User {
  id: number;
  name: string;
  email: string;
}
const users = ref<User[]>([]);
onMounted(async () => {
  try {
    const response = await axios.get<User[]>('/users', {
      params: {
        // 设置查询参数
        page: 1,
        limit: 10
      },
      headers: {
        // 设置请求头
        'X-Requested-With': 'XMLHttpRequest'
      },
      timeout: 5000, // 设置超时时间为5秒
      withCredentials: true, // 发送跨域请求时携带凭据
    });
    users.value = response.data;
  } catch (error) {
    console.error('There was an error!', error);
  }
});
</script>使用拦截器的场景 
- 添加通用的HTTP头:例如,你可能想在每个请求中自动添加一个认证令牌。
 - 响应处理:自动处理某些全局的HTTP响应,例如重定向或者特定错误码。
 - 请求数据转换:在请求发送到服务器之前修改请求数据。
 - 响应数据转换:在响应数据到达客户端之前对其进行格式化。
 
下面的例子展示了如何在Axios实例中添加请求拦截器和响应拦截器:
// src/api/client.js
import axios from 'axios';
const apiClient = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
});
// 添加请求拦截器
apiClient.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    // 例如添加认证令牌
    const token = localStorage.getItem('authToken');
    config.headers.Authorization = token ? `Bearer ${token}` : '';
    return config;
  }, 
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);
// 添加响应拦截器
apiClient.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    // 可以在这里统一处理数据格式
    return response.data;
  },
  function (error) {
    // 对响应错误做点什么
    if (error.response && error.response.status === 401) {
      // 例如,如果用户未授权,可以在这里处理
      console.log('需要用户验证');
    }
    return Promise.reject(error);
  }
);
export default apiClient;// src/api/client.js
import axios from 'axios';
const apiClient = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
});
// 添加请求拦截器
apiClient.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    // 例如添加认证令牌
    const token = localStorage.getItem('authToken');
    config.headers.Authorization = token ? `Bearer ${token}` : '';
    return config;
  }, 
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);
// 添加响应拦截器
apiClient.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    // 可以在这里统一处理数据格式
    return response.data;
  },
  function (error) {
    // 对响应错误做点什么
    if (error.response && error.response.status === 401) {
      // 例如,如果用户未授权,可以在这里处理
      console.log('需要用户验证');
    }
    return Promise.reject(error);
  }
);
export default apiClient;要点:interceptors.response/request.use(fun (response), fun (error))
Node 
创建Http服务器 
const http = require('http');
const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
});
const PORT = 3000;
server.listen(PORT, () => {
    console.log(`服务器运行在 http://localhost:${PORT}/`);
});const http = require('http');
const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
});
const PORT = 3000;
server.listen(PORT, () => {
    console.log(`服务器运行在 http://localhost:${PORT}/`);
});使用fs模块读写文件 
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
    if (err) {
        console.error('读取文件时发生错误:', err);
        return;
    }
    console.log(data);
});
//写入
fs.writeFile('output.txt', '这是一段文本内容', (err) => {
    if (err) {
        console.error('写入文件时发生错误:', err);
        return;
    }
    console.log('文件已被保存');
});const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
    if (err) {
        console.error('读取文件时发生错误:', err);
        return;
    }
    console.log(data);
});
//写入
fs.writeFile('output.txt', '这是一段文本内容', (err) => {
    if (err) {
        console.error('写入文件时发生错误:', err);
        return;
    }
    console.log('文件已被保存');
});使用Promises和Async/Await处理异步操作 
const fs = require('fs').promises;
async function readFile() {
    try {
        const data = await fs.readFile('example.txt', 'utf8');
        console.log(data);
    } catch (err) {
        console.error('读取文件时发生错误:', err);
    }
}
readFile();const fs = require('fs').promises;
async function readFile() {
    try {
        const data = await fs.readFile('example.txt', 'utf8');
        console.log(data);
    } catch (err) {
        console.error('读取文件时发生错误:', err);
    }
}
readFile();环境变量的使用 
首先,创建一个.env文件:
DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3然后,在你的应用中加载并使用这些变量:
require('dotenv').config();
console.log(process.env. DB_HOST);
console.log(process.env. DB_USER);
console.log(process.env. DB_PASS);require('dotenv').config();
console.log(process.env. DB_HOST);
console.log(process.env. DB_USER);
console.log(process.env. DB_PASS);