The World Best ST.

前端备忘

字数统计: 13.8k阅读时长: 57 min
2020/04/04 Share

前端备忘

好记性不如烂笔头!


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
2
3
4
<input type="date" />
<input type="time" />
<input type="month" />
<input type="week" />

目前 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
2
3
<input type="text" name="require" required="" />
<input type="text" name="require1" required="required" />
<input type="text" name="require2" pattern="^[1-9]\d{5}$" />

表单验证属性require 类型时,若输入值为空,则拒绝提交并出现提示,注意在 Opera 中必须指定 name 值,否则无效果。

autofocus属性:

1
<input type="text" autofocus="true" />

默认聚焦属性,可在页面加载时聚焦到一个表单控件,类似于 JS 的 focus()

list属性:

1
2
3
4
5
6
7
<input type="text" list="ilist">
<datalist id="ilist">
<option label="a"></option>
<option label="b"></option>
<option label="c"></option>
</datalist>
</input>

需要与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
2
3
4
<form action="demo_form.asp" method="get" novalidate="true">
E-mail: <input type="email" name="user_email" />
<input type="submit" />
</form>

在提交表单时不应该验证 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
2
3
4
5
6
7
h1 {
text-shadow: 5px 5px 5px #FF0000;
}

text-shadow: h-shadow v-shadow blur color;
水平阴影位置 , 垂直阴影位置 , 模糊距离(可选) , 颜色
inset表示设置“内阴影”,可以不设置,则默认为外阴影

Web Font与@font-face

用途: 指定名为”myFirstFont”的字体,并指定在哪里可以找到它的URL

1
2
3
4
5
6
7
8
9
10
11
@font-face
{
font-family: myFirstFont;
src: url('Sansation_Light.ttf'),
url('Sansation_Light.eot'); /* IE9 */
}

div
{
font-family: myFirstFont;
}

font-size-adjust

用途: 通过指定font-size-adjust属性,浏览器将调整字体大小,无论字体系列, 不同字体也能保持一样的大小(只有firefox支持)

1
2
3
4
div
{
font-size-adjust: 0.58;
}

背景边框相关新增属性

background-clip

用途: 规定背景的绘制区域

1
2
3
4
5
6
7
8
div
{
background-color:yellow;
background-clip:content-box;
}

background-clip: border-box|padding-box|content-box;
背景被裁剪到边框盒 , 背景被裁剪到内边距框 , 背景被裁剪到内容框

background-origin

用途: 内容框相对定位的背景图片(背景原点)

1
2
3
4
5
6
7
8
9
10
div
{
background-image:url('smiley.gif');
background-repeat:no-repeat;
background-position:left;
background-origin:content-box;
}

background-origin: padding-box|border-box|content-box;
※如果background-attachment是固定, 则这个属性没有效果

background-size

用途: 重设背景图片大小

1
2
3
4
5
6
7
8
9
div
{
background:url(img_flwr.gif);
background-size:80px 60px;
background-repeat:no-repeat;
}

background-size: length|percentage|cover|contain;
通过像素设置长宽 , 通过百分比设置长宽 , 保持图像的纵横比并将图像缩放成将完全覆盖背景定位区域的最小大小 , 保持图像的纵横比并将图像缩放成将适合背景定位区域的最大大小

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
2
3
4
5
6
7
8
9
10
11
12
13
14
div
{
border:2px solid;
border-radius:25px;
}

border-radius: 2em 1em 4em / 0.5em 3em;

is equivalent to:

border-top-left-radius: 2em 0.5em;
border-top-right-radius: 1em 3em;
border-bottom-right-radius: 4em 0.5em;
border-bottom-left-radius: 1em 3em;

border-image

1
2
3
4
5
6
7
8
#borderimg { 
-webkit-border-image: url(border.png) 30 round; /* Safari 3.1-5 */
-o-border-image: url(border.png) 30 round; /* Opera 11-12.1 */
border-image: url(border.png) 30 round;
}

border-image: source slice width outset repeat|initial|inherit;
用于设置图像边界是否应重复(repeat)、拉伸(stretch)或铺满(round)。

布局相关

display新增属性

多行文本居中省略号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
单行文本省略号
{
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}

多行文本省略号
{
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; // 限制文本的行数, 只显示3行
overflow: hidden;
}

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.box{

display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */

}

.flex1 {
-webkit-flex: 1; /* Chrome */
-ms-flex: 1 /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
-webkit-box-flex: 1 /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
}

// 注意点, 带box的一定要放在最下面

Media Queries相关样式

Media Queries直译过来就是“媒体查询”

1
2
3
<link href="css/reset.css" rel="stylesheet" type="text/css" media="screen" />
<link href="css/style.css" rel="stylesheet" type="text/css" media="all" />
<link href="css/print.css" rel="stylesheet" type="text/css" media="print" />

