0%

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

到了新公司发现同事用的都是VSCode,而VSCode的格式化代码与WebStorm的不一致。

因为前后端都做,用惯了JetBrains全家桶,导致不太适应VSCode,最后所以打算调整一下代码的格式化,继续用webstorm开发。

  • 自闭合的标签,闭合前补充空格

Settings > Editor > Code Style > HTML > Other(Tab页) > 勾选 in empty tag

  • 句尾冒号分割,永远使用单引号,多行保留最后一项的逗号

Settings > Editor > Code Style > JavaScript > Punctuation(Tab页) >

1
2
3
use semicolon to terminate statement always
use single quotes always
Trailing comma Add when multiline
  • 使用空格代替tab,tab展示为两个空格,代码缩进为两个空格

Settings > Editor > Code Style > JavaScript > Tabs and Indents(Tab页) > 不勾选 Use Tab character

1
2
3
Tab Size: 2
Indent: 2
Continuation indent: 2
  • 对象花括号和中间键值填充空格(包括ES6 的import export)

Settings > Editor > Code Style > JavaScript > Spaces(Tab页) > Within > 勾选Object literal braces 和 ES6 import/export braces
————————————————
版权声明:本文为CSDN博主「咕了个咕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Azhuzhu_chaste/article/details/106636056

内联样式优先与Style标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
h1 {
color: red;
}
</style>
</head>
<body>
<h1 style="color: blue;">CSS测试</h1>
</body>
</html>

后声明的优先于先声明的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>style与link</title>
<style>
h1 {
color: red;
}
</style>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h1>CSS测试</h1>
</body>
</html>

style.css

1
h1{color: blue;}

Style标签优先于link标签

style标签在link标签后面的前提下,其实也是先后顺序的比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>style与link</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<style>
h1 {
color: red;
}
</style>
<h1>CSS测试</h1>
</body>
</html>

style.css

1
h1{color: blue;}

id优先与class

即使class在id之后声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>class与id</title>
<style>
#text {
color: red;
}
.text {
color: blue;
}
</style>
</head>
<body>
<h1 class="text" id="text">CSS测试</h1>
</body>

</html>

选择器选择器越详细优先级越高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>选择器优先级</title>
<style>
.parent h1 {
color: red;
}
h1 {
color: blue;
}
</style>
</head>
<body>
<div class="parent">
<h1 id="text">CSS测试</h1>
</div>
</body>
</html>

创建数组

1
2

let array = ['a', 'b']

访问数组

1
2
3
4

let a=array[0]

//a

遍历数组

1
2
3
4

array.forEach(function(item, index, array) {
console.log(item, index)
})

添加元素到数组的末尾

1
2

array.push('c')

删除数组最后一个元素

1
array.pop();

删除数组第一个元素

1
array.shift()

添加元素到数组的第一位

1
array.unshift('1')

获取数组的长度

1
let length=array.length;

获取某个元素在数组中的索引

1
2

let index=array.indexOf('a')

通过索引删除某个元素

1
2

array.splice(1, 1)

安装依赖

1
2
3
4
5
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>

安装浏览器驱动

下载安装

选择自己喜欢的浏览器,本文使用Edge

打开一个网页

1
2
3
4
5

System.setProperty("webdriver.edge.driver", "D:\\edgedriver_win32\\MicrosoftWebDriver.exe"); //上面下载的浏览器驱动
WebDriver driver = new EdgeDriver();
driver.get("https://www.baidu.com/");

定位元素

1
2
3
4
5
6
7

driver.findElement(By.id("kw")).sendKeys("java"); //输入内容

driver.findElement(By.id("su")).click(); //点击按钮

List<WebElement> muchoCheese = driver.findElements(By.cssSelector("#cheese li"));//获取多个与元素

获取页面cookie

1
2
3
4
5
6
Set<Cookie> cookies = driver.manage().getCookies();
String cookieStr = "";
for (Cookie cookie : cookies) {
cookieStr+= cookie.getValue();

}

浏览器加载扩展

1
2
3
4
5
6
7
8

File plugPath = new File("E:\\tsy\\tsy-tool.crx");

