语义化让网页结构更加清晰,便于浏览器、搜索引擎的解析,便于阅读维护。javascript
语义化标签php
加强表单css
新增的表单属性html
视频和音频前端
canvas/svg绘图vue
地理位置html5
拖放Apijava
Web Workernode
Web Storagereact
webSocket
标准模式
和怪异模式
,data-
出现。dataset
getAttribute
setAttribute
data()
canavs
是h5新增一种用户绘制图形的容器标签,经过js绘制,经常使用于动画,游戏页面,数据可视化。
position: absolute;/*绝对定位*/
position: relative; /*相对定位*/
position: flexd; /*固定定位* / 复制代码
指浏览器不用等待全部页面资源都渲染好以后再呈现给用户看,而是边下载边渲染,因此用户打开一个网页的时候每每不能第一时间看到全部的内容,可是可以看到一个大概的样子,后续的内容浏览器会慢慢补上造成一个完整的页面。
是一种将业务逻辑层和表现层分离,将规定格式的模板代码转化为业务数据的实现
区别
优雅降级从复杂开始,渐进加强则从一个基础的版本开始,并不断扩充。
Link 属于 html 标签,而@import 是 CSS 中提供的
在页面加载的时候,link会同时被加载,而@import引用的CSS会在页面加载完成后才会加载引用的CSS
@import只有在ie5以上才能够被识别,而link是html标签,不存在浏览器兼容性问题
link引入样式的权重大于@import的引用(@import 是将引用的样式导入到当前的页面中)
clear:both
;在浮动的盒子下面再放一个标签,使用 clear:both;来清除浮动
使用 overflow
清除浮动, 找到浮动盒子的父元素,给父元素添加overflow:hidden;
属性
.clearfix:after {
content:"";
height:0;
line-height:0;
display:block;
clear:both;
visibility:hidden;
}
// 兼容IE6
.clearfix {
zoom: 1;
}
复制代码
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul < li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = "external"])
9.伪类选择器(a: hover, li: nth-child)
* 可继承: font-size font-family color, UL LI DL DD DT;
* 不可继承 :border padding margin width height ;
* 优先级就近原则,样式定义最近者为准;
* 载入样式以最后载入的定位为准;
优先级为:
!important > id > class > tag important 比 内联优先级高
CSS3新增伪类举例:
p:first-of-type 选择属于其父元素的首个 <p> 元素的每一个 <p> 元素。
p:last-of-type 选择属于其父元素的最后 <p> 元素的每一个 <p> 元素。
p:only-of-type 选择属于其父元素惟一的 <p> 元素的每一个 <p> 元素。
p:only-child 选择属于其父元素的惟一子元素的每一个 <p> 元素。
p:nth-child(2) 选择属于其父元素的第二个子元素的每一个 <p> 元素。
:enabled、:disabled 控制表单控件的禁用状态。
:checked,单选框或复选框被选中。
复制代码
块级元素(block)特性:
内联元素(inline)特性:
<input> 、<img> 、<button> 、<texterea> 、<label>。
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
position: absolute; /*父元素须要相对定位*/
top: 50%;
left: 50%;
margin-top: -100px; /*设为高度的1/2*/
margin-left: -100px; /*设为宽度的1/2*/
}
复制代码
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
position: absolute; /*父元素须要相对定位*/
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /*在水平和垂直方向上各偏移-50%*/
}
复制代码
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
margin: auto; /*很关键的一步*/
position: absolute; /*父元素须要相对定位*/
left: 0;
top: 0;
right: 0;
bottom: 0; /*让四个定位属性都为0*/
}
复制代码
body {
display: flex; /*设置外层盒子display为flex*/
align-items: center; /*设置内层盒子的垂直居中*/
justify-content: center; /*设置内层盒子的水平居中*/
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
}
}
复制代码
.content {
/* img的容器设置以下 */
display: table-cell;
text-align: center;
vertical-align: middle;
}
复制代码
什么是 BFC
BFC(Block Formatting Context)格式化上下文,是 Web 页面中盒模型布局的 CSS 渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。
造成 BFC 的条件
BFC 的特性
span {
width: 0;
heigh: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid #ff0000;
}
复制代码
他们是CSS预处理器。是 CSS 上的一种抽象层。他们是一种特殊的语法/语言编译成 CSS。
为何要使用它们?
概念:
将多个小图片拼接到一个图片中。经过 background-position 和元素尺寸调节须要显示的背景图案。
优势:
缺点:
IOS8+下已经支持带小数的px值,media query 对应 devicePixelRatio 有个查询值 -webkit-min-device-pixel-ratio;
.border { border: 1px solid #999 }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border { border: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
.border { border: 0.333333px solid #999 }
}
复制代码
<body><div id="main" style="border: 1px solid #000000;"></div></body>
<script type="text/javascript"> if (window.devicePixelRatio && devicePixelRatio >= 2) { var main = document.getElementById('main'); main.style.border = '.5px solid #000000'; } </script>
复制代码
<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
复制代码
*var* viewport = document.querySelector("meta[name=viewport]")
if (window.devicePixelRatio == 1) {
viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
}
if (window.devicePixelRatio == 2) {
viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
}
if (window.devicePixelRatio == 3) {
viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
}
*var* docEl = document.documentElement;
*var* fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;
复制代码
div {
-webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);
}
复制代码
/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
.border-bottom::after {
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
.border-bottom::after {
-webkit-transform: scaleY(0.33);
transform: scaleY(0.33);
}
}
复制代码
div {
height:1px;
background:#000;
-webkit-transform: scaleY(0.5);
-webkit-transform-origin:0 0;
overflow: hidden;
}
复制代码
单列布局
两列自适应布局
圣飞布局和双飞翼布局
flxd布局
弹性盒子是 CSS3 的一种新的布局模式。
CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面须要适应不一样的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。
引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。
base64 是网络上最多见的用于传输 8Bit 字节代码的编码方式之一,要求把每三个 8Bit 的字节转换为四个 6Bit 的字节,Base64 是网络上最多见的用于传输 8Bit 字节代码的编码方式之一。
通俗点讲:将资源本来二进制形式转成以 64 个字符基本单位,所组成的一串字符串。
好比一张图片转成 base64 编码后就像这样,图片直接以 base64 形式嵌入文件中(很长没截完):
- 生成 base64 编码:
图片生成 base64 能够用一些工具,如在线工具,但在项目中这样一个图片这样生成是挺繁琐。
特别说下,webpack 中的 url-loader 能够完成这个工做,能够对限制大小的图片进行 base64 的转换,很是方便。
- 优势:
base64 的图片会随着 html 或者 css 一块儿下载到浏览器,减小了请求.
可避免跨域问题
- 缺点:
老东西(低版本)的 IE 浏览器不兼容。
体积会比原来的图片大一点。
css 中过多使用 base64 图片会使得 css 过大,不利于 css 的加载。
- 适用场景:
应用于小的图片几 k 的,太大的图片会转换后的大小太大,得不偿失。
用于一些 css sprites 不利处理的小图片,如一些能够经过 background-repeat 平铺来作成背景的图片
复制代码
偏移
offsetWidth width + padding + border
offsetHeight height + padding + border
offsetLeft
offsetTop
offsetParent
注意:没有offsetRight和offsetBottom
************************************************************************************************
卷曲
scrollWidth width + padding
scrollHeight 当内部的内容溢出盒子的时候, 顶边框的底部,计算到内容的底部;若是内容没有溢出盒子,计算方式为盒子内部的真实高度(边框到边框)
scrollLeft 这个scroll系列属性不是只读的
scrollTop
scroll()
此函数能够获取卷曲的高度和卷曲的宽度
function myScroll() {
return {
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0
};
}
滚动滚动条的时候触发事件
box(window).onscroll = function () {}
************************************************************************************************
可视
clientWidth 获取的是元素内部的真实宽度 width + padding
clientHeight 边框之间的高度
clientLeft 至关于左边框的宽度 若是元素包含了滚动条,而且滚动条显示在元素的左侧。这时,clientLeft属性会包含滚动条的宽度17px
clientTop 至关于顶边框的宽度
client()
此函数能够获取浏览器可视区域的宽高
function myClient() {
return {
wid: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0,
heit: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0
};
}
\----------------------------------------------------------------------------------------------
@offsetHeight和style.height的区别
demo.style.height只能获取行内样式,若是样式写到了其余地方,甚至根本就没写,便没法获取
style.height是字符串(并且带单位),offsetHeight是数值
demo.style.height能够设置行内样式,offsetHeight是只读属性
所以,通常用demo.offsetHeight来获取某元素的真实宽度/高度,用style.height来设置宽度/高度
\----------------------------------------------------------------------------------------------
@offsetLeft和style.left的区别
1、style.left只能获取行内样式
2、offsetLeft只读,style.left可读可写
3、offsetLeft是数值,style.left是字符串而且有单位px
4、若是没有加定位,style.left获取的数值多是无效的
5、最大区别在于offsetLeft以border左上角为基准,style.left以margin左上角为基准
\----------------------------------------------------------------------------------------------
@scrollHeight和scrollWidth
标签内部实际内容的高度/宽度
不计算边框,若是内容不超出盒子,值为盒子的宽高(不带边框)
若是内容超出了盒子,就是从顶部或左部边框内侧一直到内容a的最外部分
\----------------------------------------------------------------------------------------------
@scrollTop和scrollLeft
被卷去部分的 顶部/左侧 到可视区域 顶部/左侧 的距离
复制代码
在肯定问题缘由和有问题的浏览器后,使用单独的样式表,仅供出现问题的浏览器加载。这种方法须要使用服务器端渲染。
使用已经处理好此类问题的库,好比 Bootstrap。
使用 autoprefixer
自动生成 CSS 属性前缀。
使用 Reset CSS 或 Normalize.css。
优雅的降级:为现代浏览器构建应用,同时确保它在旧版浏览器中正常运行。
渐进式加强:构建基于用户体验的应用,但在浏览器支持时添加新增功能。
利用 caniuse.com 检查特性支持。
使用 autoprefixer
自动生成 CSS 属性前缀。
使用 Modernizr进行特性检测。
{box-sizing: border-box;}
会产生怎样的效果?元素默认应用了box-sizing: content-box
,元素的宽高只会决定内容(content)的大小。
box-sizing: border-box
改变计算元素width
和height
的方式,border
和padding
的大小也将计算在内。
元素的height
= 内容(content)的高度 + 垂直方向的padding
+ 垂直方向border
的宽度
元素的width
= 内容(content)的宽度 + 水平方向的padding
+ 水平方向border
的宽度
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
复制代码
display: -webkit-box;
-webkit-box-orient: vertical;
/* 最多显示几行*/
-webkit-line-clamp: 3;
overflow: hidden;
复制代码
function Person(name) {
var o = new Object;
o.age = name;
o.sayName = function(){
console.log(this.name);
}
return o;
}
// 缺点:对象没法识别
复制代码
function person(name) {
this.name = name;
// 优化点:能够把函数放到外面,这样每次建立实例的时候函数就不会被从新建立
this.sayName = function() {
console.log(this.name)
}
}
// 优势:能够识别对象的类型
// 缺点:每次建立实例函数都要从新建立一遍
复制代码
function Person() {}
person.prototype.name = 'nick';
person.prototype.sayName = function(){
console.log(this.name);
}
var person1 = new Person();
// 优势:方法和属性都共享
// 缺点:不能初始化参数
// 优化版
function Person(name) {}
Person.prototype = {
constructor: Person,
name: 'nick',
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
// 能够经过constructor找到所属构造函数
复制代码
function Person(name) {
this.name = name;
}
person.prototype = function() {
console.log(this.name);
}
const person = new Person('nick');
// 优势:方法共享,变量私有。
复制代码
function Person(name) {
this.name = name;
if (typeof this.sayName != 'function') {
Person.prototype.sayName = function() {
console.log(this.name);
}
}
}
复制代码
function Person(name) {
var o = new Object;
o.age = name;
o.sayName = function(){
console.log(this.name);
}
return o;
}
// 示例
function SpecialArray() {
var values = new Array();
for (var i = 0, len = arguments.length; i < len; i++) {
values.push(arguments[i]);
}
values.toPipedString = function () {
return this.join("|");
};
return values;
}
var colors = new SpecialArray('red', 'blue', 'green');
var colors2 = SpecialArray('red2', 'blue2', 'green2');
console.log(colors);
console.log(colors.toPipedString()); // red|blue|green
console.log(colors2);
console.log(colors2.toPipedString()); // red2|blue2|green2
// 你会发现,其实所谓的寄生构造函数模式就是比工厂模式在建立对象的时候,多使用了一个new,实际上二者的结果是同样的。
复制代码
function Person(name) {
var o = new Object;
o.sayName = function(){
console.log(this.name);
}
return o;
}
// 没有公共属性
复制代码
__proto__
属性指向构造函数的原型对象。(原型.prototype)// 定义构造函数
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1.make);
// expected output: "Eagle"
复制代码
变量必须先声明,再使用
不能对变量执行delete操做
对象的属性名不能重复
禁用eval()
函数的arguments参数
禁用with(){}
复制代码
全局做用域
:在代码中任何地方都能访问到的对象拥有全局做用域。
window对象的属性
定义在最外层的函数或变量
未定义直接赋值的变量
局部做用域
:通常在代码片断内能够访问到的,最多见的如函数内部,因此又称函数做用域
块级做用域
: 在任何一对{}
中的定义的变量在代码块外都不可见。const ary = [1,2,3,4,5,6];
Math.max(1,2,3,4,5,6);
Math.max.call()
1 === '1'
1== '1'
[1] == [2]
复制代码
script
标签没有跨域限制的漏洞,从其余来源动态获取数据,jsonp请求须要服务器支持才能够,jsonp属于非同源get
请求,但可能会遭受xss
攻击W3C
标准,全称是跨域资源共享
,容许浏览器向跨域服务器发送XMLHttpRequest
/Fetch
请求。res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("Content-Type", "application/json;charset=utf-8");
复制代码
Websocket
是一种双向通讯协议,创建链接以后,server
端和client
端都能主动向对方接收/发送数据。了解过,没用过。
浅拷贝
Object.assign()
:将全部可枚举的值从一个或多个源对象复制到目标对象Array.prototype.slice()
返回数组的浅拷贝深拷贝
JSON.parse(JSON.stringify(object))
进行深拷贝,但会有几个问题,好比不能处理正则,不能处理new Date
,不能序列化函数,会忽略undefined
和symbol
总结:
实现一个深拷贝
// 简单深拷贝
const cloneDeep = (source) => {
let target = Array.isArray(source) ? [] : {};
for(const key in source) {
const val = source[key];
if(typeof val === 'object') {
target[key] = cloneDeep(val);
} else {
target[key] = val;
}
}
return target;
}
// 加强版的深拷贝
const isObject = (object) => {
// 兼容数组
return typeof object === 'object' && object != null;
}
const cloneDeep = (source) => {
// 参数校验
if(!isObject(source)) return source;
let target = Array.isArray(source) ? [] : {};
// 哈希表解决循环引用
let hash = new WeakMap();
hash.set(source, target);
for (const key in source) {
// hasOwnProperty: 检测对象自身属性中是否具备指定的属性,返回布尔值
if (source.hasOwnProperty(key)) {
if(typeof source[key] === 'object') {
// 递归实现深拷贝
target[key] = cloneDeep(source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
}
var a = {
name: "muyiy",
book: {
title: "You Don't Know JS",
price: "45",
demo: {
demo: {
demo: {}
},
demo1: {
demo: {}
},
demo2: {
demo: {}
}
}
},
a1: undefined,
a2: null,
a3: 123
}
var b = cloneDeep(a);
a.name = "高级前端进阶";
a.book.price = "55";
a.circleRef = a;
b.book.demo.demo.demo.a = 2;
console.log(a);
console.log(b);
复制代码
原型
prototype
属性,这是属性是指向构造函数
的原型对象
,这个对象包含全部实例共享的属性和方法。constructor
属性,这个属性指向所关联的构造函数。__proto__
属性[非标准的方法],这个属性指向构造函数的原型prototype
原型链
__proto__
属性去原型上查找,若是尚未找到则会在构造函数的原型的__proto__
中查找,这样一层层向上查找就会造成一个做用域链,称为原型链
为何要有原型链
手绘原型图

event.stopPropagation()
//非标准,已废弃
event.cancelBubble=false; // IE
复制代码
event.preventDefault()
//非标准,已废弃
event.returnValue=false; //IE
复制代码
let getJson = url => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return;
if (xhr.readyState === 4 && 200 === xhr.status) {
resolve(xhr.responseText);
} else {
reject();
}
};
xhr.send();
});
};
getJson('/login').then(function (res) {
return getJson('/order');
}).then(function(res){
console.log(res);
}).catch(function (err) {
console.log('error')
})
复制代码
let xhr = new XMLHttpRequest();
xhr.open('get', 'http://xxx.com');
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return;
if (200 === xhr.status) {
console.log(xhr.responseText)
}
};
xhr.send();
复制代码
指的是某个函数在某段时间内,不管触发了多少次回调,都只执行最后一次。
实现方案 使用定时器,函数第一次执行时设定一个定时器,以后调用时发现已经设定过定时器就清空以前的定时器,并从新设定一个新的定时器,若是存在没有被清空的定时器,当定时器计时结束后触发函数执行
示例
/** * 延迟执行 * fn: 须要防抖的函数 * wait: 时间间隔 * */
function debounce(fn, wait = 50) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, wait)
}
}
/** * 当即执行 * fn: 须要防抖的函数 * wait: 时间间隔 * */
function debounce(fn, wait = 50) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
if (callNow) fn.apply(this, args);
}
}
复制代码
函数节流指的是某个函数在必定时间间隔内只执行一次,在这间隔内无视后来产生的函数调用请求
实现方案
每次执行时设定一个上次执行的时间戳,判断是否已到执行时间,若是到了就执行。
设定一个定时器,若是定时器存在则直接返回,等待异步执行完毕清空定时器。
示例
// 时间戳
const throttle = (fn, wait = 50) => {
// 上一次执行 fn 的时间
let previous = 0;
// 将 throttle 处理结果看成函数返回
return function(...args) {
// 获取当前时间,转换成时间戳,单位毫秒
let now = +new Date();
// 将当前时间和上一次执行函数的时间进行对比
// 大于等待时间就把 previous 设置为当前时间并执行函数 fn
if (now - previous > wait) {
previous = now
fn.apply(this, args)
}
}
}
// 定时器版本
const throttle = function(fn, wait) {
let timer = null;
return function(...args) {
if (timer) return;
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, wait);
};
}
复制代码
const ary1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
const ary2 = ary1.filter((element, index, ary) => {
// 判断索引是否相等
return ary.indexOf(element) === index;
}) // => [1, 2, 3, 5, 4]
const ary3 = [...new Set(arr1)]
// => [1, 2, 3, 5, 4]
const ary4 = Array.from(new Set(arr1))
// => [1, 2, 3, 5, 4]
const ary5 = arr1.reduce((prev, next) => {
return prev.includes(next) ? prev : [...prev, next];
}, []);
复制代码
_proto_
属性指向构造函数的原型对象。(原型.prototype)// 定义构造函数
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1.make);
// expected output: "Eagle"
复制代码
call
:使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。fun.call(thisArg[,arg1[,arg2[, ...]]])
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name); //=>"cheese"
复制代码
apply
: 调用一个具备给定this值的函数,以及做为一个数组(或相似数组对象)提供的参数fun.apply(thisArg, argsArray)
var numbers = [5, 6, 2, 3, 7];
// 最大值
var max = Math.max.apply(null, numbers);
console.log(max); //=> 7
// 最小值
var min = Math.min.apply(null, numbers);
console.log(min); //=> 2
复制代码
bind
:建立一个新的函数,在bind
被调用时,这个新函数的this被bind的第一个参数指定,其他的参数将做为新函数的参数供调用时使用。function.bind(thisArg[,arg1[,arg2[, ...]]])
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); // => undefined
var boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // => 42
复制代码
console.log(Array.from('foo'));
// expected output: Array ["f", "o", "o"]
console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]
复制代码
Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false
复制代码
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
console.log(array1.concat(array2));
// expected output: Array ["a", "b", "c", "d", "e", "f"]
复制代码
var array1 = [1, 30, 39, 29, 10, 13];
function isBelowThreshold(currentValue) {
return currentValue < 40;
}
console.log(array1.every(isBelowThreshold));
// expected output: true
复制代码
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
复制代码
var array = [1, 2, 3, 4, 5];
var even = function(element) {
// checks whether an element is even
return element % 2 === 0;
};
console.log(array.some(even));
// expected output: true
复制代码
undefined
。var array1 = [5, 12, 8, 130, 44];
var found = array1.find(function(element) {
return element > 10;
});
console.log(found);
// expected output: 12
复制代码
var array1 = [5, 12, 8, 130, 44];
function isLargeNumber(element) {
return element > 13;
}
console.log(array1.findIndex(isLargeNumber));
// expected output: 3
复制代码
var array1 = ['a', 'b', 'c'];
array1.forEach(function(element) {
console.log(element);
});
// expected output: "a"
// expected output: "b"
// expected output: "c"
复制代码
var array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
复制代码
var array1 = [1, 2, 3];
console.log(array1.includes(2));
// expected output: true
var pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));
// expected output: true
console.log(pets.includes('at'));
// expected output: false
复制代码
var beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
console.log(beasts.indexOf('bison'));
// expected output: 1
// start from index 2
console.log(beasts.indexOf('bison', 2));
// expected output: 4
console.log(beasts.indexOf('giraffe'));
// expected output: -1
复制代码
var animals = ['Dodo', 'Tiger', 'Penguin', 'Dodo'];
console.log(animals.lastIndexOf('Dodo'));
// expected output: 3
console.log(animals.lastIndexOf('Tiger'));
// expected output: 1
复制代码
var elements = ['Fire', 'Air', 'Water'];
console.log(elements.join());
// expected output: "Fire,Air,Water"
console.log(elements.join(''));
// expected output: "FireAirWater"
console.log(elements.join('-'));
// expected output: "Fire-Air-Water"
复制代码
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity 做为深度,展开任意深度的嵌套数组
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6]
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
复制代码
var arr1 = [1, 2, 3, 4];
arr1.map(x => [x * 2]);
// [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]
// 只会将 flatMap 中的函数返回的数组 “压平” 一层
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]
let arr = ["今每天气不错", "", "早上好"]
arr.map(s => s.split(""))
// [["今", "天", "天", "气", "不", "错"],[],["早", "上", "好"]]
arr.flatMap(s => s.split(''));
// ["今", "天", "天", "气", "不", "错", "早", "上", "好"]
复制代码
var array1 = ['a', 'b', 'c'];
var iterator = array1.keys();
for (let key of iterator) {
console.log(key); // expected output: 0 1 2
}
复制代码
const array1 = ['a', 'b', 'c'];
const iterator = array1.values();
for (const value of iterator) {
console.log(value); // expected output: "a" "b" "c"
}
复制代码
var plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];
console.log(plants.pop());
// expected output: "tomato"
console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage", "kale"]
plants.pop();
console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage"]
复制代码
const animals = ['pigs', 'goats', 'sheep'];
const count = animals.push('cows');
console.log(count);
// expected output: 4
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows"]
animals.push('chickens', 'cats', 'dogs');
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]
复制代码
var array1 = [1, 2, 3];
var firstElement = array1.shift();
console.log(array1);
// expected output: Array [2, 3]
console.log(firstElement);
// expected output: 1
复制代码
var array1 = [1, 2, 3];
console.log(array1.unshift(4, 5));
// expected output: 5
console.log(array1);
// expected output: Array [4, 5, 1, 2, 3]
复制代码
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
复制代码
const array1 = [[0, 1], [2, 3], [4, 5]].reduceRight(
(accumulator, currentValue) => accumulator.concat(currentValue)
);
console.log(array1);
// expected output: Array [4, 5, 2, 3, 0, 1]
复制代码
var array1 = ['one', 'two', 'three'];
console.log('array1: ', array1);
// expected output: Array ['one', 'two', 'three']
var reversed = array1.reverse();
console.log('reversed: ', reversed);
// expected output: Array ['three', 'two', 'one']
/* Careful: reverse is destructive. It also changes the original array */
console.log('array1: ', array1);
// expected output: Array ['three', 'two', 'one']
复制代码
var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4));
// expected output: Array ["camel", "duck"]
console.log(animals.slice(1, 5));
// expected output: Array ["bison", "camel", "duck", "elephant"]
复制代码
var months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at index 1
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'June']
months.splice(4, 1, 'May');
// replaces 1 element at index 4
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'May']
复制代码
var months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
var array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
复制代码
var array1 = [1, 'a', new Date('21 Dec 1997 14:12:00 UTC')];
var localeString = array1.toLocaleString('en', {timeZone: "UTC"});
console.log(localeString);
// expected output: "1,a,12/21/1997, 2:12:00 PM",
// This assumes "en" locale and UTC timezone - your results may vary
复制代码
var array1 = [1, 2, 'a', '1a'];
console.log(array1.toString());
// expected output: "1,2,a,1a"
复制代码
console.log(String.fromCharCode(189, 43, 190, 61));
// expected output: "½+¾="
复制代码
console.log(String.fromCodePoint(9731, 9733, 9842, 0x2F804));
// expected output: "☃★♲你"
复制代码
var anyString = "Brave new world";
console.log("The character at index 0 is '" + anyString.charAt(0) + "'");
console.log("The character at index 1 is '" + anyString.charAt(1) + "'");
console.log("The character at index 2 is '" + anyString.charAt(2) + "'");
console.log("The character at index 3 is '" + anyString.charAt(3) + "'");
console.log("The character at index 4 is '" + anyString.charAt(4) + "'");
console.log("The character at index 999 is '" + anyString.charAt(999) + "'");
复制代码
var sentence = 'The quick brown fox jumps over the lazy dog.';
var index = 4;
console.log('The character code ' + sentence.charCodeAt(index) + ' is equal to ' + sentence.charAt(index));
// expected output: "The character code 113 is equal to q"
复制代码
'ABC'.codePointAt(1); // 66
'\uD800\uDC00'.codePointAt(0); // 65536
'XYZ'.codePointAt(42); // undefined
复制代码
var hello = "Hello, ";
console.log(hello.concat("Kevin", " have a nice day.")); /* Hello, Kevin have a nice day. */
复制代码
const str1 = 'Saturday night plans';
console.log(str1.startsWith('Sat'));
// expected output: true
console.log(str1.startsWith('Sat', 3));
// expected output: false
复制代码
const str1 = 'Cats are the best!';
console.log(str1.endsWith('best', 17));
// expected output: true
const str2 = 'Is this a question';
console.log(str2.endsWith('?'));
// expected output: false
复制代码
var str = 'To be, or not to be, that is the question.';
console.log(str.includes('To be')); // true
console.log(str.includes('question')); // true
console.log(str.includes('nonexistent')); // false
console.log(str.includes('To be', 1)); // false
console.log(str.includes('TO BE')); // false
复制代码
var paragraph = 'The quick brown fox jumps over the lazy dog. If the dog barked, was it really lazy?';
var searchTerm = 'dog';
var indexOfFirst = paragraph.indexOf(searchTerm);
console.log('The index of the first "' + searchTerm + '" from the beginning is ' + indexOfFirst);
// expected output: "The index of the first "dog" from the beginning is 40"
console.log('The index of the 2nd "' + searchTerm + '" is ' + paragraph.indexOf(searchTerm, (indexOfFirst + 1)));
// expected output: "The index of the 2nd "dog" is 52"
复制代码
"canal".lastIndexOf("a") // returns 3
"canal".lastIndexOf("a",2) // returns 1
"canal".lastIndexOf("a",0) // returns -1
"canal".lastIndexOf("x") // returns -1
// 区分大小写
"Blue Whale, Killer Whale".lastIndexOf("blue"); // returns -1
复制代码
// The letter "a" is before "c" yielding a negative value
'a'.localeCompare('c');
// -2 or -1 (or some other negative value)
// Alphabetically the word "check" comes after "against" yielding a positive value
'check'.localeCompare('against');
// 2 or 1 (or some other positive value)
// "a" and "a" are equivalent yielding a neutral value of zero
'a'.localeCompare('a');
// 0
复制代码
var str = 'For more information, see Chapter 3.4.5.1';
var re = /see (chapter \d+(\.\d)*)/i;
var found = str.match(re);
console.log(found);
// logs [ 'see Chapter 3.4.5.1',
// 'Chapter 3.4.5.1',
// '.1',
// index: 22,
// input: 'For more information, see Chapter 3.4.5.1' ]
// 'see Chapter 3.4.5.1' 是整个匹配。
// 'Chapter 3.4.5.1' 被'(chapter \d+(\.\d)*)'捕获。
// '.1' 是被'(\.\d)'捕获的最后一个值。
// 'index' 属性(22) 是整个匹配从零开始的索引。
// 'input' 属性是被解析的原始字符串。
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);
console.log(matches_array);
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
复制代码
const regexp = RegExp('foo*','g');
const str = 'table football, foosball';
while ((matches = regexp.exec(str)) !== null) {
console.log(`Found ${matches[0]}. Next starts at ${regexp.lastIndex}.`);
// expected output: "Found foo. Next starts at 9."
// expected output: "Found foo. Next starts at 19."
}
//===
const regexp = RegExp('foo*','g');
const str = 'table football, foosball';
let matches = str.matchAll(regexp);
for (const match of matches) {
console.log(match);
}
// Array [ "foo" ]
// Array [ "foo" ]
// matches iterator is exhausted after the for..of iteration
// Call matchAll again to create a new iterator
matches = str.matchAll(regexp);
Array.from(matches, m => m[0]);
// Array [ "foo", "foo" ]
复制代码
// Initial string
// U+1E9B: LATIN SMALL LETTER LONG S WITH DOT ABOVE
// U+0323: COMBINING DOT BELOW
var str = "\u1E9B\u0323";
// Canonically-composed form (NFC)
// U+1E9B: LATIN SMALL LETTER LONG S WITH DOT ABOVE
// U+0323: COMBINING DOT BELOW
str.normalize("NFC"); // "\u1E9B\u0323"
str.normalize(); // same as above
// Canonically-decomposed form (NFD)
// U+017F: LATIN SMALL LETTER LONG S
// U+0323: COMBINING DOT BELOW
// U+0307: COMBINING DOT ABOVE
str.normalize("NFD"); // "\u017F\u0323\u0307"
// Compatibly-composed (NFKC)
// U+1E69: LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
str.normalize("NFKC"); // "\u1E69"
// Compatibly-decomposed (NFKD)
// U+0073: LATIN SMALL LETTER S
// U+0323: COMBINING DOT BELOW
// U+0307: COMBINING DOT ABOVE
str.normalize("NFKD"); // "\u0073\u0323\u0307"
复制代码
'abc'.padEnd(10); // "abc "
'abc'.padEnd(10, "foo"); // "abcfoofoof"
'abc'.padEnd(6, "123456"); // "abc123"
'abc'.padEnd(1); // "abc"
复制代码
'abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
'abc'.padStart(8, "0"); // "00000abc"
'abc'.padStart(1); // "abc"
复制代码
"abc".repeat(-1) // RangeError: repeat count must be positive and less than inifinity
"abc".repeat(0) // ""
"abc".repeat(1) // "abc"
"abc".repeat(2) // "abcabc"
"abc".repeat(3.5) // "abcabcabc" 参数count将会被自动转换成整数.
"abc".repeat(1/0) // RangeError: repeat count must be positive and less than inifinity
({toString : () => "abc", repeat : String.prototype.repeat}).repeat(2)
//"abcabc",repeat是一个通用方法,也就是它的调用者能够不是一个字符串对象.
复制代码
var p = 'The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?';
var regex = /dog/gi;
console.log(p.replace(regex, 'ferret'));
// expected output: "The quick brown fox jumps over the lazy ferret. If the ferret reacted, was it really lazy?"
console.log(p.replace('dog', 'monkey'));
// expected output: "The quick brown fox jumps over the lazy monkey. If the dog reacted, was it really lazy?"
复制代码
var paragraph = 'The quick brown fox jumps over the lazy dog. If the dog barked, was it really lazy?';
// any character that is not a word character or whitespace
var regex = /[^\w\s]/g;
console.log(paragraph.search(regex));
// expected output: 43
console.log(paragraph[paragraph.search(regex)]);
// expected output: "."
复制代码
var str = 'The quick brown fox jumps over the lazy dog.';
console.log(str.slice(31));
// expected output: "the lazy dog."
console.log(str.slice(4, 19));
// expected output: "quick brown fox"
console.log(str.slice(-4));
// expected output: "dog."
console.log(str.slice(-9, -5));
// expected output: "lazy"
复制代码
var str = 'The quick brown fox jumps over the lazy dog.';
var words = str.split(' ');
console.log(words[3]);
// expected output: "fox"
var chars = str.split('');
console.log(chars[8]);
// expected output: "k"
var strCopy = str.split();
console.log(strCopy);
// expected output: Array ["The quick brown fox jumps over the lazy dog."]
复制代码
var anyString = "Mozilla";
// 输出 "Moz"
console.log(anyString.substring(0,3));
console.log(anyString.substring(3,0));
console.log(anyString.substring(3,-3));
console.log(anyString.substring(3,NaN));
console.log(anyString.substring(-2,3));
console.log(anyString.substring(NaN,3));
// 输出 "lla"
console.log(anyString.substring(4,7));
console.log(anyString.substring(7,4));
// 输出 ""
console.log(anyString.substring(4,4));
// 输出 "Mozill"
console.log(anyString.substring(0,6));
// 输出 "Mozilla"
console.log(anyString.substring(0,7));
console.log(anyString.substring(0,10));
复制代码
console.log('ALPHABET'.toLocaleLowerCase());
// 'alphabet'
console.log('中文简体 zh-CN || zh-Hans'.toLocaleLowerCase());
// '中文简体 zh-cn || zh-hans'
复制代码
console.log('alphabet'.toLocaleUpperCase()); // 'ALPHABET'
复制代码
console.log('中文简体 zh-CN || zh-Hans'.toLowerCase());
// 中文简体 zh-cn || zh-hans
console.log( "ALPHABET".toLowerCase() );
// "alphabet"
复制代码
console.log( "alphabet".toUpperCase() ); // "ALPHABET"
复制代码
var x = new String("Hello world");
alert(x.toString()) // 输出 "Hello world"
复制代码
var orig = ' foo ';
console.log(orig.trim()); // 'foo'
// 另外一个.trim()例子,只从一边删除
var orig = 'foo ';
console.log(orig.trim()); // 'foo'
复制代码
var greeting = ' Hello world! ';
console.log(greeting);
// expected output: " Hello world! ";
console.log(greeting.trimEnd());
console.log(greeting.trimRight());
// expected output: " Hello world!";
复制代码
var str = " foo ";
alert(str.length); // 8
str = str.trimLeft();
alert(str.length); // 5
document.write( str );
复制代码
x = new String("Hello world");
alert(x.valueOf()) // Displays "Hello world"
复制代码
String.raw`Hi\n${2+3}!`;
// 'Hi\n5!',Hi 后面的字符不是换行符,\ 和 n 是两个不一样的字符
String.raw `Hi\u000A!`;
// "Hi\\u000A!",同上,这里获得的会是 \、u、0、0、0、A 6个字符,
// 任何类型的转义形式都会失效,保留原样输出,不信你试试.length
let name = "Bob";
String.raw `Hi\n${name}!`;
// "Hi\nBob!",内插表达式还能够正常运行
// 正常状况下,你也许不须要将 String.raw() 看成函数调用。
// 可是为了模拟 `t${0}e${1}s${2}t` 你能够这样作:
String.raw({ raw: 'test' }, 0, 1, 2); // 't0e1s2t'
// 注意这个测试, 传入一个 string, 和一个相似数组的对象
// 下面这个函数和 `foo${2 + 3}bar${'Java' + 'Script'}baz` 是相等的.
String.raw({
raw: ['foo', 'bar', 'baz']
}, 2 + 3, 'Java' + 'Script'); // 'foo5barJavaScriptbaz'
复制代码
let
关键字,用于声明只在块级做用域起做用的变量const
关键字,用于声明常量Symbol
数据类型,定义一个独一无二的值for...of
遍历器,可遍历具备iterator
(迭代器)接口的数据类型Set
结构,用于存储不重复成员值的集合Map
结构Promise
对象,一种异步操做的解决方案,更合理、规范的操做异步处理。class
类,定义类和更简便的实现类的继承var
在任何语句执行前就完成了声明和初始化funciton
声明、初始化和赋值在一开始就所有完成,函数变量提高的优先级更高let
先声明但并无初始化,只有解析到let
那一行才会进入初始化阶段。若是在此做用域前提早访问,则报错xx is not defined
, 暂时性死区,在相同做用域内不容许重复声明同一个变量const
和let
区别在于const
声明的是一个只读常亮,一旦声明后就不能改变一、遍历器(Iterator)是一种接口,为各类不一样的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就能够完成遍历操做(即依次处理该数据结构的全部成员)
二、Iterator 的做用有三个:
三、默认部署了 Iterator 的数据有 Array、Map、Set、String、TypedArray、arguments、NodeList 对象,ES6 中有的是 Set、Map、
// 一、类的基本定义
class Parent {
constructor(name = "小白") {
this.name = name;
}
}
//=====================================
// 二、生成一个实例
let g_parent = new Parent();
console.log(g_parent); //{name: "小白"}
let v_parent = new Parent("v"); // 'v'就是构造函数name属性 , 覆盖构造函数的name属性值
console.log(v_parent); // {name: "v"}
//=====================================
// 三、继承
class Parent {
//定义一个类
constructor(name = "小白") {
this.name = name;
}
}
class Child extends Parent {}
console.log("继承", new Child()); // 继承 {name: "小白"}
//=====================================
// 四、继承传递参数
class Parent {
//定义一个类
constructor(name = "小白") {
this.name = name;
}
}
class Child extends Parent {
constructor(name = "child") {
// 子类重写name属性值
super(name); // 子类向父类修改 super必定放第一行
this.type = "preson";
}
}
console.log("继承", new Child("hello")); // 带参数覆盖默认值 继承{name: "hello", type: "preson"}
//=====================================
// 五、ES6从新定义的ES5中的访问器属性
class Parent {
//定义一个类
constructor(name = "小白") {
this.name = name;
}
get longName() {
// 属性
return "mk" + this.name;
}
set longName(value) {
this.name = value;
}
}
let v = new Parent();
console.log("getter", v.longName); // getter mk小白
v.longName = "hello";
console.log("setter", v.longName); // setter mkhello
//=====================================
// 六、类的静态方法
class Parent {
//定义一个类
constructor(name = "小白") {
this.name = name;
}
static tell() {
// 静态方法:经过类去调用,而不是实例
console.log("tell");
}
}
Parent.tell(); // tell
//=====================================
// 七、类的静态属性:
class Parent {
//定义一个类
constructor(name = "小白") {
this.name = name;
}
static tell() {
// 静态方法:经过类去调用,而不是实例
console.log("tell"); // tell
}
}
Parent.type = "test"; // 定义静态属性
console.log("静态属性", Parent.type); // 静态属性 test
let v_parent = new Parent();
console.log(v_parent); // {name: "小白"} 没有tell方法和type属性
复制代码
es6 是一个新的标准,它包含了许多新的语言特性和库,是 JS 最实质性的一次升级。
好比'箭头函数'、'字符串模板'、'generators(生成器)'、'async/await'、'解构赋值'、'class'等等,还有就是引入 module 模块的概念。
箭头函数可让 this 指向固定化,这种特性颇有利于封装回调函数
this
对象是定义是所在的对象,而不是使用时所在的对象new
命令function postJson(url, data) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.onreadystatuschange = () => {
if(xhr.readyState !== 4) return;
if(xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject('请求失败')
}
}
xhr.send(JSON.stringify(data));
})
}
复制代码
key给每一个vnode(虚拟节点)增长一个惟一ID,在更新组件是判断两个节点是否相同。相同就复用,不相同就删除旧建立新的。
虽然带上key会增长开销,可是对于用户来讲基本感觉不到差距,并且能保证组件状态正确。
不带key时节点可以复用,省去了销毁/建立组件的开销,同时只须要修改DOM文本内容而不是移除/添加节点。
这种模式diff速度可能会更快,但也会带来一些隐藏的反作用,好比可能不会产生过渡效果,或者在某些节点有绑定数据(表单)状态,会出现状态错位。 这种模式只适用于渲染简单的无状态组件
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性的setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:须要 observe
的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter
和 getter
这样的话,给这个对象的某个值赋值,就会触发setter
,那么就能监听到了数据变化
第二步:compile
解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新视图
第三步:Watcher
订阅者是Observer
和Compile
之间通讯的桥梁,主要作的事情是:
update()
方法第四步:MVVM做为数据绑定的入口,整合Observer、Compile和Watcher三者,经过Observer来监听本身的model数据变化,经过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通讯桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变动的双向绑定效果。
Vue生命周期一共分为8个阶段
beforeCreated
阶段,实例的$el
、data
和methods
都未初始化。this
指向建立的实例created
阶段,实例的data
和methods
都初始化完成,但 DOM
节点还未挂载,不能访问到$el
属性,$ref
属性为空数组beforeMount
阶段,实例找到相对应的template
并编译成render
函数mouted
阶段,实例将el
挂载到DOM
上,能够获取到DOM
节点,$ref
属性能够访问data
变化时,会触发beforeUpdate
和updated
destroy
方法后,data
的改变不会再触发周期函数,此时Vue实例已经解除了事件监听
和DOM绑定
,但DOM结构依然存在。on
自定义事件绑定方法来接收值,子组件经过$emit触发自定义事件传递参数给父组件keep-alive
的做用是什么小图片转base64
静态下图片使用雪碧图
生成环境屏蔽sourceMap
开启gzip压缩文件,减小文件大小
第三方依赖按需加载
vue-router懒加载/异步路由
代码优化
骨架屏
State
,Getter
,Mutation
,Action
,Module
state
为单一状态数,是数据源存放的地方(对应Vue
对象里的data
),存放的数据是响应式的,Vue组件从store
读取数据,当store
中的数据发生变化则依赖数据的组件也会发生变化。mapState
辅助函数把state
映射到组件的computed
计算属性上store.commit
store.dispatch
触发异步组件
component: resolve => require(['../components/PromiseDemo'], resolve)
import
const ImportFuncDemo2 = () => import('../components/ImportFuncDemo2')
component: ImportFuncDemo2
webpackrequire.ensure()
component: resolve => require.ensure([], () => resolve(require('../components/PromiseDemo')), 'demo')
参考:vue项目按需加载
router-link
建立a标签来定义导航连接router.push({ path: 'home' })
全局守卫
router.beforeEach
router.beforeResolve
(2.5.0 新增)router.afterEach
路由独享守卫
beforeEnter
组件守卫
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
Vue源码
项目中遇到的问题
微信小程序项目结构主要有四个文件类型
WXML
: WeiXin Markup Language
是框架设计的一套标签语言,结合基础组件、事件系统,能够构建出页面的结构。内部主要是微信本身定义的一套组件WXSS
: WeiXin Style Sheets
是一套样式语言,用于描述 WXML
的组件样式js
: 逻辑处理,网络请求json
: 小程序设置,如页面注册,页面标题及tabBar
主要文件
app.json
必需要有这个文件,若是没有这个文件,项目没法运行,由于微信框架把这个做为配置文件入口,整个小程序的全局配置。包括页面注册,网络设置,以及小程序的 window
背景色,配置导航条样式,配置默认标题app.js
必需要有这个文件,没有也是会报错!可是这个文件建立一下就行 什么都不须要写之后咱们能够在这个文件中监听并处理小程序的生命周期函数、声明全局变量app.wxss
可选微信小程序采用
JavaScript
、WXML
、WXSS
三种技术进行开发,本质就是一个单页面应用,全部的页面渲染和事件处理,都在一个页面内进行,但又能够经过微信客户端调用原生的各类接口
微信的架构,是数据驱动的架构模式,它的
UI
和数据是分离的,全部的页面更新,都须要经过对数据的更改来实现
小程序分为两个部分
webview
和appService
。其中webview
主要用来展示UI
,appService
有来处理业务逻辑、数据及接口调用。它们在两个进程中运行,经过系统层JSBridge
实现通讯,实现UI
的渲染、事件的处理
小程序直接 this.data
的属性是不能够同步到视图的,必须调用:
this.setData({
// 这里设置
})
复制代码
WXSS
和CSS
相似,不过在CSS
的基础上作了一些补充和修改
rpx
rpx
是响应式像素,能够根据屏幕宽度进行自适应。规定屏幕宽为 750rpx
。如在 iPhone6
上,屏幕宽度为 375px
,共有 750
个物理像素,则 750rpx = 375px = 750
物理像素
@import
标识符来导入外联样式。@import
后跟须要导入的外联样式表的相对路径,用;表示语句结束/** index.wxss **/
@import './base.wxss';
.container{
color: red;
}
复制代码
app.js
文件中定义全局变量 globalData
, 将须要存储的信息存放在里面// app.js
App({
// 全局变量
globalData: {
userInfo: null
}
})
复制代码
使用的时候,直接使用 getApp()
拿到存储的信息
wx.navigateTo
与 wx.redirectTo
的时候,能够将部分数据放在 url
里面,并在新页面 onLoad
的时候初始化//pageA.js
// Navigate
wx.navigateTo({
url: '../pageD/pageD?name=raymond&gender=male',
})
// Redirect
wx.redirectTo({
url: '../pageD/pageD?name=raymond&gender=male',
})
// pageB.js
...
Page({
onLoad: function(option){
console.log(option.name + 'is' + option.gender)
this.setData({
option: option
})
}
})
复制代码
须要注意的问题:
wx.navigateTo
和 wx.redirectTo
不容许跳转到 tab
所包含的页面
onLoad
只执行一次
Storage
相关onLoad
页面加载时触发。一个页面只会调用一次,能够在 onLoad
的参数中获取打开当前页面路径中的参数onShow()
页面显示/切入前台时触发onReady()
页面初次渲染完成时触发。一个页面只会调用一次,表明页面已经准备稳当,能够和视图层进行交互onHide()
页面隐藏/切入后台时触发。 如 navigateTo
或底部 tab
切换到其余页面,小程序切入后台等onUnload()
页面卸载时触发。如 redirectTo
或 navigateBack
到其余页面时详见 生命周期回调函数
wx.request({
url: 'test.php', //仅为示例,并不是真实的接口地址
data: {
x: '' ,
y: ''
},
success: function(res) {
console.log(res.data)
}
})
// promise
复制代码
参考 这里
一、提升页面加载速度
二、用户行为预测
三、减小默认 data
的大小
四、组件化方案
优点
App
低缺点
App
要深不少小程序支持大部分
ES6
语法
Promise
异步若是开发者拥有多个移动应用、网站应用、和公众账号(包括小程序),可经过
unionid
来区分用户的惟一性,由于只要是同一个微信开放平台账号下的移动应用、网站应用和公众账号(包括小程序),用户的unionid
是惟一的。换句话说,同一用户,对同一个微信开放平台下的不一样应用,unionid
是相同的
config
中的 window
配置 enablePullDownRefresh
Page
中定义 onPullDownRefresh
钩子函数,到达下拉刷新条件后,该钩子函数执行,发起请求方法wx.stopPullDownRefresh
中止下拉刷新参考 这里
相同点:首先他们都是做为点击事件函数,就是点击时触发。在这个做用上他们是同样的,能够不作区分
不一样点:他们的不一样点主要是 bindtap
是不会阻止冒泡事件的,catchtap
是阻值冒泡的
wx.navigateTo()
, wx.redirectTo()
, wx.switchTab()
, wx.navigateBack()
, wx.reLaunch()
的区别wx.navigateTo()
:保留当前页面,跳转到应用内的某个页面。可是不能跳到 tabbar
页面wx.redirectTo()
:关闭当前页面,跳转到应用内的某个页面。可是不容许跳转到 tabbar
页面wx.switchTab()
:跳转到 abBar
页面,并关闭其余全部非 tabBar
页面wx.navigateBack()
关闭当前页面,返回上一页面或多级页面。可经过 getCurrentPages()
获取当前的页面栈,决定须要返回几层wx.reLaunch()
:关闭全部页面,打开到应用内的某个页面JS 采用的是双精度版本
咱们计算机的信息所有转化为二进制进行存储的,那么0.1的二进制表示的是一个无限循环小数, 该版本的 JS 采用的是浮点数标准须要对这种无限循环的二进制进行截取,从而致使了精度丢失, 形成了0.1再也不是0.1,截取以后0.1变成了 0.100...001,0.2变成了0.200...002。因此二者相加的数大于0.3。
由于在输入内容进行转换的时候,二进制转换成十进制,而后十进制转换成字符串, 在这个转换的过程当中发生了取近似值,因此打印出来的是一个近似值。
// 特定需求页面,好比评论页面,输入框在顶部之类的
const interval = setInterval(function() {
document.body.scrollTop = 0;
}, 100)
// 注意关闭页面或者销毁组件的时候记得清空定时器
clearInterval(interval);
复制代码
/**使用postcss的autoprefixer插件,自动添加浏览器内核前缀, 而且增长更低浏览器版本的配置,自动添加flex老版本的属性和写法**/
autoprefixer({
browsers: [
'iOS >= 6', // 特殊处理支持低版本IOS
'Safari >= 6', // 特殊处理支持低版本Safari
],
}),
复制代码
<meta content="telephone=no" name="format-detection" />
复制代码
<meta content="email=no" name="format-detection" />
复制代码
缘由:click事件要等待是不是双击事件,会有300ms的延迟
解决:使用touchstart/touchend或者使用zepto的tap事件替代click