“media”就是用来指定特定的媒体类型,在HTML4和CSS2中充许你使用“media”来指定特定的媒体类型,如屏幕(screen)和打印(print)的样式表,当然还有其他的,比如说“TV”,“handheld”等,其中“all”表示的是支持所有媒体介质

简单的实例:

1
2
<link rel="stylesheet" media="screen and (max-width: 600px)" href="small.css" />
当页页宽度小于或等于600px,调用small.css样式表来渲染你的Web页面

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
28
var 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
2
3
4
let first = 'Jane';
let last = 'Doe';
console.log(`Hello ${first} ${last}!`);
// Hello Jane Doe!
  • 多行模板字符串
1
2
3
4
5
let multiLine = `
This is
a string
with multiple
lines`;
  • 原始字符串, 反斜线不再是特殊字符

String.raw: 用于产生原始字符串(反斜杠不会被转义)

1
2
3
4
5
let raw = String.raw`Not a newline: \n`;
console.log(raw === 'Not a newline: \\n'); // true

let greeting = `\`Yo\` World!`;
如果在模板字符串中需要使用反引号,则前面要用反斜杠转义
字符串迭代
1
2
3
4
5
6
7
8
9
10
11
12
方法1:
for (let ch of 'abc') {
console.log(ch);
}
// Output:
// a
// b
// c

方法2:
let chars = [...'abc'];
// ['a', 'b', 'c']
Unicode和码位
  • String.fromCodePoint(…codePoints : number[]) : string
    将数字值码位转换成字符串。
1
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
  • String.prototype.codePointAt(pos) : number
    返回码位开始位置的数字值(会包含一个或两个JavaScript的字符)。
1
2
3
4
let str = 'x\uD83D\uDE80y';
console.log(str.codePointAt(0).toString(16)); // 78
console.log(str.codePointAt(1).toString(16)); // 1f680
console.log(str.codePointAt(3).toString(16)); // 79
  • 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
2
3
4
5
6
7
8
9
var str="hello world!";
str.replace("l",'o');
>>>>>>"heolo world!";
str.replace(/l/g,"o");
>>>>>>"heooo worod";
str.replace(/l/g,function(){
return "o";
})
>>>>>>"heooo worod";
indexOf和search的区别

search是强制匹配正则, indexOf是匹配字符串

1
2
3
4
5
6
7
var str="123456789.abcde";
console.log(str.search("."));//0 因为正则.匹配\n以外任意字符
console.log(str.indexOf("."));//9 只匹配字符串.
console.log(str.search("\\."));//9
console.log(str.indexOf("\\."));//-1 匹配\. 所以不存在
console.log(str.search(/\./)); //9 正则匹配后.字符
console.log(str.indexOf(/\./)); //-1 相当于匹配'/\./' 所以不存在
match和search的区别

match 返回值是数组,返回数组是正则捕获的字符串

search 返回值是Number,返回正则匹配到的字符串起始位置的偏移量(下标) 如果未匹配到返回 -1

slice切片

String.prototype.slice(star,end);两个参数结束参数为可选参数,截取的字符串不包括结束参数的下标。结束参数可以为负数,表示从字符串末位截取。但开始参数在结束参数后面则返回一个空字符串。

1
2
3
4
5
6
7
var str="hello world";
str.slice(0);
>>>>>>"hello world"
str.slice(0,-1);
>>>>>>"hello worl"
str.slice(2,1);
>>>>>>""
padStart头部补全
1
2
3
4
5
6
7
let str = '1234'.padStart(8,'0');
console.log(str); // "00001234"

let str = 'abc'.padStart(5);
console.log(str); // " abc"

如果 padString 大于 padLength,padString 将被截断,只填充最左边的部分。
padEnd尾部补全
1
2
3
4
5
6
7
let str = 'abc'.padEnd(5);
console.log(str); // "abc "

str = 'abc'.padEnd(5,'*');
console.log(str); // "abc**"

如果 padString 大于 padLength,padString 将被截断,只填充最左边的部分。
match匹配

match参数有两种形式,可以是字符串也可以是正则对象。返回查询到的字符串本身,如果没有规定查询的字符串,则返回null。
加入正则表达式中没有全局匹配的话,返回一个匹配到的字符串,和子查询到的字符串组成的数组,该数组返回一个查询的
索引值。和被查询的字符串对象

1
2
3
4
5
6
7
8
9
10
var str="hello world";
str.match('hello');
>>>>>>"hello"
str.match(/l+/g);
>>>>>>['ll','l']
var str="<input value={wwwww} type={222222} />";
var arr=str.match(/{(\w+)}/);
>>>>>>['{wwwww}','wwwww'];
for(var i in arr)console.log(i);
>>>>>>0,1,index,input
test测试

test是用来检测字符串是否匹配某一个正则表达式,如果匹配就会返回true,反之则返回false