//创建options对象
ChromeOptions options = new ChromeOptions();
options.addExtensions(plugPath);
WebDriver driver = new ChromeDriver(options); //这里使用的是chrome

Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

Promise的特点

  • 对象的状态不受外界影响

    Promise对象代表一个异步操作,有三种状态,pendingfulfilledrejected,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态。

  • 一旦状态改变,就不会在变,任何时候都可以得到这个结果。
    Promise对象的状态改变只有两种可能,从pending变为fulfilled,从pending变为rejected。只要这两种情况发生,状态就凝固了,不会在改变,会一直保持这个结果,这时就成为resolved。如果改变已经发生了,你在对Promise对象添加回调函数,也会立即得到这个结果。

  • 也有一些缺点

    无法取消Promise,一旦创建对象就会立即执行,无法中途取消。

    如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。

    当处于pending状态时,无法得到当前进展到哪一阶段

    参考阮一峰老师的ECMAScript 6 入门

语法

1
2
3
4
5
6
7
8
9
10

const promise = new Promise(function(resolve, reject) {
// ... some code

if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});

Promise构造函数接受一个函数做为参数,该函数的两个参数分别是resolvereject。它们是两个函数,由JavaScript 引擎提供

resolve函数的作用是,将Promise对象的状态从pending 改为fulfilled,并且将异步结果传递出去。

reject函数的作用是,将Promise对象的状态从pending改为rejected,并将异步异常传递出去

then 方法

Promise对象创建完成后,可以用then方法分别指定resolverejected状态的回调函数

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
function ajaxGet(url) {
return new Promise((resolve, reject) => {
if (url !== "api") {
reject(url + "请求失败");
}

setTimeout(function () {
resolve(url + "请求完成");
}, 1000);
});
}
ajaxGet("api").then(
(data) => {
console.log(data);
},
(error) => {
console.error(error);
}
);

ajaxGet("api11").then(
(data) => {
console.log(data);
},
(error) => {
console.error(error);
}
);


运行代码

上面的代码中使用Promise对象模拟了一个从后台服务取数据的过程,ajaxGet方法只有一个简单的逻辑判断,如果传如的参数是api那么会在一秒之后返回成功,否则,立即返回失败。

上面代码的返回结果是

1
2
//"api11请求失败"  
//"api请求完成"

Promise对象创建后会立即执行,所以先输出第二个方法的返回值,此时第一个还在等待状态变成完成

catch 方法

Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

如果异步操作发生了异常,状态变成了rejected,就会调用catch方法指定的函数,处理这个异常。如果then方法指定的回调函数中发生了异常,也会被catch方法捕获

1
2
3
4
5
6
7
8
9
 ajaxGet("api11").then(
(data) => {
console.log(data);
}
).catch(error=>{
console.error(error)

});

运行代码

1
2
3
4
5
6
7
8
9
10
11

ajaxGet("api").then(
(data) => {
console.log(data);
throw 'error!';
}
).catch(error=>{
console.error(error) //then方法中的异常也会捕捉到

});

运行代码

finally 方法

finally方法是不管Promise对象最后状态如何,都会执行的操作。和try catch中的finally方法是一样的

下面是一个例子,最后使用finally方法输出一段内容

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
 
ajaxGet("api").then(
(data) => {
console.log(data);
},
(error) => {
console.error(error);
}
).finally(()=>{
console.log('不管成不成功,我都会输出')
});

ajaxGet("api11").then(
(data) => {
console.log(data);
},
(error) => {
console.error(error);
}
).finally(()=>{

console.log('不管成不成功,我都会输出')
});

//"api11请求失败"
//"不管成不成功,我都会输出"
//"api请求完成"
//"不管成不成功,我都会输出"

运行代码

finally的回调函数是没有参数的,无法得知Promise对象的结果是什么,这也表明不管最后的返回结果是什么,它都会执行

Web Api 的概念

浏览器提供了一些操作浏览器功能与页面元素的API,本次整理了一些常用操作页面元素的Api

document.querySelector()

该方法会返回文档中与指定选择器或选择器组匹配的第一个页面元素。如果找不到匹配项,则返回null

语法

1
let element = document.querySelector(selectors);

参数

  • selectors

    该字符串必须是有效的CSS选择器字符串

