js其他笔记

2/10/2022 笔记js

# 移动端

屏幕适配

/*
  屏幕     size     效果图
  375      50px     750px    
  750      100px    750px

  W=window.innerWidth 窗口宽度
  html-font-size=W/375*50=W*50/375=100*100/750vw

*/

/*
  fontsize=10000/效果图宽度 vw
  量出来多少 除以100转化位rem即可
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 事件

按下事件

function tap(el, hook) {
  var time = 0;
  el.ontouchstart = function (e) {
    time = new Date().getTime();
  }
  el.ontouchend = function (e) {
    var time2 = new Date().getTime();
    if (time2 - time < 300) {
      hook.call(this, e);
    }
  }
  el.ontouchmove = function (e) {
    time -= 300
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

长按事件

function longPress(el,f){
  var timer;
  el.addEventListener("touchstart",function(e){
    timer=setTimeout(function(){
      f.call(el,e)
    },1000)
  })
  el.addEventListener("touchend",function(){
    clearTimeout(timer);
  })
}
1
2
3
4
5
6
7
8
9
10
11

# 视频 & 音频

tip method
暂停 el.pause()
播放 el.play()
当前播放时间 el.currentTime 可以赋值
总时长 el.duration
播放时间发生变化时 ontimeupdate
加载完毕时 oncanplay

# video.js

<video controls id="vid" class="video-js vid-default-skin">
  //可以写多个source标签  以让浏览器选择合适的视频类型
  <source src="https://gd-sycdn.kuwo.cn/b7fb7b0bfdecbce09c11d5b466e46dc9/61aeffc5/resource/m2/59/7/2701626468.mp4">
</video>

<script>
  var myvid=videojs("vid",function(){//准备就绪

  });

  // 更新播放地址
  myvid.src("https://other-web-nf03-sycdn.kuwo.cn/9dee4d569805774ac415411389735936/61af020f/resource/m1/51/49/2408827443.mp4")
  //或者
  myvid.src([{
    src:"https://other-web-nf03-sycdn.kuwo.cn/9dee4d569805774ac415411389735936/61af020f/resource/m1/51/49/2408827443.mp4",
    type:"video/mp4"
  }])

  // 监听事件
  myvid.on("timeupdate",function(){
    console.log(this.currentTime(),this.duration());
  })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

指定 flash 格式

videojs("vid", {
  flash: {
    swf: "./videojs/video-js.swf"
  }
});
1
2
3
4
5

# 文件上传

# 生成临时地址

标签加上 multiple 可以多选

<label>
  <input type="file" id="myfile" style="display: none;">
  <p>选择文件</p>
</label>

<script>
  // 选择文件
  // myfile.onchange=function(){
  //     console.log(this.files);
  // }

  var files=[];
	//监听文件选择
  myfile.onchange=function(){
    // console.log()
    // 生成临时地址
    var path=URL.createObjectURL(this.files[0]);
    pic.src=path;
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

tips: 视频音频也可以预览

vid.src=URL.createObjectURL(this.files[0]);

# FormData

// 生成对象
var formdata=new FormData();
formdata.append("userName","张三");
formdata.append("password","20");
//不用给请求头加  参数类型了
fetch("http://39.96.88.57/login",{
  method:"POST",
  body:formdata
})
  .then(r=>r.json())
  .then(function(res){
  console.log(res);
})
1
2
3
4
5
6
7
8
9
10
11
12
13

# FormData上传文件

//获取到选择的文件
myfile.onchange=function(){
  file=this.files[0];
}

if (file) {
  // 上传
  var formdata = new FormData();
  formdata.append("type", "image");
  //把选择的文件append进去 即可以上传文件到服务器了
  formdata.append("file", file)

  fetch("http://192.168.218.160:4567/appendix/upload", {
    method: "POST",
    body: formdata
  })
    .then(r => r.json())
    .then(function (res) {
    console.log(res);
  })


} else {
  alert("请选择文件")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# ajax+form+formData

<form id="myform">
  <input type="text" name="userName">
  <input type="text" name="password">
  <input type="text" name="password2">
  <input type="text" name="password3">
  <input type="text" name="password4">
  <input type="text" name="password5">
  <input type="text" name="password6">
  <input type="text" name="password7">
  <input type="text" name="password8">
  <input type="submit">
</form>

<script>
  myform.onsubmit=function(){

    // 提取form内包含的表单内容
    var formdata=new FormData(this);

    fetch("http://39.96.88.57/login",{
      method:"POST",
      body:formdata
    })
      .then(r=>r.json())
      .then(function(res){
      console.log(res);
    })

    return false;
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# base64转file

工具

function base64toFile(dataurl, filename) {
  let arr = dataurl.split(",");
  let mime = arr[0].match(/:(.*?);/)[1];
  let suffix = mime.split("/")[1];
  let bstr = atob(arr[1]);
  let n = bstr.length;
  let u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], `${filename}.${suffix}`, {
    type: mime
  });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//调用方法即可完成转换
var myfile = base64toFile(base64, "名字");
1
2

# file转base64

使用 readAsDataURL

myfile.onchange=function(){
  // 创建文件读取器对象
  var reader=new FileReader();
  reader.readAsDataURL(this.files[0]);
  // 读取成功
  reader.onload=function(){
    console.log(reader.result);
  }
}
1
2
3
4
5
6
7
8
9

# 图片裁剪

https://gitee.com/mirrors/simplecrop/tree/master

# ES6

# 继承

class Animal{
  constructor(voc){
    this.voc=voc;
    this.type="动物"
  }
  speak(a){
    alert(a);
  }
}
// 继承
class Person extends Animal{
  constructor(){
    super("哈哈哈");//对用Animal的构造函数 私有的属性
    this.type="人"
  }
}
let p=new Person();
// p.speak("hello");
console.log(p);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# es6新特性

find --- 查找第一个符合要求的元素

findIndex --- 查找第一个符合要求的下标

let res = list.find(item => {
  // item指数组中单个元素
  return item.title == "苹果"
})

let index = list.findIndex(item => item.title == "西瓜")
1
2
3
4
5
6

Array.from 把伪数组转化为真正的数组 节点集合 arguments

let btns=document.getElementsByTagName("button");

btns=Array.from(btns);
btns.shift();
console.log(btns);
1
2
3
4
5

includes --- 是否包含某些元素

let arr = [1, 2, 3]
console.log(arr.includes(2)) // true
1
2

at --- 索引负值

let arr2 = [1, 2, 3, 4, 5]
console.log(arr2.at(0)) // 1
console.log(arr2.at(-1)) // 5
1
2
3

Object.assign --- 合并对象

function math(obj) {
  let moren = {
    x: 1,
    y: 2,
    z: 3
  }
  obj = Object.assign(moren, obj) // 值相同 obj会把moren覆盖
  console.log(obj.x + obj.y + obj.z)
}
math({x: 10}); // 15
math(); // 6
1
2
3
4
5
6
7
8
9
10
11

Symbol --- 凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突

function Person(name, age) {
  let n = Symbol();
  let a = Symbol();
  return {
    [n]: name,
    [a]: age
  }
}
let p1 = Person("张三", 20);
console.log(p1); // {Symbol(): '张三', Symbol(): 20}
1
2
3
4
5
6
7
8
9
10

Proxy --- 对象 代理/劫持

操作对象的时候 都要经过这一层

<h1 id="title">0</h1>

let obj = {
  num: 0
}
let res = new Proxy(obj, {
  // target => o
	// key num
  // val 0
  set(target, key, val) { // 当设置的对象属性时会执行此函数
    if (key == "num") {
      title.innerHTML = val;
    }
    target[key] = val;
    return true;
  },
  get(target, key) { // 当获取对象时执行的函数 返回值是响应的结果
    return target[key];
  }
})
res.num = 100 // obj.num / res.num => 100
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# Set

set --- 成员的值都是唯一的,没有重复的值。

Set 结构的实例有以下属性。

  • Set.prototype.constructor:构造函数,默认就是Set函数。
  • Set.prototype.size:返回Set实例的成员总数。

Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。

  • Set.prototype.add(value):添加某个值,返回 Set 结构本身。
  • Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。
  • Set.prototype.clear():清除所有成员,没有返回值。
//去重
const arr = [1,2,3,4,5,5,5,5]
console.log(new Set(arr)); // 1, 2, 3, 4, 5
1
2
3

Array.from方法可以将 Set 结构转为数组。

这就提供了去除数组重复成员的另一种方法。

function dedupe(array) {
  return Array.from(new Set(array));
}
dedupe([1, 1, 2, 3]) // [1, 2, 3]
1
2
3
4

Set 结构的实例有四个遍历方法,可以用于遍历成员。

  • Set.prototype.keys():返回键名的遍历器
  • Set.prototype.values():返回键值的遍历器
  • Set.prototype.entries():返回键值对的遍历器
  • Set.prototype.forEach():使用回调函数遍历每个成员
let set = new Set(['red', 'green', 'blue']);

for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

let set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9
Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# promise

应用

function getData(url) {
  return fetch(url).then(r => r.json());
}
const url1 = "http://39.96.88.57:9090/api/www/artist/artistInfo?category=0&pn=1&rn=100";
const url2 = "http://39.96.88.57:9090/api/www/artist/artistMusic?artistid=336&pn=1&rn=30";
getData(url1)
  .then(res => {
  console.log(res);
  return getData(url2)
}).then(res => {
  console.log(res);
})
1
2
3
4
5
6
7
8
9
10
11
12

三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)

function setTime(t) {
  let p = new Promise((resolve, reject) => {
    setTimeout(() => {
      		成功时        失败时
      x ? resolve(x) : reject()
    }, t)
  })
  return p;
}

setTime(1000)
  .then(res => {
  x = 0;
  console.log('第一次', x);
  return setTime(1000)
})
  .catch(err => {
  console.log('第一次错误');
  return setTime(1000)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

异步加载图片封装

function loadImg(url) {
  return new Promise(resolve => {
    let img = new Image();
    img.src = url;
    img.onload = function () {
      resolve(img);
    }
  })
}

loadImg("https://imgcps.jd.com/ling4/100018640796/6auY5oCn6IO95omL5py657K-6YCJ/54iG5qy-55u06ZmN/p-5bd8253082acdd181d02f9f2/e0a9430a/cr/s/q.jpg")
  .then(img => {
  console.log("加载完毕")
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# all

function setTime(t,page){
  let p=new Promise(resolve=>{
    setTimeout(()=>{
      resolve("第"+page+"页内容");
    },t)
  })
  return p;
}


let p1=setTime(2000,10);
let p2=setTime(1000,5);

Promise.all([p1,p2])
  .then(([r1,r2])=>{//p1\p2全部resolve之后
  console.log(r1,r2);
})
  .catch(err=>{//任意一个reject 就会触发catch
  console.log("失败")
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Promise.all([
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        name: 'why',
        age: 18
      })
    }, 2000)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        name: 'kobe',
        age: 19
      })
    }, 1000)
  })
]).then(results => {
  console.log(results);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# race

// 碰到第一个resolve就结束 竞速
Promise.race([p1,p2])
  .then(res=>{
  console.log(res);
})
  .catch(err=>{//任意一个reject 就会触发catch
  console.log("失败")
})
1
2
3
4
5
6
7
8

# finally()

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
1
2
3
4

finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。

# 异步函数

function setTime(t){
  let p=new Promise(resolve=>{
    setTimeout(()=>{
      var x=10;
      resolve(x);
    },t)
  })
  return p;
}

btn.onclick=function(){
  ;(async function(){
    // 等后面的promise实例resolve
    let res=await setTime(1000);
    console.log(res);
    let res2=await setTime(1000);
    console.log(res2);
  }())
  this.style.color="red";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
async function getData(url) {
  let res = await fetch(url).then(r => r.json())
  console.log(res);
}
1
2
3
4
Last Updated: 9/14/2022, 4:07:49 PM