1
2
3
/\d+/.test("123") ; //true

/\d+/.test("abc") ; //false
参考链接

https://www.cnblogs.com/chairs/p/6985597.html

正则表达式

1
2
3
4
//1、使用字面量来创建表达式
// 语法:var 变量 = /正则表达式/匹配模式
//2、使用构造函数创建
// 语法:var reg = new RegExp("a", "i")

参考链接: 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
says(say){
var self = this;
setTimeout(function(){
console.log(self.type + ' says ' + say)
}, 1000)

用bind(this):

says(say){
setTimeout(function(){
console.log(this.type + ' says ' + say)
}.bind(this), 1000)

用箭头函数:

says(say){
setTimeout( () => {
console.log(this.type + ' says ' + say)
}, 1000)
}

箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this
不可以使用arguments对象,该对象在函数体内不存在

Function构造器

1
2


new.target属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Person(name) {
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必须使用new生成实例');
}
}

// 另一种写法
function Person(name) {
if (new.target === Person) {
this.name = name;
} else {
throw new Error('必须使用new生成实例');
}
}

var person = new Person('张三'); // 正确
var notAPerson = Person.call(person, '张三'); // 报错

Class内部调用new.target,返回当前Class。
子类继承父类时,new.target会返回子类。

如果构造函数不是通过new命令调用的,new.target会返回undefined,因此这个属性可以用来确定构造函数是怎么调用的

扩展的对象功能

属性方法简写

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
32
33
// 属性简写: 

let name = 'why'
let age = 8

// ESC5
let obj = {
name: name,
age: age
}

// ESC6
let obj2 = {
name, age
}

// {name: 'why', age: 8}


// 方法简写
// ESC5
let obj1 = {
test: function() {
console.log(1)
}
}

// ESC6
let obj2 = {
test() {
console.log(2)
}
}

Object.assign

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var target = { a: 1 };

var source1 = { b: 2 };
var source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

如果重名, 则后面覆盖前面的:
var target = { a: 1, b: 1 };

var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

Object.is

用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。

  • 两个值都是 undefined
  • 两个值都是 null
    – 两个值都是 true 或者都是 false
  • 两个值是由相同个数的字符按照相同的顺序组成的字符串
  • 两个值指向同一个对象
  • 两个值都是数字并且
    • 都是正零 +0
    • 都是负零 -0
    • 都是 NaN
    • 都是除零和 NaN 外的其它同一个数字

Object.setPrototypeOf

1
2
3
Object.setPrototypeOf(a, b)

// 将对象b赋值给对象a

更方便的数据访问

对象词法扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function getCar(make, model, value) {
return {
// 简写变量
make, // 等同于 make: make
model, // 等同于 model: model
value, // 等同于 value: value

// 属性可以使用表达式计算值
['make' + make]: true,

// 忽略 `function` 关键词简写对象函数
depreciate() {
this.value -= 2500;
}
};
}

let car = getCar('Barret', 'Lee', 40000);

对象和数组解构

解构可以避免在对象赋值时产生中间变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function foo() {
return [1,2,3];
}
let arr = foo(); // [1,2,3]

let [a, b, c] = foo();
console.log(a, b, c); // 1 2 3

function bar() {
return {
x: 4,
y: 5,
z: 6
};
}
let {x: x, y: y, z: z} = bar();
console.log(x, y, z); // 4 5 6

Symbol

ES6引入了一种新的原始数据类型Symbol,表示独一无二的ID。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。

Symbol类型的值不能与其他类型的值进行运算,会报错。

但是,Symbol类型的值可以转为字符串。

如果它被用作一个对象的属性,那么这个属性会是不可枚举的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var sym = Symbol('My symbol');

"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string

不会报错
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'

---------
var o = {
val: 10,
[ Symbol("random") ]: "I'm a symbol",
};

console.log(Object.getOwnPropertyNames(o)); // val

Symbol属性不会被展示

Set与Map

Map

Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象), 相当于java的map

1
2
3
4
5
var m = new Map();
o = {p: "Hello World"};
m.set(o, "content")
document.write(m.get(o))
// "content"
  • 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
2
3
4
5
6
7
8
9
10
11
12
var items = new Set([1,2,3,4,5,5,5,5]);
document.write(items.size); // 5

Set加入值的时候,不会发生类型转换,所以5和“5”是两个不同的值。

let set = new Set();
set.add({})
set.size // 1
set.add({})
set.size // 2

由于两个空对象不是精确相等,所以它们被视为两个值。
将set转化为数组
1
2
var items = new Set([1, 2, 3, 4, 5]);
var array = Array.from(items);

WeakSet

WeakSet的成员只能是对象,而不能是其他类型的值。WeakSet没有size属性,没有办法遍历它的成员。

Array增强

Array.from()

