前端备忘
好记性不如烂笔头!
HTML5
HTML5表单的特点:
HTML5 表单增加了许多内置的控件和控件属性
XHTML 中需要放在 form 之中的诸如 input/button/select/textarea 等标签元素,在 HTML 5 中完全可以放在页面任何位置,并通过新增的 form 属性指向元素所属表单的 ID 值,即可关联起来。
HTML5新增的控件类型:
email输入类型:
1 | <input type="email" name="email" /> |
要求输入格式正确的 email 地址,否则浏览器不允许提交,同时会提示错误信息
url输入类型:
1 | <input type="url" /> |
要求输入格式正确的 URL 地址,Opera 中会自动在开始处添加 http://
日期时间相关输入类型:
1 | <input type="date" /> |
目前 MS 只有 Opera/Chrome 新版本支持,且展示效果也不一样
number输入类型:
1 | <input type="number" /> |
要求输入格式正确的数字
range类型:
1 | <input type="range" step="2" min="0" max="10" value="2" /> |
显示一个可拖动的滑块条,通过设定 max/min/step 值限定拖动范围,拖动时会反馈给value一个值
search输入类型:
1 | <input type="search" /> |
输入一个搜索关键字,通过 results=s 可显示一个搜索小图标
tel输入类型:
1 | <input type="tel" /> |
要求输入一个电话号码,但实际上并没有特殊的验证,与 text 类型没什么区别
color输入类型:
1 | <input type="color" /> |
可让用户通过颜色选择器选择一个颜色值,并反馈到value中
HTML5新增的表单属性:
placeholder属性:
1 | <input type="text" placeholder="点击我会清除" /> |
实现点击清除表单初始值,MS 除了 Firefox,其他标 准浏览器都能很好的支持
require/pattern属性:
1 | <input type="text" name="require" required="" /> |
表单验证属性require 类型时,若输入值为空,则拒绝提交并出现提示,注意在 Opera 中必须指定 name 值,否则无效果。
autofocus属性:
1 | <input type="text" autofocus="true" /> |
默认聚焦属性,可在页面加载时聚焦到一个表单控件,类似于 JS 的 focus()
list属性:
1 | <input type="text" list="ilist"> |
需要与datalist属性共用,datalist是对选择框的记忆,而list属性可以为选择框自定义记忆的内容
max/min/step属性:
1 | <input type="range" max="100" min="1" step="20" /> |
限制值的输入范围,以及值的输入渐进程度,比如可在 number 设定输入最大值最小值,或在 range 中设定拖动阶梯
autocomplete属性:
1 | <input type="text" autocomplete="on" /> |
此属性是为表单提供自动完成功能,如果该属性为打开状态可很好地自动完成,一般来说,此属性必须启动浏览器的自动完成功能
novalidate属性:
1 | <form action="demo_form.asp" method="get" novalidate="true"> |
在提交表单时不应该验证 form 或 input 域
data属性:
1 | <select data="http://XX.com/"></select> |
HTML5 支持 data 属性,为 select 控件外联数据源,可以在 select 下拉别表动态的添加来自数据库的各组选项, 比如说国家、省市列表等等。
XML Submission编码格式:
常见的是 Web Form 的编码格式是 application/x-www-form-urlencoded。 这种格式将数据送到服务器端,可以方便的存取。HTML5 提供一种新的数据格式:XML Submission,即 application/x-www-form+xml。简单的举例说,服务器端将直接接收到 XML 形式的表单数据。
目前任何表单元素都有八种可能的验证约束条件:
| 名称 | 用途 | 用法 |
|---|---|---|
| valueMissing | 确保控件中的值已填写 | 将required属性设为true,<input type="text"required="required"/> |
| typeMismatch | 确保控件值与预期类型相匹配 | <input type="email"/> |
| patternMismatch | 根据pattern的正则表达式判断输入是否为合法格式 | <input type="text" pattern="[0-9]{12}"/> |
| toolong | 避免输入过多字符 | 设置maxLength,<textarea id="notes" name="notes" maxLength="100"></textarea> |
| rangeUnderflow | 限制数值控件的最小值 | 设置min,<input type="number" min="0" value="20"/> |
| rangeOverflow | 限制数值控件的最大值 | 设置max,<input type="number" max="100" value="20"/> |
| stepMismatch | 确保输入值符合min,max,step的设置 | 设置max min step,<input type="number" min="0" max="100" step="10" value="20"/> |
| customError | 处理应用代码明确设置能计算产生错误 | 例如验证两次输入的密码是否一致,document.getElementById("元素id").setCustomValidity("提示的错误信息") |
CSS3
文字与字体相关样式
text-shadow
用途: 基本的文本阴影效果
1 | h1 { |
Web Font与@font-face
用途: 指定名为”myFirstFont”的字体,并指定在哪里可以找到它的URL
1 | @font-face |
font-size-adjust
用途: 通过指定font-size-adjust属性,浏览器将调整字体大小,无论字体系列, 不同字体也能保持一样的大小(只有firefox支持)
1 | div |
背景边框相关新增属性
background-clip
用途: 规定背景的绘制区域
1 | div |
background-origin
用途: 内容框相对定位的背景图片(背景原点)
1 | div |
background-size
用途: 重设背景图片大小
1 | div |
background-break
用途: 控制背景在不同区域显示
(1)Background-break: continuous;
此属性是默认值,忽视区域之间的间隔空隙(给它们应用图片就好像把它们看成一个区域一样)
(2)Background-break: bounding-box;
重新考虑区域之间的间隔
(3)Background-break: each-box;
对每一个独立的标签区域进行背景的重新划分。
多个背景叠加
第一个图片是定位在元素最上面的背景,后面的背景图片依次在它下面显示
1 | background-image: url(top-image.jpg), url(middle-image.jpg), url(bottom-image.jpg); |
background-attachment
当background-attachment设置为scroll时,背景图片是不随内容滚条滚动的。现在,有了background-attachment:local,就可以做到让背景随元素内容滚动而滚动了
border-radius
用途: 为div加圆角
1 | div |
border-image
1 | #borderimg { |
布局相关
display新增属性
多行文本居中省略号
1 | 单行文本省略号 |
column多栏布局
默认没有分隔边框
- columns
使用形式:columns: 栏宽值 栏目数;
实际表现上,当总宽度大于等于“栏宽x栏目数”时,栏目数固定,栏宽可能会有所调整(变大)。
当总宽度小于“栏宽x栏目数”时,栏目数会减少(保证栏宽不小于设定的栏宽)。
- column-gap栏间隙
设定栏与栏之间的宽度值,默认是font-size大小(比如14px)
- column-rule
column-rule-width:设定线宽,比如1px,5px;
column-rule-style:设定线型,比如solid,dashed,dotted;
column-rule-color:设定线色,比如red, #ff9966, rgb(200,100,0)
column-rule:上述3个属性的综合属性。
column-rule:3px outset #ff00ff;
flex布局
弹性布局的主要属性设置包括如下几个:
- display: flex;
说明:设置盒子的显示模式为弹性盒模型,即该盒子成为了弹性盒模式的容器盒子。
flex-direction:
说明:设置弹性盒模式的子盒子的排列方式,有如下4个方式(4个属性值):
row:横向排列,
row-reverse:横向排列,但顺序反向
column:纵向排列
column-reverse:纵向排列,但顺序反响
flex-wrap:
说明:设置弹性盒模式的子盒子超出时的换行特性,常用属性值有:
nowrap:不换行,尽量在一行显示,这是默认值。
此时有可能会超出父盒子(当子盒子有最小宽度设置时)。
wrap:自动换行。
wrap-reverse:换行,但反向显示(即其实显示到上一行去了)justify-content:
说明:设置子盒子的主轴方向的一行中的排布方式。
常用属性值有:
flex-start:子盒子从所设定的起始位置开始排列出来,空隙留后面;
flex-end:子盒子从所设定的终止位置开始排列出来,空隙留前面;
center:子盒子完全从居中的位置开始排列出来,空隙留两边;
space-between:子盒子两边紧靠父盒子,空隙留在相互的中间且均等;
space-around:子盒子均衡布置,分布给每个盒子的空隙都一样。
- align-content:
说明:设置子盒子在辅轴方向的排布方式,大于一行且辅轴有多余空间时时才有效。
常用的属性值有:
flex-start:子盒子从所设定的起始位置开始排列出来,空隙留后面;
flex-end:子盒子从所设定的终止位置开始排列出来,空隙留前面;
center:子盒子完全从居中的位置开始排列出来,空隙留两边;
space-between:子盒子两边仅靠父盒子,空隙留在相互的中间;
space-around:子盒子均衡布置,空隙均衡出现;
针对多行容器使用
- align-items:
说明:设置子盒子在当前行中辅轴方向的对齐方式。
flex-start:子盒子定位于所设定的起始位置,空隙留后面;
flex-end:子盒子定位于设定的终止位置,空隙留前面;
center:子盒子定位于居中的位置,空隙留两边;
baseline:子盒子定位于基准位置;
stretch:子盒子进行拉伸(充满纵轴);
针对单行容器和多行容器使用
参考链接: https://blog.csdn.net/sinat_27088253/article/details/51532992
flex旧布局
flex布局分为旧版本dispaly: box;,过渡版本dispaly: flex box;,以及现在的标准版本display: flex;。所以如果你只是写新版本的语法形式,是肯定存在兼容性问题的。
1 | .box{ |
Media Queries相关样式
Media Queries直译过来就是“媒体查询”
1 | <link href="css/reset.css" rel="stylesheet" type="text/css" media="screen" /> |
“media”就是用来指定特定的媒体类型,在HTML4和CSS2中充许你使用“media”来指定特定的媒体类型,如屏幕(screen)和打印(print)的样式表,当然还有其他的,比如说“TV”,“handheld”等,其中“all”表示的是支持所有媒体介质
简单的实例:
1 | <link rel="stylesheet" media="screen and (max-width: 600px)" href="small.css" /> |
ECMAScript6
是javascript的版本
Babel是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码
块级绑定(let, const)
let
看个例子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
28var name = 'zach'
while (true) {
var name = 'obama'
console.log(name) //obama
break
}
console.log(name) //obama
ES5只有全局作用域和函数作用域,没有块级作用域, 会出现内层变量覆盖外层变量的情况
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
如果用let
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
const
const也用来声明变量,但是声明的是常量。一旦声明,常量的值就不能改变。const有一个很好的应用场景,就是当我们引用第三方库的时声明的变量,用const来声明可以避免未来不小心重命名而导致出现bug
const monent = require('moment')
字符串与正则表达式的新增能力
字符串新增方法
模板字符串
- 字符串插值
1 | let first = 'Jane'; |
- 多行模板字符串
1 | let multiLine = ` |
- 原始字符串, 反斜线不再是特殊字符
String.raw: 用于产生原始字符串(反斜杠不会被转义)
1 | let raw = String.raw`Not a newline: \n`; |
字符串迭代
1 | 方法1: |
Unicode和码位
- String.fromCodePoint(…codePoints : number[]) : string
将数字值码位转换成字符串。
1 | String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y' |
- String.prototype.codePointAt(pos) : number
返回码位开始位置的数字值(会包含一个或两个JavaScript的字符)。
1 | let str = 'x\uD83D\uDE80y'; |
- normalize()
可以提供Unicode的标准化形式。接收一个可选的字符串参数,指明用以下的某种Unicode标准化形式。str.normalize(可选参数)
NFC:以标准等价方式分解,然后以标准等价方式重组。默认选项。
NFD:以标准等价方式分解。
NFKC:以兼容等价方式分解。
NFKD:以兼容等价方式分解,然后以标准等价方式重组。
在对 比字 / 排序 符串之前,一定要先把它们标准化为同一种形式。
查找字符串
String.prototype.startsWith(searchString, position=0) : boolean
检查一个字符串是否以另一个字符串(searchString)开始。位置(position)指定从哪开始执行检查。String.prototype.endsWith(searchString, endPosition=searchString.length) : boolean
检查一个字符串是否以另一个字符串(searchString)结尾。结束位置(endPosition)指定在哪执行结尾检查。String.prototype.includes(searchString, position=0) : boolean
检查一个字符字符串是否包含另一个字符串(searchString)。位置(position)指定从哪开始检查。
repeat重复字符串
String.prototype.repeat(count)
当参数小于零时会报错
replace替换
replace可接受两个参数,第二个参数如果不选择,则会将目标字符串替换为undefind。第一个参数可以为字符串,也可以为正则对象。第二个参数可以是字符串,也可以是一个有返回值的函数。
1 | var str="hello world!"; |
indexOf和search的区别
search是强制匹配正则, indexOf是匹配字符串
1 | var str="123456789.abcde"; |
match和search的区别
match 返回值是数组,返回数组是正则捕获的字符串
search 返回值是Number,返回正则匹配到的字符串起始位置的偏移量(下标) 如果未匹配到返回 -1
slice切片
String.prototype.slice(star,end);两个参数结束参数为可选参数,截取的字符串不包括结束参数的下标。结束参数可以为负数,表示从字符串末位截取。但开始参数在结束参数后面则返回一个空字符串。
1 | var str="hello world"; |
padStart头部补全
1 | let str = '1234'.padStart(8,'0'); |
padEnd尾部补全
1 | let str = 'abc'.padEnd(5); |
match匹配
match参数有两种形式,可以是字符串也可以是正则对象。返回查询到的字符串本身,如果没有规定查询的字符串,则返回null。
加入正则表达式中没有全局匹配的话,返回一个匹配到的字符串,和子查询到的字符串组成的数组,该数组返回一个查询的
索引值。和被查询的字符串对象
1 | var str="hello world"; |
test测试
test是用来检测字符串是否匹配某一个正则表达式,如果匹配就会返回true,反之则返回false
1 | /\d+/.test("123") ; //true |
参考链接
https://www.cnblogs.com/chairs/p/6985597.html
正则表达式
1 | //1、使用字面量来创建表达式 |
参考链接: https://blog.csdn.net/TING_april/article/details/117087246
()、[]、{} 的区别
| 修饰符 | 描述 | 举例 |
|---|---|---|
| () | 作用是提取匹配的字符串。表达式中有几个()就会得到几个相应的匹配字符串。 | 比如 (\s+) 表示连续空格的字符串 |
| [] | 定义匹配的字符范围。 | 比如 [a-zA-Z0-9] 表示字符文本要匹配英文字符和数字 |
| {} | 一般用来表示匹配的长度。 | 比如 \d{3} 表示匹配三个空格,\d[1,3]表示匹配1~3个空格。 |
^ 和 $
| 修饰符 | 描述 | 举例 |
|---|---|---|
| ^ | 匹配一个字符串的开头 | 比如 (^a) 就是匹配以字母a开头的字符串 |
| $ | 匹配一个字符串的结尾 | 比如 (b$) 就是匹配以字母b结尾的字符串 |
^ 还有另个一个作用就是取反,比如[^xyz] 表示匹配的字符串不包含xyz
需要注意的是:如果^出现在[]中一般表示取反,而出现在其他地方则是匹配字符串的开头
\d \s \w .
| 修饰符 | 描述 |
|---|---|
| \d | 匹配一个非负整数, 等价于 [0-9] |
| \s | 匹配一个空白字符 |
| \w | 匹配一个英文字母或数字,等价于[0-9a-zA-Z] |
| . | 匹配除换行符以外的任意字符,等价于[^\n] |
* + ?
| 修饰符 | 描述 | 举例 |
|---|---|---|
| * | 表示匹配前面元素0次或多次 | 比如 (\s*) 就是匹配0个或多个空格 |
| + | 表示匹配前面元素1次或多次 | 比如 (\d+) 就是匹配由至少1个整数组成的字符串 |
| ? | 相当于{0,1} 比如(\w?) 就是匹配最多由1个字母或数字组成的字符串 |
匹配模式
ES5中的修饰符有3个, 加上 ES6 的修饰符,一共5个:
| 修饰符 | 描述 | 描述 |
|---|---|---|
| m | multiline | 多行模式 |
| i | ignore case | 忽略大小写模式 |
| g | global match | 全局匹配模式 |
| u | unicode | unicode模式 |
| y | sticky | 粘连模式 |
函数
函数参数默认值
只有当函数的形参没有传入的时候,默认值才会生效,默认参数的值在函数内不会改变,即便修改arguments对象中的值,也不会改变默认参数的值
前置参数对后置可见,相反则不行
一般来说,建议将带默认值的函数参数放最后,不需要带默认值的函数参数放前面,这样在使用起来比较顺手
this问题
1 | says(say){ |
Function构造器
1 |
new.target属性
1 | function Person(name) { |
如果构造函数不是通过new命令调用的,new.target会返回undefined,因此这个属性可以用来确定构造函数是怎么调用的
扩展的对象功能
属性方法简写
1 | // 属性简写: |
Object.assign
1 | var target = { a: 1 }; |
Object.is
用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
- 两个值都是 undefined
- 两个值都是 null
– 两个值都是 true 或者都是 false - 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值指向同一个对象
- 两个值都是数字并且
- 都是正零 +0
- 都是负零 -0
- 都是 NaN
- 都是除零和 NaN 外的其它同一个数字
Object.setPrototypeOf
1 | Object.setPrototypeOf(a, b) |
更方便的数据访问
对象词法扩展
1 | function getCar(make, model, value) { |
对象和数组解构
解构可以避免在对象赋值时产生中间变量:
1 | function foo() { |
Symbol
ES6引入了一种新的原始数据类型Symbol,表示独一无二的ID。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。
Symbol类型的值不能与其他类型的值进行运算,会报错。
但是,Symbol类型的值可以转为字符串。
如果它被用作一个对象的属性,那么这个属性会是不可枚举的:
1 | var sym = Symbol('My symbol'); |
Set与Map
Map
Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象), 相当于java的map
1 | var m = new Map(); |
- size:返回成员总数。
- set(key, value):设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
- get(key):读取key对应的键值,如果找不到key,返回undefined。
- has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
- delete(key):删除某个键,返回true。如果删除失败,返回false。
- clear():清除所有成员,没有返回值。
- keys():返回键名的遍历器。
- values():返回键值的遍历器。
- entries():返回所有成员的遍历器。
WeakMap
WeakMap结构与Map结构基本类似,唯一的区别是它只接受对象作为键名(null除外),不接受原始类型的值作为键名,而且键名所指向的对象,不计入垃圾回收机制。
WeakMap与Map在API上的区别主要是两个:
一是没有遍历操作(即没有key()、values()和entries()方法),也没有size属性;
二是无法清空,即不支持clear方法。这与WeakMap的键不被计入引用、被垃圾回收机制忽略有关。
Set
类似java里的set\
1 | var items = new Set([1,2,3,4,5,5,5,5]); |
将set转化为数组
1 | var items = new Set([1, 2, 3, 4, 5]); |
WeakSet
WeakSet的成员只能是对象,而不能是其他类型的值。WeakSet没有size属性,没有办法遍历它的成员。
Array增强
Array.from()
任何有length属性的对象,都可以通过Array.from方法转为数组
Array.from()还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理。类似java8的stream
1 | let array = [0,1,2,3,4]; |
Array.of()
Array.of方法用于将一组值,转换为数组。
1 | Array.of(3, 11, 8) // [3,11,8] |
find
1 | // 找出值小于0的数 |
findIndex
用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。这两个方法都可以接受第二个参数,用来绑定回调函数的this对象。这两个方法都可以发现NaN,弥补了数组的IndexOf方法的不足。
1 | [NaN].indexOf(NaN) |
fill()
1 | fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去 |
entires()
1 | var arr = ["red", "blue", "green"] |
keys()
方法用于从数组创建一个包含数组键的可迭代对象。包含原始数组的键(key)
1 | let colors = ["red", "pink", "blue", "skyblue"]; |
values()
1 | var A = [ 'Ram', 'Z', 'k', 'geeksforgeeks' ]; |
keys() values() entries() 的区别
1 | let arr = [ {age:18, value:'张三'}, {age:19, value:'李四'}, {age:20, value:'王五'} ] |
foreach
forEach((element, index, array) => { /* … */ })
forEach() 本身是不支持的 continue 与 break 语句的,我们可以通过 some 和 every 来实现。
它的return是continue的意思
如果想要实现break效果, 那么可以使用ervery实现
1 | var arr = [1, 2, 3, 4, 5]; |
map()
map定义和方法 map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理的后值。
map()方法按照原始数组元素顺序依次处理元素。
注意: map不会对空数组进行检测, map不会改变原始数组
1 | var array1 = [1,4,9,16]; |
reduce()
reduce()方法为归并类方法,最常用的场景就是,计算数组中的每一项的总和。
有两个参数:
- 每次遍历都会调用的函数,而这个函数有接收四个参数,分别是:前一个值、当前项、项目的索引和数组对象,而这个函数的返回值,回传给下一次遍历时,执行的这个方法的第一个参数。
- 归并基础的初始值
1 | let arr = [1,2,3,4,5] |
filter()
filter()方法用于把Array中的某些元素过滤掉,然后返回剩下的未被过滤掉的元素。
- filter() 不会对空数组进行检测;
- filter() 不会改变原始数组。
1 | const school = [ |
参考资料: https://www.w3school.com.cn/jsref/jsref_obj_array.asp
ArrayBuffer
简单说,ArrayBuffer对象代表原始的二进制数据,TypedArray视图用来读写简单类型的二进制数据,DataView视图用来读写复杂类型的二进制数据。
ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(TypedArray视图和DataView视图)来读写,视图的作用是以指定格式解读二进制数据。
1 | var buf = new ArrayBuffer(32); |
上面代码对一段32字节的内存,建立DataView视图,然后以不带符号的8位整数格式,读取第一个元素,结果得到0,因为原始内存的ArrayBuffer对象,默认所有位都是0。
ArrayBuffer.prototype.slice()
ArrayBuffer实例有一个slice方法,允许将内存区域的一部分,拷贝生成一个新的ArrayBuffer对象。
1 | var buffer = new ArrayBuffer(8); |
ArrayBuffer.isView()
ArrayBuffer有一个静态方法isView,返回一个布尔值,表示参数是否为ArrayBuffer的视图实例。这个方法大致相当于判断参数,是否为TypedArray实例或DataView实例。
1 | var buffer = new ArrayBuffer(8); |
ArrayBuffer与字符串的互相转换
1 | // 假定字符串采用UTF-16编码(JavaScript的内部编码方式) |
DataView
如果一次读取两个或两个以上字节,就必须明确数据的存储方式,到底是小端字节序还是大端字节序。默认情况下,DataView的get方法使用大端字节序解读数据,如果需要使用小端字节序解读,必须在get方法的第二个参数指定true。
- getInt8:读取1个字节,返回一个8位整数。
- getUint8:读取1个字节,返回一个无符号的8位整数。
- getInt16:读取2个字节,返回一个16位整数。
- getUint16:读取2个字节,返回一个无符号的16位整数。
- getInt32:读取4个字节,返回一个32位整数。
- getUint32:读取4个字节,返回一个无符号的32位整数。
- getFloat32:读取4个字节,返回一个32位浮点数。
- getFloat64:读取8个字节,返回一个64位浮点数。
1 | // 小端字节序 |
参考资料: https://www.jianshu.com/p/5a841d6d7cc3
Promise与异步编程
所谓Promise,就是一个对象,用来传递异步操作的消息。
Promise对象有以下两个特点:
对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
Promise也有一些缺点:
- 首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
- 其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
- 第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
用法
1 | //创建promise |
- resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
- reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
then
then方法是定义在原型对象,作用是为Promise实例添加状态改变时的回调函数。then方法返回的是一个新的Promise实例, 所以then方法可以链式调用
1 | getJSON("/posts.json").then(function(json) { |
catch
如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误, 且异常带有冒泡性质, 会一直向后传递, 直到被捕获
1 | var promise = new Promise(function(resolve, reject) { |
Promise.all()
1 | // 生成一个Promise对象的数组 |
上面定义了6个promise, promise.all的状态是根据这6个promise的结果来定的, 只要有一个是rejected, 那么promise.all的状态就是rejected, 且传递的值是第一个rejected的实例返回值。如果都成功了, 则会将成功的返回值组成一个数组返回
Promise.race()
与Promise.all类似, 不同的是, 它只要是有一个promise状态改变, 那么它的状态就会跟着变, 并收到第一个改变的返回值
Promise.resolve()
1 | var p = Promise.resolve('Hello'); |
如果Promise.resolve方法的参数,不是具有then方法的对象(又称thenable对象),则返回一个新的Promise对象,且它的状态为Resolved。由于字符串Hello不属于异步操作(判断方法是它不是具有then方法的对象),返回Promise实例的状态从一生成就是Resolved,所以回调函数会立即执行。
Promise.reject()
与resolve方法类似, 会调用promise的reject方法
1 | var p = Promise.reject('出错了'); |
深浅拷贝
浅拷贝(Shallow Copy)
- 浅拷贝创建了一个新的对象,但是其中的属性仍然是原始对象中属性的引用。
- 修改拷贝对象中的属性会影响到原始对象,反之亦然。
- 对于嵌套对象(对象中包含对象),浅拷贝只会复制对象的引用,而不会递归复制嵌套对象。
常见的浅拷贝方法包括 Object.assign() 和展开运算符 (…)
深拷贝(Deep Copy)
- 深拷贝创建了一个全新的对象,并且将原始对象中的属性递归地复制到新对象中,包括嵌套的对象。
- 修改拷贝对象中的属性不会影响原始对象,二者互不关联。
- 深拷贝操作相对耗费资源,特别是对于大型嵌套对象或包含循环引用的对象。
常见的深拷贝方法包括 JSON.parse(JSON.stringify()) (不太推荐)、Lodash 的 _.cloneDeep()、递归方式(就是自己写循环) 、jquery的extend()方法进行深拷贝等。
1 | let obj = { a: { c: 2, d: [1, 3, 5], e: "哇哇哇" }, b: 4 }; |
VUE
VUE生命周期
总共分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后。
1、创建前/后:
1) beforeCreate阶段:vue实例的挂载元素el和数据对象data都为undefined,还未初始化。
说明:在当前阶段data、methods、computed以及watch上的数据和方法都不能被访问。
2) created阶段:vue实例的数据对象data有了,el还没有。
说明:可以做一些初始数据的获取,在当前阶段无法与Dom进行交互,如果非要想,可以通过vm.$nextTick来访问Dom。
2、载入前/后:
1) beforeMount阶段:vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点。
说明:当前阶段虚拟Dom已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updated。
2) mounted阶段:vue实例挂载完成,data.message成功渲染。
说明:在当前阶段,真实的Dom挂载完毕,数据完成双向绑定,可以访问到Dom节点,使用$refs属性对Dom进行操作。
3、更新前/后:
1) beforeUpdate阶段:响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器。
说明:可以在当前阶段进行更改数据,不会造成重渲染。
2) updated阶段:虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新,避免在这个钩子函数中操作数据,防止死循环。
说明:当前阶段组件Dom已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新。
4、销毁前/后:
1) beforeDestroy阶段:实例销毁前调用,实例还可以用,this能获取到实例,常用于销毁定时器,解绑事件。
说明:在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,比如清除计时器。
2) destroyed阶段:实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁。
说明:当前阶段组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁。
补充回答:
第一次页面加载时会触发:beforeCreate, created, beforeMount, mounted。
1) created 实例已经创建完成,因为它是最早触发的原因可以进行一些数据,资源的请求。(服务器渲染支持created方法)
2) mounted 实例已经挂载完成,可以进行一些DOM操作。(接口请求)
渲染过程:
父组件挂载完成一定是等子组件都挂载完成后,才算是父组件挂载完,所以父组件的mounted在子组件mouted之后
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
销毁过程:
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
VUE基本语法
什么是VUE.js
Vue.js是目前最后一个前端框架,React是最流行的一个前端框架(react除了开发网站,还可以开发手机App,Vue语法也是可以进行手机App,还需要借助 weex)
Vue.js是前端的主流框架之一,和angular、react.js一起,并成为前端三大主流框架
Node(后端)中的mvc与前端mvvm之间的区别
mvc是后端的分层开发概念
mvvm是前端视图层的概念,主要关注于视图层分离,也就是说:mvvm把前端的视图层,分为三部分:model,view,vm viewmodel
VUE简介
Vue是vue的实例,这个实例存在计算机中,主要干俩大事:1、绑定事件;2、dom检测
Vue全家桶包括:vuex、vue-router、vue-resource还有构建工具 vue-cli
指令式渲染
v-html:它可以加标签,它会解析成html
v-text:不能加标签,如果加了,它会当作字符串展示出来
插值表达式
v-text与插值表达式的区别
默认v-text没有闪烁的问题的,而插值表达式有闪烁问题
v-text 会覆盖元素中原本的内容,但是插值表达式只会替换自己的这个占位符,不会把整个元素的内容清空
v-html 与 v-text的区别
v-html会解析html格式
v-text与插值表达式会把内容当做文本来解析
v-html 和 v-text都会覆盖元素中原有的内容
v-cloak
能够解决 插值表达式闪烁的问题
1 | [v-cloak]{ |
v-if
后面的值如果是true节点就显示,false就隐藏
v-show
改变css中的display
v-if与v-show的区别
v-if是对节点的删除和添加,v-show是堆display属性值none和block的切换
共同点:都是动态显示DOM元素
不同点:
- v-if:
v-if 是动态的向DOM树内添加或删除DOM元素
v-if 切换一个局部编译/卸载的过程,切换时合适销毁和重建内部事件监听和子组件
v-if是懒惰性的,初始条件 = false,什么也不做,只有在条件第一次 = true时,才开始局部编译
v-show 是在任何条件下(首次条件是否为着真)都会被编译,然后缓存,而且DOM元素保留
v-if有更高的切换消耗
使用场景:
v-if 适合运营条件不大可能改变
- v-show
v-show有更高的初始化渲染消耗
v-show只是简单的基于css切换
v-show是通过设置DOM元素的display实现控制显隐的
使用场景:
v-show 适合频繁切换
v-for
值是一个数组 (item,index) in 数组名
值是一个对象 (value,key) in 对象名 value是属性值,key是属性
※key属性只能使用 number 或string,且是唯一的, 必须使用 v-bind 属性绑定的形式,指定key的值
v-bind和v-on
可写成:和@
v-model
可用于数据双向绑定
常见的修饰符
.lazy v-model 在每次 input 事件触发后将输入框的值与数据进行同步
<input v-model.lazy="msg" >
.number 自动将用户的输入值转为数值类型
<input v-model.number="age" type="number">
.trim 自动过滤用户输入的首尾空白字符
<input v-model.trim="msg">
vue的事件修饰符
vue.js为 v-on 提供了事件修饰符
.stop 阻止maop
.prevent 阻止默认事件
.captur 添加事件监听器时使用事件捕获模式
.self 只当事件在该元素本身(比如不是子元素)触发是触发回调
.once 事件值触发一次
.stop和.self的区别:
.stop阻止事件冒泡
.self只会阻止自己身上冒泡行为的触发,并不会真正阻止 冒泡行为
在vue工程中引入jquery
一、通过npm install jquery安装jquery依赖
1 | npm install jquery --save |
二、修改webpack.base.conf文件
该文件一般位于build文件夹内
1 | const path = require('path') |
1 | module.exports = { |
三、引入jquery
在想要引入jquery的组件中进入jquery
import $ from 'jquery'
也可直接在main.js中全局引入jquery
实现文件上传功能
一个文件上传功能做了好多次了,但每次做的时候还是需要各种百度,瞧我这个烂记性。。
想实现用ajax进行文件上传~
前端
此处还用了elmentui的样式
1 | <form id="upload" enctype="multipart/form-data" method="post"> |
1 | uploadPic() { |
JAVA端
1 |
|
axios
发送post请求
1 | // Content-Type: application/json: |
发送get请求
1 | // 不带参数的请求 |
VUE父子传值
父组件向子组件传值
1 | // 父组件中, 将需要传的值放在post.title中: |
子组件向父组件传值
1 | <!-- 父组件 --> |
Vue-router
基本概念
路由中有三个基本的概念 route, routes, router。
1, route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮 => home内容, 这是一条route, about按钮 => about 内容, 这是另一条路由。
2, routes 是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, { about按钮 => about 内容}]
3, router 是一个机制,相当于一个管理者,它来管理路由。因为routes 只是定义了一组路由,它放在哪里是静止的,当真正来了请求,怎么办? 就是当用户点击home 按钮的时候,怎么办?这时router 就起作用了,它到routes 中去查找,去找到对应的 home 内容,所以页面中就显示了 home 内容。
4,客户端中的路由,实际上就是dom 元素的显示和隐藏。当页面中显示home 内容的时候,about 中的内容全部隐藏,反之也是一样。客户端路由有两种实现方式:基于hash 和基于html5 history api.
使用方法
1 | const routes = [ |
但是有一个问题,当首次进入页面的时候,页面中并没有显示任何内容。这是因为首次进入页面时,它的路径是 ‘/‘,我们并没有给这个路径做相应的配置。但是如果我们写{ path: ‘/‘, component: Home },vue 会报错,因为两条路径却指向同一个方向。这怎么办?这需要重定向,所谓重定向,就是重新给它指定一个方向,它本来是访问 / 路径,我们重新指向‘/home’
1 |
|
路由的资料: https://blog.csdn.net/qq_31967569/article/details/91546294
vue-router的push和replace的区别
1.this.$router.push()
描述:跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。
2.this.$router.replace()
描述:同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。
3.this.$router.go(n)
相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面
服务器端渲染SSR
服务端渲染 对比 预渲染(Prerendering)
如果你只是用服务端渲染来改善一个少数的营销页面(如 首页,关于,联系 等等)的SEO,那你可以用预渲染替换。预渲染不像服务器渲染那样即时编译HTML,预渲染只是在构建时为了特定的路由生成特定的几个静态页面。其优势是预渲染的设置更加简单,可以保持前端是一个完整的静态站。
你用webpack可以很简单地通过prerender-spa-plugin来添加预渲染,它被广泛地用在Vue应用上 - 事实上,创建者也是Vue核心团队成员之一。
服务端渲染是先向后端服务器请求数据,然后生成完整首屏html返回给浏览器;
而客户端渲染是等js代码下载、加载、解析完成后再请求数据渲染,等待的过程页面是什么都没有的,就是用户看到的白屏。
就是服务端渲染不需要等待js代码下载完成并请求数据,就可以返回一个已有完整数据的首屏页面。
为什么要使用服务端渲染?
第一点,有利于SEO;第二点,希望用户更快速地看到完整渲染的页面,从而提高用户体验。基于这两点
Vuex
参考资料: https://www.cnblogs.com/chinabin1993/p/9848720.html
Vue-cli
vue项目脚手架, 可以帮助我们快速初始化下项目, 并提供很多插件选择, 类似springboot的官方demo生成器