返回值

文档中与指定的一组CSS选择器匹配的第一个页面元素。如果没有匹配到,则返回null

实例

实例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="first">
<span class="text">1</span>
<span class="text">2</span>
<span class="text">3</span>
<span class="text">4</span>
</div>
</body>
</html>

以这个页面为基础,比如我想获取第一个classtext的内容,写法如下

1
2
let element=document.querySelector('.text').textContent;
console.log(element); //1

运行代码

按照预期,输出的内容是1,是我想要的结果

页面中有多个classtest的元素,但是精准的返回了我们要想的1,是因为该方法只会匹配页面中查到的第一个元素

实例2

还用上面的页面为例,如果我想获取到页面中第二个classtext的元素该怎么写呢。

1
2
3
let element=document.querySelector('span.text:nth-child(2)').textContent;
console.log(element); //2

运行代码

该方法支持复杂选择器

实例3

页面元素中id应该是唯一的,但是在实际开发中很有可能会出现一个页面中有多个相同id的元素,那这个时候使用这个方法会得到什么呢。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<span id="first">1</span>
<span id="first">2</span>
</body>
</html>

页面中有两个idfirst的元素,我们执行该方法看一下效果

1
2
let element=document.querySelector('#first').textContent;
console.log(element); //1

返回结果是1
运行代码

就算页面中有多个id重复的元素,也是返回第一个元素

document.querySelectorAll()

返回与指定的选择器组匹配的文档中的元素列表。

语法

1
let elementList = document.querySelectorAll(selectors);

参数

  • selectors

这个字符串必须是一个合法的 CSS选择器字符串

如果selectors参数中包含 CSS伪元素,则返回的列表始终为空。

返回值

一个静态 NodeList,包含一个与至少一个指定选择器匹配的元素的Element对象,或者在没有匹配的情况下为空NodeList

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="first">
<span class="text">1</span>
<span class="text">2</span>
<span class="text">3</span>
<span class="text">4</span>
</div>
</body>
</html>

1
2
3

let elementList = document.querySelectorAll('.text');
console.log(elementList) // [object NodeList] (4)

document.images

返回当前文档中所有 image 元素的集合.

语法

1
let imageCollection = document.images;

返回值

HTMLImageElement集合,当前页面的所有图片元素

实例

1
2
3
4
5
6
let ilist = document.images;
for(var i = 0; i < ilist.length; i++) {
if(ilist[i].src == "logo.png") {

}
}

Proxy 意思为代理,即在访问对象之前建立一道拦截,任何访问该对象的操作之前都会通过这道拦截

Proxy可以拦截什么

  • getPrototypeOf()

  • setPrototypeOf()

  • isExtensible()

  • preventExtensions()

  • getOwnPropertyDescriptor()

  • defineProperty()

  • has()

  • get()

  • set()

  • deleteProperty()

  • ownKeys()

  • apply()

  • construct()

实例

Proxy 语法

1
let proxy = new Proxy(target, handler);

这就是Proxy的使用方法,所有的用法都是上面的方法,不同的是handler里面拦截的设置

new Proxy()表示生成一个Proxy实例

target表示要拦截的目标对象

handler是一个对象,用来定制拦截方法

想要handler里的拦截方法生效,后续所有操作必须使用Proxy的实例

get

get方法在日常开发中应该是使用最多的方法了,先看一下在不使用Proxy时候的场景

1
2
3
4
5
let user = {
name: "张三",
};
console.log(user.name); //张三
console.log(user.age); //undefined

上面代码中,使用let定义了一个对象,并且有一个name属性

然后分别打印出nameage属性,结果很明显,age属性未定义会输出undefined

但是在实际项目中我们是不希望返回undefined这种值给页面的,下面我们就看一下怎么使用Proxy解决这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let handler = {
//定义了get方法的拦截器
get: function (target, key) {
//target:要拦截的对象
//key: 修改的属性
if(target.hasOwnProperty(key)){
if(key=='name'){
return "法外狂徒-张三"
}
}
return "18"
}
};
let obj = {
name: "张三"
};
let user = new Proxy(obj, handler);