任何有length属性的对象,都可以通过Array.from方法转为数组

Array.from()还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理。类似java8的stream

1
2
3
4
5
let array = [0,1,2,3,4];
let arrNew = Array.from(array, x => x * x);
console.log(arrNew);
// 等同于
let arrNew = Array.from(array).map(x => x * x);

Array.of()

Array.of方法用于将一组值,转换为数组。

1
2
3
4
5
6
7
8
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

Array()方法存在缺陷
Array() // []
Array(3) // [undefined, undefined, undefined]
Array(3,11,8) // [3, 11, 8]

find

1
2
3
4
5
6
7
8
9
// 找出值小于0的数
let array = [1, 4, -5, 10].find((n) => n < 0);
document.write("array:", array);

// 可接受3个参数
let array = [1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
})
document.write(array); // 10

findIndex

用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。这两个方法都可以接受第二个参数,用来绑定回调函数的this对象。这两个方法都可以发现NaN,弥补了数组的IndexOf方法的不足。

1
2
3
4
5
[NaN].indexOf(NaN)
// -1

[NaN].findIndex(y => Object.is(NaN, y))
// 0

fill()

1
2
3
4
5
6
7
8
9
10
11
12
fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去

let arr = ['a', 'b', 'c'].fill(7)
document.write(arr); // [7, 7, 7]

let newArr = new Array(3).fill(7)
document.write(newArr); // [7, 7, 7]

fill()还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。

let newArr = ['a', 'b', 'c'].fill(7, 1, 2)
document.write(newArr); // ['a', 7, 'c']

entires()

1
2
3
4
5
6
7
8
9
var arr = ["red", "blue", "green"]
var x = arr.entries()
console.log(x); // Array Iterator {}
console.log(x.next()) //{value: Array:[0, "red"],done:false}
console.log(x.next()) //{value: Array:[1, "blue"],done:false}
console.log(x.next()) //{value: Array:[2, "green"],done:false}
console.log(x.next()) //{value: undefined, done: true}

可以通过x.next().done是否为true来判断迭代器是否结束

keys()

方法用于从数组创建一个包含数组键的可迭代对象。包含原始数组的键(key)

1
2
3
4
5
6
7
8
let colors = ["red", "pink", "blue", "skyblue"];
// 创建迭代对象
let colorkey = colors.keys();
console.log(colorkey); // Array Iterator{}
// 利用 for...of 迭代出创建的迭代对象的键
for (let item of colorkey) {
console.log(item); // 下标
}

values()

1
2
3
4
5
6
7
8
9
var A = [ 'Ram', 'Z', 'k', 'geeksforgeeks' ]; 
var iterator = A.values();
console.log(iterator.next().value);

// 或者通过这个方法获取
var iterator = array.values();
for (let elements of iterator) {
console.log(elements);
}

keys() values() entries() 的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let arr = [ {age:18, value:'张三'}, {age:19, value:'李四'}, {age:20, value:'王五'} ]

const keys1 = arr.keys()
const keys2 = arr.values()
const keys3 = arr.entries()

for (let item of keys1 ) {
console.log(item)
}
// 此处返回的是该数组的索引
// 输出结果: 0 1 2

for (let item of keys2 ) {
console.log(item)
}
// 此处返回的是该数组的元素
// 输出结果: {age:18, value:'张三'} {age:19, value:'李四'} {age:20, value:'王五'}

for (let item of keys3 ) {
console.log(item)
}
// 此处返回的是该数组的键值对
// 输出结果:[0, {age:18, value:'张三'}] [1, {age:19, value:'李四'}] [2, {age:20, value:'王五'}]

foreach

forEach((element, index, array) => { /* … */ })

forEach() 本身是不支持的 continue 与 break 语句的,我们可以通过 some 和 every 来实现。

它的return是continue的意思

如果想要实现break效果, 那么可以使用ervery实现

1
2
3
4
5
6
7
8
var arr = [1, 2, 3, 4, 5];

arr.every(function (item) {
console.log(item);
return item !== 3;
});

打印出来 1 2 3

map()

map定义和方法 map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理的后值。

map()方法按照原始数组元素顺序依次处理元素。

注意: map不会对空数组进行检测, map不会改变原始数组

1
2
3
var array1 = [1,4,9,16];
const map1 = array1.map(x => x *2);
console.log(map1);

reduce()

reduce()方法为归并类方法,最常用的场景就是,计算数组中的每一项的总和。

有两个参数:

  1. 每次遍历都会调用的函数,而这个函数有接收四个参数,分别是:前一个值、当前项、项目的索引和数组对象,而这个函数的返回值,回传给下一次遍历时,执行的这个方法的第一个参数。
  2. 归并基础的初始值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let arr = [1,2,3,4,5]
arr.reduce((prev,cur)=>{
return prev+cur
},10)

// 10+1+2+3+4+5

var arr = [
[0, 1],
[2, 3],
[4, 5],
];

var value = arr.reduce((pre, cur) => {
return pre.concat(cur);
}, []);

console.log(value); // 输出:[0, 1, 2, 3, 4, 5]

filter()

filter()方法用于把Array中的某些元素过滤掉,然后返回剩下的未被过滤掉的元素。

  1. filter() 不会对空数组进行检测;
  2. filter() 不会改变原始数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const school = [
{
occupation:"老师",
age:40
},
{
occupation:"学生",
age:23
},{
occupation:"程序猿",
age:1
}
]
var newShool = school.filter(item => item.age > 20)
console.log(newShool);//[ { occupation: '老师', age: 40 }, { occupation: '学生",age:23}

参考资料: https://www.w3school.com.cn/jsref/jsref_obj_array.asp

ArrayBuffer

简单说,ArrayBuffer对象代表原始的二进制数据,TypedArray视图用来读写简单类型的二进制数据,DataView视图用来读写复杂类型的二进制数据。

ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(TypedArray视图和DataView视图)来读写,视图的作用是以指定格式解读二进制数据。

1
2
3
var buf = new ArrayBuffer(32);
var dataView = new DataView(buf);
dataView.getUint8(0) // 0

上面代码对一段32字节的内存,建立DataView视图,然后以不带符号的8位整数格式,读取第一个元素,结果得到0,因为原始内存的ArrayBuffer对象,默认所有位都是0。

ArrayBuffer.prototype.slice()

ArrayBuffer实例有一个slice方法,允许将内存区域的一部分,拷贝生成一个新的ArrayBuffer对象。

1
2
3
4
var buffer = new ArrayBuffer(8);
var newBuffer = buffer.slice(0, 3);

拷贝buffer对象的前3个字节(从0开始,到第3个字节前面结束)
ArrayBuffer.isView()

ArrayBuffer有一个静态方法isView,返回一个布尔值,表示参数是否为ArrayBuffer的视图实例。这个方法大致相当于判断参数,是否为TypedArray实例或DataView实例。

1
2
3
4
5
var buffer = new ArrayBuffer(8);
ArrayBuffer.isView(buffer) // false

var v = new Int32Array(buffer);
ArrayBuffer.isView(v) // true
ArrayBuffer与字符串的互相转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 假定字符串采用UTF-16编码(JavaScript的内部编码方式)
// ArrayBuffer转为字符串,参数为ArrayBuffer对象
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}

// 字符串转为ArrayBuffer对象,参数为字符串
function str2ab(str) {
var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
var bufView = new Uint16Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}

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
2
3
4
5
6
7
8
// 小端字节序
var v1 = dv.getUint16(1, true);

// 大端字节序
var v2 = dv.getUint16(3, false);

// 大端字节序
var v3 = dv.getUint16(3);

参考资料: https://www.jianshu.com/p/5a841d6d7cc3

Promise与异步编程

所谓Promise,就是一个对象,用来传递异步操作的消息。

Promise对象有以下两个特点:

  • 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。

Promise也有一些缺点:

  • 首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  • 其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  • 第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//创建promise
var promise = new Promise(function(resolve, reject) {
// 进行一些异步或耗时操作
if ( /*如果成功 */ ) {
resolve("Stuff worked!");
} else {
reject(Error("It broke"));
}
});
//绑定处理程序
promise.then(function(result) {
//promise成功的话会执行这里
document.write(result); // "Stuff worked!"
}, function(err) {
//promise失败会执行这里
document.write(err); // Error: "It broke"
});
  • resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
  • reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

then

then方法是定义在原型对象,作用是为Promise实例添加状态改变时的回调函数。then方法返回的是一个新的Promise实例, 所以then方法可以链式调用

1
2
3
4
5
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});

catch

如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误, 且异常带有冒泡性质, 会一直向后传递, 直到被捕获

1
2
3
4
5
var promise = new Promise(function(resolve, reject) {
throw new Error('test')
});
promise.catch(function(error) { document.write(error) });
// Error: test

Promise.all()

1
2
3
4
5
6
7
8
9
10
// 生成一个Promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function(id){
return getJSON("/post/" + id + ".json");
});

Promise.all(promises).then(function(posts) {
// ...
}).catch(function(reason){
// ...
});

上面定义了6个promise, promise.all的状态是根据这6个promise的结果来定的, 只要有一个是rejected, 那么promise.all的状态就是rejected, 且传递的值是第一个rejected的实例返回值。如果都成功了, 则会将成功的返回值组成一个数组返回

Promise.race()

与Promise.all类似, 不同的是, 它只要是有一个promise状态改变, 那么它的状态就会跟着变, 并收到第一个改变的返回值

Promise.resolve()

1
2
3
4
5
6
var p = Promise.resolve('Hello');