//注意,这里的user不是上个示例的user对象了,而是Proxy的实例
console.log(user.name); //法外狂徒-张三

console.log(user.age); //18

运行代码

使用了Proxy之后,发现和之前什么都不一样了,这是因为我们设置了get方法的拦截,当获取name属性的时候,我们返回一个固定的值,否则就返回年龄18。

这里是不太严谨的,实际项目中不可能只有两个字段的,这里只是为了演示

想要handler里的拦截方法生效,后续所有操作必须使用Proxy的实例

这个时候可以验证一下这句话,我们不使用Proxy实例,看看会怎么样

运行代码

set

在实际项目中,我们会经常进行修改某个对象的属性,有时候在一些特殊的场景下需要对对象修改的新属性进行判断,看是否符合当前的业务场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let user = new Proxy(
{
age: 18
},
{
set: function (target, key, value) {
if (value > 140) {
throw "你要成仙了!";
}
target[key]=value
}
}
);
user.age = 20;
console.log(user.age)//20
user.age=200
//Uncaught 你要成仙了!

运行代码

当我们修改一个人的年龄大于140,就会触发异常

construct

construct方法用于拦截new操作符,为了使new操作符在生成的Proxy对象上生效,用于初始化代理的目标对象自身必须具有Construct内部方法

示例

1
2
3
4
5
6
7
8
let proxy = new Proxy(1, {
construct(target, args) {
console.log(target);
return new target(...args);
}
});

//Uncaught TypeError: Cannot create proxy with a non-object as target or handler

运行代码

1
2
3
4
5
6
7
8
9
10

let proxy = new Proxy(function () {}, {
construct(target, args) {
console.log(args);
return 1;
}
});

let obj = new proxy();
//Uncaught TypeError: 'construct' on proxy: trap returned non-object ('1')

运行代码

上面是两个错误的示例,下面写一个正确的写法

1
2
3
4
5
6
7
8
var p = new Proxy(function() {}, {
construct: function(target, argumentsList, newTarget) {
console.log('called: ' + argumentsList.join(', '));
return { value: argumentsList[0] * 10 };
}
});
console.log(new p(1).value); // "called: 1"
// 10

运行代码

通过以上代码得出结论

  • 要代理的对象必须具有Construct方法
  • 必须返回一个对象

其他

其他方法下一章继续

Img 标签在不同设备上显示不同的图片

1
2
3
4
5
<picture>
<source media="(min-width:768px)" srcset="med_flag.jpg" />
<source media="(min-width:495px)" srcset="small_flower.jpg" />
<img src="high_flag.jpg" alt="Flags" style="width:auto;" />
</picture>

快速搜索匹配项

1
2
3
4
5
6
7
8
9
10
<label for="country">Choose your country from the list:</label>
<input list="countries" name="country" id="country" />

<datalist id="countries">
<option value="UK"></option>
<option value="Germany"></option>
<option value="USA"></option>
<option value="Japan"></option>
<option value="India"></option>
</datalist>

Html 标签变量

1
2
3
4
5
6
7
8
<head>
<base href="https://www.twitter.com/" target="_blank" />
</head>

<body>
<img src="elonmusk" alt="Elon Musk" />
<a href="BillGates">Bill Gate</a>
</body>

img标签的完整地址是https://www.twitter.com/elonmusk

a标签同样

图片懒加载

1
<img src="image.png" loading="lazy" alt="…" width="200" height="200" />

使用 CSS 固定 header 与 footer

1
2
3
4
5
<div id="container">
<header>header</header>

<footer>footer</footer>
</div>
1
2
3
4
5
6
7
8
header {
position: sticky;
top: 0;
}
footer {
position: sticky;
bottom: 0;
}

使用 Promise 实现任务进度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const loadingBar = document.getElementById("loadingBar");

async function task() {
return new Promise((res) => {
setTimeout(res, Math.random() * 5000);
});
}

function loadingBarStatus(current, max) {
loadingBar.textContent = `Loading ${current} of ${max}`;
}

(async () => {
let current = 1;
const promises = new Array(100)
.fill(0)
.map(() => task().then(() => loadingBarStatus(current++, 100)));

await Promise.all(promises);
loadingBar.textContent = `Loading Finished`;
})();