p.then(function (s){
document.write(s)
});
// Hello

如果Promise.resolve方法的参数,不是具有then方法的对象(又称thenable对象),则返回一个新的Promise对象,且它的状态为Resolved。由于字符串Hello不属于异步操作(判断方法是它不是具有then方法的对象),返回Promise实例的状态从一生成就是Resolved,所以回调函数会立即执行。

Promise.reject()

与resolve方法类似, 会调用promise的reject方法

1
2
3
4
5
6
var p = Promise.reject('出错了');

p.then(null, function (s){
document.write(s)
});
// 出错了

深浅拷贝

浅拷贝(Shallow Copy)

  1. 浅拷贝创建了一个新的对象,但是其中的属性仍然是原始对象中属性的引用。
  2. 修改拷贝对象中的属性会影响到原始对象,反之亦然。
  3. 对于嵌套对象(对象中包含对象),浅拷贝只会复制对象的引用,而不会递归复制嵌套对象。

常见的浅拷贝方法包括 Object.assign() 和展开运算符 (…)

深拷贝(Deep Copy)

  1. 深拷贝创建了一个全新的对象,并且将原始对象中的属性递归地复制到新对象中,包括嵌套的对象。
  2. 修改拷贝对象中的属性不会影响原始对象,二者互不关联。
  3. 深拷贝操作相对耗费资源,特别是对于大型嵌套对象或包含循环引用的对象。

常见的深拷贝方法包括 JSON.parse(JSON.stringify()) (不太推荐)、Lodash 的 _.cloneDeep()、递归方式(就是自己写循环) 、jquery的extend()方法进行深拷贝等。

1
2
3
let obj = { a: { c: 2, d: [1, 3, 5], e: "哇哇哇" }, b: 4 };
let newObj = $.extend(true, {}, obj1);
//拷贝完成obj.b = 20;console.log(newObj.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
2
3
[v-cloak]{
display: none;
}

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
2
3
4
npm install jquery --save

# 如果你更换了淘宝镜像,可以使用cnpm来安装,速度更快
cnpm install jquery --save

二、修改webpack.base.conf文件

该文件一般位于build文件夹内

1
2
3
4
5
6
7
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')

// 增加
const webpack = require('webpack')
1
2
3
4
5
6
7
8
9
10
11
module.exports = {
...,
//新增
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
...
}

三、引入jquery

在想要引入jquery的组件中进入jquery

import $ from 'jquery'

也可直接在main.js中全局引入jquery

实现文件上传功能

一个文件上传功能做了好多次了,但每次做的时候还是需要各种百度,瞧我这个烂记性。。
想实现用ajax进行文件上传~

前端

此处还用了elmentui的样式

1
2
3
4
5
6
7
8
9
10
11
<form id="upload" enctype="multipart/form-data" method="post">
<span>分组名称</span>
<el-input v-model="groupName" id="groupName" name="groupName"></el-input>
<span>分组描述</span>
<el-input v-model="description" id="description" name="description"></el-input>
<span>白名单文件</span>
<br/>
<input type="file" name="file" id="pic"/>
<br/>
<el-button @click="uploadPic">提交</el-button>
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
uploadPic() {
var form = document.getElementById('upload'),
formData = new FormData(form);
console.log(form)
$.ajax({
url:"http://localhost:8081/file/upload",
type:"post",
data:formData,
processData:false,
contentType:false,
success:function(res){
if(res){
alert("上传成功!");
}
console.log(res);
},
error:function(err){
alert("网络连接失败,稍后重试",err);
}
})
}

JAVA端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@CrossOrigin
@RequestMapping("/file")
@RestController
public class FileController {
@RequestMapping("/upload")
public String upload(@RequestParam("file") MultipartFile multipartFile,
@RequestParam String groupName,
@RequestParam String description){
if (multipartFile == null) {
System.out.println("empty");
} else {
System.out.println("ok");
}
return "success";
}
}

axios

发送post请求

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
// Content-Type: application/json:

let data = {"code":"1234","name":"yyyy"};
axios.post(`${this.$url}/test/testRequest`,data)
.then(res=>{
console.log('res=>',res);
})

// Content-Type: multipart/form-data:

let data = new FormData();
data.append('code','1234');
data.append('name','yyyy');
axios.post(`${this.$url}/test/testRequest`,data)
.then(res=>{
console.log('res=>',res);
})

// Content-Type: application/x-www-form-urlencoded:

import axios from 'axios'
import qs from 'Qs'
let data = {"code":"1234","name":"yyyy"};
axios.post(`${this.$url}/test/testRequest`,qs.stringify({
data
}))
.then(res=>{
console.log('res=>',res);
})

发送get请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 不带参数的请求
axios.get(this.GLOBAL.host.+“后台接口地址”).then(res => {
//获取你需要用到的数据
})

// 带参数的请求
this.$axios.get(this.GLOBAL.host.+“后台接口地址”,{
params:{
phone:12345678 //参数,键值对,key值:value值
name:hh
}
}).then(res => {
//获取你需要用到的数据
});

VUE父子传值

父组件向子组件传值

1
2
3
4
5
6
7
8
9
10
11
12
13
// 父组件中, 将需要传的值放在post.title中:
<blog-post title="post.title"></blog-post>


// 子组件中使用props接受父组件的传值
export default {
props: {
title: {
type: String,
default: 'hello'
}
}
}

子组件向父组件传值

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!-- 父组件 -->
<template>
<div class="test">
<test-com @childFn="parentFn"></test-com>
<br/>
子组件传来的值 : {{message}}
</div>
</template>

<script>
export default {
// ...
data() {
return {
message: ''
}
},
methods: {
parentFn(payload) {
this.message = payload;
}
}
}
</script>

<!-- 子组件使用$emit -->
<template>
<div class="testCom">
<input type="text" v-model="message" />
<button @click="click">Send</button>
</div>
</template>
<script>
export default {
// ...
data() {
return {
// 默认
message: '我是来自子组件的消息'
}
},
methods: {
click() {
this.$emit('childFn', this.message);
}
}
}
</script>

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
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
32
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]

const router = new VueRouter({
routes // routes: routes 的简写
}

const app = new Vue({
router
}).$mount('#app')


<template>
<div id="app">
<img src="./assets/logo.png">
<header>
<!-- router-link 定义点击后导航到哪个路径下 -->
<router-link to="/home">Home</router-link>
<router-link to="/about">About</router-link>
</header>
<!-- 对应的组件内容渲染到router-view中 -->
<router-view></router-view>
</div>
</template>

<script>
export default {

}
</script>

但是有一个问题,当首次进入页面的时候,页面中并没有显示任何内容。这是因为首次进入页面时,它的路径是 ‘/‘,我们并没有给这个路径做相应的配置。但是如果我们写{ path: ‘/‘, component: Home },vue 会报错,因为两条路径却指向同一个方向。这怎么办?这需要重定向,所谓重定向,就是重新给它指定一个方向,它本来是访问 / 路径,我们重新指向‘/home’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

const routes = [
{
path:"/home",
component: home
},
{
path: "/about",
component: about
},
// 重定向
{
path: '/',
redirect: '/home'
}
]

路由的资料: 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生成器

CATALOG
  1. 1. 前端备忘
    1. 1.1. HTML5
      1. 1.1.1. HTML5表单的特点:
      2. 1.1.2. HTML5新增的控件类型:
      3. 1.1.3. HTML5新增的表单属性:
      4. 1.1.4. 目前任何表单元素都有八种可能的验证约束条件:
    2. 1.2. CSS3
      1. 1.2.1. 文字与字体相关样式
        1. 1.2.1.1. text-shadow
        2. 1.2.1.2. Web Font与@font-face
        3. 1.2.1.3. font-size-adjust
      2. 1.2.2. 背景边框相关新增属性
        1. 1.2.2.1. background-clip
        2. 1.2.2.2. background-origin
        3. 1.2.2.3. background-size
        4. 1.2.2.4. background-break
        5. 1.2.2.5. 多个背景叠加
        6. 1.2.2.6. background-attachment
        7. 1.2.2.7. border-radius
        8. 1.2.2.8. border-image
      3. 1.2.3. 布局相关
        1. 1.2.3.1. display新增属性
        2. 1.2.3.2. 多行文本居中省略号
        3. 1.2.3.3. column多栏布局
        4. 1.2.3.4. flex布局
        5. 1.2.3.5. flex旧布局
      4. 1.2.4. Media Queries相关样式
    3. 1.3. ECMAScript6
      1. 1.3.1. 块级绑定(let, const)
        1. 1.3.1.1. let
        2. 1.3.1.2. const
      2. 1.3.2. 字符串与正则表达式的新增能力
        1. 1.3.2.1. 字符串新增方法
          1. 1.3.2.1.1. 模板字符串
          2. 1.3.2.1.2. 字符串迭代
          3. 1.3.2.1.3. Unicode和码位
          4. 1.3.2.1.4. 查找字符串
          5. 1.3.2.1.5. repeat重复字符串
          6. 1.3.2.1.6. replace替换
          7. 1.3.2.1.7. indexOf和search的区别
          8. 1.3.2.1.8. match和search的区别
          9. 1.3.2.1.9. slice切片
          10. 1.3.2.1.10. padStart头部补全
          11. 1.3.2.1.11. padEnd尾部补全
          12. 1.3.2.1.12. match匹配
          13. 1.3.2.1.13. test测试
          14. 1.3.2.1.14. 参考链接
        2. 1.3.2.2. 正则表达式
          1. 1.3.2.2.1. ()、[]、{} 的区别
          2. 1.3.2.2.2. ^ 和 $
          3. 1.3.2.2.3. \d \s \w .
          4. 1.3.2.2.4. * + ?
          5. 1.3.2.2.5. 匹配模式
      3. 1.3.3. 函数
        1. 1.3.3.1. 函数参数默认值
        2. 1.3.3.2. this问题
        3. 1.3.3.3. Function构造器
        4. 1.3.3.4. new.target属性
      4. 1.3.4. 扩展的对象功能
        1. 1.3.4.1. 属性方法简写
        2. 1.3.4.2. Object.assign
        3. 1.3.4.3. Object.is
        4. 1.3.4.4. Object.setPrototypeOf
      5. 1.3.5. 更方便的数据访问
        1. 1.3.5.1. 对象词法扩展
        2. 1.3.5.2. 对象和数组解构
      6. 1.3.6. Symbol
      7. 1.3.7. Set与Map
        1. 1.3.7.1. Map
        2. 1.3.7.2. Set
          1. 1.3.7.2.1. 将set转化为数组
      8. 1.3.8. Array增强
        1. 1.3.8.1. Array.from()
        2. 1.3.8.2. Array.of()
        3. 1.3.8.3. find
        4. 1.3.8.4. findIndex
        5. 1.3.8.5. fill()
        6. 1.3.8.6. entires()
        7. 1.3.8.7. keys()
        8. 1.3.8.8. values()
        9. 1.3.8.9. keys() values() entries() 的区别
        10. 1.3.8.10. foreach
        11. 1.3.8.11. map()
        12. 1.3.8.12. reduce()
        13. 1.3.8.13. filter()
        14. 1.3.8.14. ArrayBuffer
          1. 1.3.8.14.1. ArrayBuffer.prototype.slice()
          2. 1.3.8.14.2. ArrayBuffer.isView()
          3. 1.3.8.14.3. ArrayBuffer与字符串的互相转换
        15. 1.3.8.15. DataView
      9. 1.3.9. Promise与异步编程
        1. 1.3.9.1. 用法
        2. 1.3.9.2. then
        3. 1.3.9.3. catch
        4. 1.3.9.4. Promise.all()
        5. 1.3.9.5. Promise.race()
        6. 1.3.9.6. Promise.resolve()
        7. 1.3.9.7. Promise.reject()
      10. 1.3.10. 深浅拷贝
        1. 1.3.10.1. 浅拷贝(Shallow Copy)
        2. 1.3.10.2. 深拷贝(Deep Copy)
    4. 1.4. VUE
      1. 1.4.1. VUE生命周期
        1. 1.4.1.1. 1、创建前/后:
        2. 1.4.1.2. 2、载入前/后:
        3. 1.4.1.3. 3、更新前/后:
        4. 1.4.1.4. 4、销毁前/后:
      2. 1.4.2. VUE基本语法
        1. 1.4.2.1. 什么是VUE.js
        2. 1.4.2.2. Node(后端)中的mvc与前端mvvm之间的区别
        3. 1.4.2.3. VUE简介
        4. 1.4.2.4. 指令式渲染
        5. 1.4.2.5. 插值表达式
        6. 1.4.2.6. v-text与插值表达式的区别
        7. 1.4.2.7. v-html 与 v-text的区别
        8. 1.4.2.8. v-cloak
        9. 1.4.2.9. v-if
        10. 1.4.2.10. v-show
        11. 1.4.2.11. v-if与v-show的区别
        12. 1.4.2.12. v-for
        13. 1.4.2.13. v-bind和v-on
        14. 1.4.2.14. v-model
        15. 1.4.2.15. 常见的修饰符
        16. 1.4.2.16. vue的事件修饰符
          1. 1.4.2.16.1. .stop和.self的区别:
      3. 1.4.3. 在vue工程中引入jquery
        1. 1.4.3.1. 一、通过npm install jquery安装jquery依赖
        2. 1.4.3.2. 二、修改webpack.base.conf文件
        3. 1.4.3.3. 三、引入jquery
    5. 1.5. 实现文件上传功能
      1. 1.5.1. 前端
      2. 1.5.2. JAVA端
      3. 1.5.3. axios
        1. 1.5.3.1. 发送post请求
        2. 1.5.3.2. 发送get请求
      4. 1.5.4. VUE父子传值
        1. 1.5.4.1. 父组件向子组件传值
        2. 1.5.4.2. 子组件向父组件传值
      5. 1.5.5. Vue-router
        1. 1.5.5.1. 基本概念
        2. 1.5.5.2. 使用方法
        3. 1.5.5.3. vue-router的push和replace的区别
      6. 1.5.6. 服务器端渲染SSR
      7. 1.5.7. Vuex
      8. 1.5.8. Vue-cli