HTML5
新个性
语义化标签:header, footer, article, section, nav, menu, hgroup等
更多的HTML5表单个性,例如calendar、date、time、email、url、search,
反对Video
新增Local Storage,应用Local Storage能够永恒存储大的数据片段在客户端(除非被动删除),目前大部分浏览器曾经反对
挪动端适配计划
viewport缩放计划
在写 HTML、CSS 对设计稿进行还原时不关注屏幕尺寸的差别,而是间接按设计稿的标注来开发。比方设计稿里标注的文字字号是30px,CSS里就设置文字字号30px。
页面开发好后,在 HTML 的 head 标签里退出
<meta name="viewport" content="width={设计稿宽度}, initial-scale={屏幕逻辑像素宽度/设计稿宽度}" >
。通过js动静计算屏幕的逻辑像素宽度,initial-scale:网页初始缩放值
动静rem计划
在应用单位管制页面元素大小时,能够应用固定单位 px,也能够应用绝对单位 rem。2rem 等于 html 标签 font-size 的 2 倍。
基于这个原理,对于须要适配屏幕等比缩放的元素能够选用 rem 作为单位,对于不须要等比缩放的元素仍旧应用 px 作为单位。
只有调整html标签的 font-size,就能让所有应用 rem 单位的元素跟随着发生变化,而应用 px 单位的元素不受影响。
插件:postcss
例如:设计师交付的设计稿宽度是 750px,设计稿上一个 div 的标注尺寸是 375px(宽度是设计稿宽度的一半)。咱们能够
- 设置 html 的 font-size 为 100*屏幕宽度/设计稿宽度
- 在写 CSS 时设置 div 的宽度是 3.75rem(计算时用设计稿标注值除以100),边框宽度为 1px
假如用户在逻辑像素宽度是 375px 的设施上关上页面,则 html 的 font-size 是100*375/750 = 50px,div 的宽度是 3.75rem ,即 187.5px 正好是屏幕宽度的一半。
假如用户在逻辑像素宽度是 428px 的设施上关上页面,则 html 的 font-size 是100*428/750 = 57.07px,div的宽度是 3.75rem ,即 214px 正好是屏幕宽度的一半。
注:font-size= 100 只是为了不便就是,事实上能够取任意值
<script> const WIDTH = 750 //如果是尺寸的设计稿在这里批改 const setView = () => { //设置html标签的 fontSize * 屏幕宽度 / 设计稿宽度 document.documentElement.style.fontSize = (100*screen.width/WIDTH) + 'px' } window.onresize = setView; // 如果窗口大小产生扭转,就触发 setView 事件 setView()</script>
vm适配计划
vw 是绝对单位,1vw 示意屏幕宽度的 1%。基于此,咱们能够把所有须要适配屏幕大小等比缩放的元素都应用 vw 作为单位。不须要缩放的元素应用 px 做单位。
媒体查问
应用css media工具不同的屏幕大小适配不同的款式
盒子模型
规范盒子模型:(box-sizing:content-box;)
padding和border不被蕴含在定义的width和height之内,对象的理论宽度等于设置的width值和border、padding之和
IE盒子模型:(box-sizing:border-box;)
padding和border被蕴含在定义的width和height之内。对象的理论宽度就等于设置的width值,即便定义有border和padding也不会扭转对象的理论宽度
CSS3
新增的一些个性
圆角border-radius,暗影box-shadow,文字暗影text-shadow,
线性突变(gradient),旋转(transform)
媒体查问(@media),多栏布局(colums)
边框图片:border-image
CSS3动画
产考
https://zhuanlan.zhihu.com/p/...
css三栏布局(圣杯布局),左右固定宽度,两头自适应
相对定位法
原理是将左右两边应用absolute定位,因为相对定位使其脱离文档流,前面的 middle 会天然流动到他们下面,而后应用margin属性,留出左右元素的宽度,既能够使两头元素自适应屏幕宽度。
<div class="main"> <div class="left">left</div> <div class="middle">middle</div> <div class="right">right</div></div>
本身浮动法
原理就是对左右别离左浮动和右浮动,float使左右两个元素脱离文档流,两头元素失常在失常文档流中。对两头文档流应用margin指定左右外边距进行定位。
该布局法的有余是三个元素的程序,middle肯定要放在最初,middle占据文档流地位,所以肯定要放在最初,左右两个元素地位没有关系。当浏览器窗口很小的时候,左边元素会被挤到下一行。
<div class="main"> <div class="left">left</div> <div class="right">right</div> <div class="middle">middle</div></div>
flex 布局法
原理就是为父元素增加款式display:flex,左右固定宽度,两头设置flex:1,middle肯定要放在两头。
<div class="main"> <div class="left">left</div> <div class="middle">middle</div> <div class="right">right</div></div>
Css浏览器兼容
依据不同的浏览器内核增加不同的css前缀
Chrome 内核 之前Webkit,已改Blink内核
FireFox火狐 内核 Gecko
Ssfari苹果 内核 Webkit
IE浏览器 内核 Trident
Opera欧朋 内核 现已改用Google Chrome的Blink内核
-moz-
火狐浏览器-Webkit-
safari谷歌浏览器等应用Webkit引擎的浏览器-o-
Opera浏览器(晚期)-ms-
IE
实现垂直居中
对已知高度块级元素进行垂直居中
- 相对定位,配合top:50%和负margin-top(元素高度一半)进行垂直居中
.content{ position: absolute; top: 50%; left: 50%; margin-top: -10em; /* 为元素height/2 */ margin-left: -10em; width: 20em; height: 20em; background-color: aqua;}
- 相对定位,配合top:0;bottom:0;和margin:auto进行垂直居中
.content{ position: absolute; margin:auto; top: 0; bottom: 0; left: 0; right: 0; height: 200px; /*要求指明元素高度*/ background-color: aqua;}
设置position:absolute;和calc()函数实现垂直居中
.content{ position: absolute; top:calc(50% - 10em); /*calc(50% - 元素自身高度一半)*/ left: calc(50% - 20em); /*留神应用时减号间有空格*/ width: 40em; height: 20em; background-color: aqua;}
对未知高度块级元素进行垂直居中
设置position:absolute;和transform:traslate(x,y)实现程度垂直居中
.content{ position: absolute; margin:auto; top: 50%; left: 50%; transform:translate(-50%,-50%); /*针对元素自身向左以及向上挪动50%*/ background-color: aqua;}
基于flex的解决方案
.parent{ display: flex; background-color: beige;}.content{ margin: auto; /*主动绝对于父元素程度垂直居中*/ background-color: aqua;}
flex 1到底是什么
flex实际上是flex-grow、flex-shrink和flex-basis三个属性的缩写。
flex:1 ==> flex:1 1 auto
flex-grow:属性指定了flex容器中残余空间的多少应该被调配给我的项目。flex-grow设置的值为扩张因子,默认为0,残余空间将会依照这个权重别离调配给子元素我的项目。
flex-shrink:属性指定了flex元素的膨胀规定。flex元素仅在默认宽度之和大于容器的时候才会产生膨胀。默认属性值为1,所以在空间不够的时候,子项目将会主动放大。
flex-basis:属性指定了flex元素在主轴方向上的初始大小。如果不应用box-sizing扭转盒模型的话,那么这个属性就决定了flex元素的内容的尺寸。如果设置了flex-basis值,那么元素占用的空间为flex-basis值;如果没有设置或者设置为auto,那么元素占据的空间为元素的width/height值。
参考
flex罕用属性
flex-direction:主轴的方向(即我的项目的排列方向)
- row(默认值):主轴为程度方向,终点在左端。
- row-reverse:主轴为程度方向,终点在右端
- column:主轴为垂直方向,终点在上沿。
- column-reverse:主轴为垂直方向,终点在下沿。
flex-wrap属性:(轴线)
- flex-wrap: nowrap | wrap | wrap-reverse;
justify-content属性:定义了我的项目在主轴上的对齐形式。
- justify-content: flex-start | flex-end | center | space-between | space-around;
align-items属性:定义我的项目在穿插轴上如何对齐。
- align-items: flex-start | flex-end | center | baseline | stretch;
align-content属性:定义了多根轴线的对齐形式。如果我的项目只有一根轴线,该属性不起作用。
- align-content: flex-start | flex-end | center | space-between | space-around | stretch;
flex-grow属性:定义我的项目的放大比例,默认为0,即如果存在残余空间,也不放大
- flex-grow: <number>; / default 0 /
JS
var、let、const 的区别?
var 申明的变量有变量晋升的个性,而 let、const 没有
同一作用域下 let 和 const 不能反复申明同名变量,而var能够
var 申明的变量会挂载到 windows 对象上,所以应用 var 申明的是全局变量
const申明的是常量,必须赋初值,一旦申明不能再次赋值批改,如果申明的是复合类型数据,能够批改其属性
js中的数据类型
根底类型:number,string,null,undefiend,boolean,symbol
援用类型:Object,Function,Date,RE正则
=== 与 ==
== 在比拟类型不同的变量时,会进行数据类型转化,将二者转换成数据类型雷同的变量,再进行比拟。
=== 比拟的二者数据类型不一样时,间接返回false。
判断某个属性是否存在对象中
in 运算符:如果指定的属性在指定的对象或其原型链中,则in 运算符返回true。
hasOwnProperty(key):示意是否有本人的属性。这个办法会查找一个对象是否有某个属性,然而不会去查找它的原型链。
Object.key():获取对象所有的key,返回一个数组,可判断属性是否存在数组中
判断this指向?箭头函数的this指向什么?
一般函数:一般函数this指向默认window,严格模式下this为undefiend
在构造函数以及类中的this:构造函数和类须要配合 new 应用, 而 new 关键字会将构造函数中的 this 指向实例对象,所以 this 指向 实例对象。
绑定事件函数的this:谁调用就指向谁。
在箭头函数中:箭头函数没有本人的 this,会继承其父作用域的 this。
call apply bind 的作用与区别?
作用:扭转函数外部 this 的指向
区别:
- call 和 apply 会调用函数,而 bind 不会调用
- call 和 bind 传递参数为 一一传入,而 apply 的参数必须为数组模式
什么是闭包?
闭包是指可能拜访另一个函数作用域中的变量的一个函数。 在js中,只有函数外部的子函数能力拜访局部变量, 所以闭包能够了解成 “定义在一个函数外部的函数”。
闭包的作用
利用闭包能够冲破作用链域,将函数外部的变量和办法传递到内部,让内部函数能够拜访到外部函数的变量和办法
闭包的长处
失常的函数,在执行完之后,函数外面申明的变量会被垃圾回收机制解决掉。然而造成闭包的函数在执行之后,不会被回收,仍旧存在内存中。
闭包的毛病
因为变量不会被回收,所以内存中始终存在,消耗内存。
JS同步与异步
同步工作是指在主线程上排队执行的工作,只有前一个工作执行结束,能力继续执行下一个工作。
异步工作指的是,不进入主线程、而进入"工作队列"的工作,只有等主线程工作执行结束,"工作队列"的工作才会进入主线程执行。
如何开启异步工作
回调函数
setTimeout(() => { // f1的工作代码 callback();},1000)
事件监听.
实现原理也是利用定时器的原理去把函数放入事件队列里,等全副执行结束之后,才会执行事件队列里的办法
公布/订阅
在Vue中能够应用
EventBus
来作为沟通桥梁的概念,就像是所有组件共用雷同的事件核心,能够向该核心注册发送事件或接管事件// 事件注册EventBus.$emit("事件", '参数');// 事件监听EventBus.$on("事件", e => { console.log('回调函数')});// 敞开事件EventBus.$off("事件",{ console.log('回调函数')})
Promises
简略说,它的思维是,每一个异步工作返回一个Promise对象,该对象有一个then办法,容许指定回调函数。比方,f1的回调函数f2,能够写成:f1().then(f2);
async await语法糖
async润饰的办法会返回一个promises对象
await只能放在被async润饰的函数内。能够了解为期待。
await 润饰的如果是Promise对象:能够获取Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行;
如果不是Promise对象:把这个非promise的货色当做await表达式的后果。
Promise
promise有三个状态:
- Pending(进行中)
- Resolved(已实现)
- Rejected(已回绝)
promise的状态一旦产生扭转就注定后果,不可逆转,通过new Promise()来应用promise
当Promise执行胜利后会执行resolved()函数,通过then回调返回后果,后果就是resolve()的参数,then返回的也是一个Promise对象,能够链式调用
当Promise外部产生谬误后会执行rejected()函数,通过catch处理错误音讯,
Promise的其余办法
promise.all()
传入一个数组,当所有事务都解决实现之后再返回后果,例如通过all去申请一系列api,所有api返回后果后promise才调用resolve回调,返回一个数组
promise.race()
传入一个数组,当其中一个事务处理实现后就回返回后果,
JS事件循环
js是单线程的脚本语言,同一时间只能做同一件事,以至于执行工夫比拟长的代码就会产生阻塞,为了解决这一问题,js将代码执行的模式分为两种,同步和异步:
- 同步模式: 就是前一个工作执行实现后,再执行下一个工作,程序的执行程序与工作的排列程序是统一的、同步的;
- 异步模式: 则齐全不同,每一个工作有一个或多个回调函数(callback),前一个工作完结后,不是执行队列上的后一个工作,而是执行回调函数;后一个工作则是不等前一个工作的回调函数的执行而执行,所以程序的执行程序与工作的排列程序是不统一的、异步的。
事件循环:
- 执行全局Script 同步代码,这些同步代码有一些是同步语句,有一些是异步语句(比方setTimeout等)(这个过程中触发的回调函(比方resolve,)数进入宏/微队列);
- 全局Script执行结束(执行栈清空),
- 执行微工作队列(微工作进入执行栈),直到微工作队列清空(留神,如果在执行microtask的过程中,又产生了microtask,那么会退出到队列的开端,也会在这个周期被调用执行;)
- 取出宏队列队首的工作,进入执行栈;
- 执行宏工作(宏工作执行过程中可能产生新的宏工作或微工作,别离入队列,宏队列可能不为空,进入宏队列队尾)
- 如此重复循环,直到所有工作清空(执行栈清空)
同步工作,宏工作,微工作:
- 同步工作:script(整体代码)
- 宏工作:setTimeout,setInterval,setImmediate(node中),I/O (比方Ajax操作从网络读取数据),UI render(渲染)
- 微工作:process.nextTick,Promise,Async/Await(理论就是promise),MutationObserver(html5新个性)
// 执行setTimeoutsetTimeout(() => { // 向宏工作外面增加一个工作 console.log(1);}, 0)// 执行同步代码并输入console.log(2);//执行 Promisenew Promise((resolve, reject) => { // 执行同步代码并输入 console.log(3); // 向微队列外面增加一个工作 resolve(4)}).then(e => { // 执行微工作 console.log(e);})// 执行同步代码并输入console.log(5); // 后果:2,3,5,4,1
JS new 一下会产生什么?
如果有一个构造函数Foo(){...}
当代码 new Foo(…) 执行时,会产生以下事件:
- 一个继承自 Foo.prototype 的新对象被创立。
- 应用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的状况。
- 由构造函数返回的对象就是 new 表达式的后果。如果构造函数没有显式返回一个对象,则应用步骤1创立的对象。(个别状况下,构造函数不返回值,然而能够手动return返回对象,来笼罩失常的对象创立步骤)
JS原型链
例如:定义一个person对象
let person = { name:"", age:30 ...}
person对象并没有toString,valueOf等办法,然而能够调用,因为当对象在调用办法的时候,如果对象上没有定义,就回去obj.prototype
或者__ prop__
里查找,如果obj.prototype
或者__ prop__
里还没有就回持续往上查找,直到最顶层都还没有就回返回undefined 这样一个链式构造就是原型链,原型链最顶层是null
__prop__
是各浏览器厂商实现的
能够在原型链上定义方法
person.prototype.eat = function () { ...}
扭转原型:将prototype
指向另一个prototype
即可
JS实现继承
参考(command + 点击)
- 1.原型链继承
- 2.结构继承:
- 3.实例继承
- 4.拷贝继承:
- 5.组合继承:
- 6.寄生组合继承:
- 7.class - extends - - ES6
JS数组相干办法
扭转原数组
Array.push(),向数组的开端增加一个或多个元素,并返回新的数组长度。原数组扭转。
Array.pop(),删除并返回数组的最初一个元素,若该数组为空,则返回undefined。原数组扭转。
Array.unshift(),向数组的结尾增加一个或多个元素,并返回新的数组长度。原数组扭转。
Array.shift(),删除数组的第一项,并返回第一个元素的值。若该数组为空,则返回undefined。原数组扭转。
Array.concat(arr1,arr2...),合并两个或多个数组,生成一个新的数组。原数组不变。
Array.join(),将数组的每一项用指定字符连贯造成一个字符串。默认连贯字符为 “,” 逗号。
Array.reverse(),将数组倒序。原数组扭转。
Array.sort(),对数组元素进行排序。依照字符串UniCode码排序,原数组扭转。
Array.splice(index,howmany,arr1,arr2...)删除元素并增加元素,从index地位开始删除howmany个元素,并将arr1、arr2...数据从index地位顺次插入。howmany为0时,则不删除元素。原数组扭转。
Array.splice()从start开始,end之前完结,不到end;如果不给end值,从start开始到数组完结。start能够给负值,-1示意数组最初地位,-2示意倒数第二个,以此类推,顾前不顾后。
不扭转原数组
Array.map(function),原数组的每一项执行函数后,返回一个新的数组。原数组不变。
Array.forEach(function),用于调用数组的每个元素,并将元素传递给回调函数。原数组不变
Array.filter(function),过滤数组中,符合条件的元素并返回一个新的数组。
Array.every(function),对数组中的每一项进行判断,若都合乎则返回true,否则返回false。例如:1是否都小于[1,2,3,4]
Array.some(function),对数组中的每一项进行判断,若都不合乎则返回false,否则返回true。例如:1是否存在于[1,2,3,4,5]数组中
Array.reduce(function),reduce() 办法接管一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
数组去重
- 检测以后值在原数组中第一次呈现的地位在与以后下标做比照[皱眉]
let datas = [1, 4, 2, 5, 4, 2, 6, 4, 7, 4, 3, 6, 3, 7, 8, 32, 564, 23, 45, 234, 65, 34, 6, 34, 5, 23]//检测以后值在原数组中第一次呈现的地位在与以后下标做比照[皱眉]datas = datas.filter((item, index, arr) => { /** * indexOf(item,start) * item 必须。查找的元素。 * start 规定在数组中开始检索的地位 */ return arr.indexOf(item, 0) === index})console.log(datas);
- new Set() 配合 Array.from
Array.from(new Set([...]))
- 循环判断法
let newArr = []datas.forEach((item, index, arr) => { if (!newArr.includes(item)) newArr.push(item)})console.log(newArr);
- set 加扩大运算符[...]
datas = [...new Set(datas)]console.log(datas);
- Map对象加filter
/***Map对象是ES6提供的一个新的数据结构,*其中has的方法是返回一个布尔值,示意某个值是否存在以后的Mp对象之中,*set的方法是给Map对象设置key/value。*/function unique(arr) { let map = new Map() return arr.filter(item => !map.has(item) && map.set(item, 1))}console.log(unique(datas));
Map 和 Set
参考 command + 单击
本地存储
cookie
cookie用于保留网站的一些登录信息,验证密钥等,最大可保留4k数据,调用api的时候会主动携带cookie在HTTP申请头中,如果应用cookie保留过多数据会带来性能问题
localStorage
用于短暂保留整个网站的数据,保留的数据没有过期工夫,直到手动去除,个别5M左右
sessionStorage
用于长期保留同一窗口(或标签页)的数据,在敞开窗口或标签页之后将会删除这些数据,个别5M左右
操作localStorage和sessionStorage
- 通过
setItem(key, value)
设置数据, - 通过
getItem(key)
获取数据, - 通过
removeItem(key)
移除数据 - 通过
clear()
革除所有数据
JS浏览器缓存 -- 强缓存与协商缓存
强缓存:不会向服务器发送申请,间接从缓存中读取资源,能够设置两种 HTTP Header 来实现:Expires、Cache-Control
Expires
- 缓存过期工夫用来指定资源的过期工夫,是服务器端的具体的工夫点,联合 last-modified 来应用
- 是 HTTP/1 的产物,受限于本地工夫,如果本地工夫批改可能会造成缓存生效
Cache-Control
- 能够在申请头或响应头中来设置,多个指令配合应用达到多个目标
- 是 HTTP/1.1 的产物,如果和 Expires同时存在,那么它的优先级要高,所以 Expires 的存在成为了一种兼容性的写法
协商缓存
- 强缓存的根据来自于缓存是否过期,而不关怀服务端文件是否曾经更新,这可能会导致加载的文件不是服务端最新的内容,此时咱们就须要用到协商缓存
协商缓存就是强制缓存生效后,浏览器携带缓存标识向服务器发送申请,由服务器依据缓存标识决定是否应用缓存的过程,次要分两种状况
- 协商缓存失效返回 304 和 Not Modified
- 协商缓存生效返回 200 和申请的后果
- 协商缓存能够通过设置两种 HTTP Header 来实现:Last-Modified 和 ETag
参考 command + 点击
VUE
个性
渐进式,组件化开发,数据响应式,双向数据绑定,数据驱动视图
vue指令
v-if v-else v-else-if v-show v-for v-bind v-ones v-on v-html v-text v-model
vue修饰符
- lazy,在默认状况下,
v-model
在每次input
事件触发后将输入框的值与数据进行同步 。你能够增加lazy
修饰符,相当于在onchange事件触发更新。 - trim,过滤首尾空格
- number 将值转换成number类型
事件修饰符:
- stop,阻止事件冒泡
- prevent,阻止事件默认行为
- self,点击事件绑定的自身才会触发事件
- once 一次性事件
- native 转化为原生事件
v-if 和 v-show的区别
if 和 show都是管制dom的显示与暗藏,不同的在于if是间接删除dom show是通过cssdisplay: block / none;
管制domd的显示暗藏,不会删除dom
须要频繁切换的场景下倡议应用show,如果是简略的dom构造显示暗藏两者都能够
为什么vue中data必须是一个函数
为了保障组件的独立性和可复用性:data是一个函数,组件实例化的时候这个函数将会被调用,返回一个对象,计算机会给这个对象调配一个内存地址,你实例化几次,就调配几个内存地址,他们的地址都不一样,所以每个组件中的数据不会互相烦扰,扭转其中一个组件的状态,其它组件不变。
key的作用
当vue在进行新旧虚构dom diff
比照的时候,patch函数会通过元素的tag和key来判断是不是同一个元素,如果不设置key就默认为undefined,比照的时候两个元素就会认为是同一个,导致视图没更新,例如两个input互相切换,没有key切换的时候就回保留上一个input元素的value值,还有一种状况就是列表渲染的时候,当没有设置key的时候,列表产生扭转时所有列表都会更新,设置key之后只会更新对应的列表项
vue中computed和watch的区别
computed
- 反对缓存,只有依赖数据产生扭转,才会从新进行计算
- 不反对异步,当computed内有异步操作时有效,无奈监听数据的变动
- computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中申明过的数据通过计算失去的
- 如果一个属性是由其余属性计算而来的,这个属性依赖其余属性,是一个多对一或者一对一,个别用computed
- 如果computed属性属性值是函数,那么默认会走get办法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set办法,当数据变动时,调用set办法。
watch
- 不反对缓存,数据变,间接会触发相应的操作;
- watch反对异步;
- 监听的函数接管两个参数,第一个参数是最新的值;第二个参数是输出之前的值;
- 当一个属性发生变化时,须要执行对应的操作;一对多;
computed和methods的区别
- computed只能作为属性应用,methods只能作为办法调用
- computed具备getter和setter,因而能够赋值,而methods不能
- computed无奈承受多个参数,而methods能够
- computed具备缓存,执行过一次之后第二次就间接应用缓存的后果而不回在此执行computed,而methods没有缓存
进阶:
vue对methods的解决比较简单,只须要遍历methods配置中的每个属性,将其对应的函数应用bind绑定以后组件实例后复制其援用到组件实例中即可,这样就能够应用this调用
Vue它会遍历computed配置中的所有属性,为每一个属性创立一个Watcher对象,并传入一个函数,该函数的实质其实就是computed配置中的getter,这样一来,getter运行过程中就会收集依赖,然而这个watcher不回立刻执行,只有在该computed属性被应用的时候才会执行,
vue组件通信
父子之间通信:
prop,event,style和class,natvie修饰符,sync修饰符,$listeners,v-model,$parent和$children,$slots和$scopedSlots,ref
跨组件通信:
vuex,router,eventBus,store模式,Provide和Inject
参考 (command + 单击)
vue数据响应式(双向数据绑定)原理
vue的数据响应只有通过4个核心部件来实现的,别离是:
- Observer
- Dep
- Watcher
- Scheduler
Observer的作用很简略,次要是通过Object.defineProperty将数据包装成一个带有getter/setter的非凡属性,读取数据的时候通过getter办法,写入数据的时候通过setter办法
其中对对象和数组的解决有所不同,对象是间接通过Observer去包装,而数组则是重写了可能扭转数组的一些办法,例如push
, pop
, shift
, unshift
, splice
, sort
, reverse
,而后在通过observeArray办法去遍历数组里的数据,是数据具备响应式
Dep次要是收集依赖和告诉依赖更新,当数据被应用的时候就回调用getter办法,get外面会通过dep实例调用dep.depend()办法,收集依赖;当数据被扭转的时候就回告诉依赖更新,set外面通过dep实况调用dep.notify()办法告诉所有订阅者依赖更新。
当某个函数在执行的过程中,应用到了响应式数据时,vue就会为响应式数据创立一个watcher实例,当数据产生扭转时,vue不间接告诉相干依赖更新,而是告诉依赖对应的watcher实例去执行。
watcher实例不间接更新视图,而是交给scheduler
调度器,scheduler
保护一个事件队列通过nextTick执行事件,从而更新视图。
参考 ( command + 单击)
v-model的原理
v-model能够作用到表单元素或者自定义组件上,
作用在表单元素上有两种状况,
- 一般表单元素,例如input时,生成一个value属性和input办法
- 单选框或者复选框元素,生成一个checked属性和一个change办法
作用在自定义组件时默认生成一个value属性和一个input办法,也能够通过配置组件外部的model来扭转默认的属性和办法
// Compconst Comp = { model: { prop: "number", // 默认为 value event: "change" // 默认为 input } // ...}
参考 ( command + 单击
vue生命周期
分为五个阶段,初始化阶段(beforeCreate,created),模版编译阶段(生成render函数),挂载阶段(beforemunt,munted),更新阶段(beforeUpdate,update),销毁阶段(before Destroy,destroyed)
初始化阶:段次要设置一些所有属性到vue实例中,并解决computed,methods,data,provide,inject属性,应用代理模式将这些属性挂载到vue实例中
编译阶段:次要将模版编译成render函数
挂载阶段:次要将render函数运行取得的虚构DOM依照每一个节点创立对应的elm属性,即实在DOM,在这一过程中,会收集所有动态数据的依赖
更新阶段:动态数据产生扭转后之前收集的依赖Watcher会被从新运行,促发一个叫做updateCompontent的函数,该函数会呈现执行render函数取得新的vnode,并把新的vnode作为参数过_update函数,在执行update函数的过程中,会触发patch函数比照新旧两颗dom树
销毁阶段:组件来到或者所销毁的时候,会调用组件的$destroy办法删除组件,该办法会先后调用beforeDestroy和destroy办法,移除本身所有的依赖和事件监听,彻底销毁组件实例
参考(command + 单机)
vue中mixin用法
mixin能够全局混入,也能够组件混入,通过mixin混入的生命周期会和组件的生命周期进行合并,抵触的办法以组件里的为主,执行程序:
- 对于created,mounted 等生命周期函数 mixin文件中的代码先执行,组件中的后执行
- 对于data中定义的字段,组件中定义组件笼罩mixin中同名字段
- 对于 method中的同名办法,组件内的同名办法笼罩mixin中的办法
vue自定义指令
- bind 只调用一次,指令第一次绑定到元素时候调用,用这个钩子能够定义一个绑定时执行一次的初始化动作。
- inserted:被绑定的元素插入父节点的时候调用(父节点存在即可调用,不用存在document中)
- update: 被绑定于元素所在模板更新时调用,而且无论绑定值是否有变动,通过比拟更新前后的绑定值,疏忽不必要的模板更新
- componentUpdate :被绑定的元素所在模板实现一次更新更新周期的时候调用
- unbind: 只调用一次,指令与元素解绑的时候调用
Vue.directive("hello",{ bind:function(el,bingind,vnode){ //只调用一次,指令第一次绑定到元素时候调用, //用这个钩子能够定义一个绑定时执行一次的初始化动作。 el.style["color"] = bingind.value; console.log("1-bind"); }, inserted:function(){ //被绑定的元素插入父节点的时候调用(父节点存在即可调用,不用存在document中) console.log("2-inserted"); }, update:function(){ //被绑定于元素所在模板更新时调用,而且无论绑定值是否有变动 //通过比拟更新前后的绑定值,疏忽不必要的模板更新 console.log("3-update"); }, componentUpdated:function(){ //被绑定元素所在模板实现一次更新周期时调用 console.log('4 - componentUpdated'); }, unbind:function(){ //只调用一次,指令与元素解绑时调用。 console.log('5 - unbind'); } })
vue相干优化
- 列表应用Key
- 静态数据应用对象解冻,比方长列表,列表数据不须要增删改的状况下能够应用Object.freeze解冻对象,被解冻的对象不回被响应化
应用函数式组件,在不须要组件实例的组件中应用函数式组件
Vue.component('my-component', { functional: true, // Props 是可选的 props: { // ... }, // 为了补救短少的实例 // 提供第二个参数作为上下文 render: function (createElement, context) { // ... }})
- 应用计算属性,如果模板中某个数据会应用屡次,并且该数据是通过计算失去的,应用计算属性以缓存它们
应用非实时绑定的表单
当应用
v-model
绑定一个表单项时,当用户扭转表单项的状态时,也会随之扭转数据,从而导致vue
产生重渲染(rerender
),这会带来一些性能的开销。特地是当用户扭转表单项时,页面有一些动画正在进行中,因为JS执行线程和浏览器渲染线程是互斥的,最终会导致动画呈现卡顿。
咱们能够通过应用
lazy
或不应用v-model
的形式解决该问题,但要留神,这样可能会导致在某一个时间段内数据和表单项的值是不统一的。在频繁切换显示暗藏的时候应用v-show代替v-if
对于频繁切换显示状态的元素,应用v-show能够保障虚构dom树的稳固,防止频繁的新增和删除元素,特地是对于那些外部蕴含大量dom元素的节点,这一点极其重要
关键字:频繁切换显示状态、外部蕴含大量dom元素
应用提早装载(defer)
首页白屏工夫次要受到两个因素的影响:
打包体积过大
巨型包须要耗费大量的传输工夫,导致JS传输实现前页面只有一个
<div>
,没有可显示的内容须要立刻渲染的内容太多
JS传输实现后,浏览器开始执行JS结构页面。
但可能一开始要渲染的组件太多,不仅JS执行的工夫很长,而且执行完后浏览器要渲染的元素过多,从而导致页面白屏
打包体积过大须要自行优化打包体积,本节不予探讨
本节仅探讨渲染内容太多的问题。
一个可行的方法就是提早装载组件,让组件依照指定的先后顺序顺次一个一个渲染进去
提早装载是一个思路,实质上就是利用
requestAnimationFrame
事件分批渲染内容,它的具体实现多种多样// mixinsexport default function(maxFrameCount) { return { data() { return { frameCount: 0, }; }, mounted() { const refreshFrameCount = () => { requestAnimationFrame(() => { this.frameCount++; if (this.frameCount < maxFrameCount) { refreshFrameCount(); } }); }; refreshFrameCount(); }, methods: { defer(showInFrameCount) { return this.frameCount >= showInFrameCount; }, }, };}
- 应用Keep- alive缓存组件
- 长列表优化,当有大量列表须要展现的时候,不须要一次性将所有列表渲染进去,只须要渲染可视区域及可视区域以下的一部分列表,并为这些曾经渲染的列表设置相对定位,让后通过计算滚动地位来不停更新开始区域的列表即可,不须要渲染所有的数据列表(插件:VueVirtualScroller)
keep-alive
keep-alive组件是vue的内置组件,用于缓存外部组件实例。这样做的目标在于,keep-alive外部的组件切回时,不必从新创立组件实例,而间接应用缓存中的实例,一方面可能防止创立组件带来的开销,另一方面能够保留组件的状态。
keep-alive具备include和exclude属性,通过它们能够管制哪些组件进入缓存。另外它还提供了max属性,通过它能够设置最大缓存数,当缓存的实例超过该数时,vue会移除最久没有应用的组件缓存。
受keep-alive的影响,其外部所有嵌套的组件都具备两个生命周期钩子函数,别离是activated
和deactivated
,它们别离在组件激活和失活时触发。第一次activated
触发是在mounted
之后
vue过渡和动画
应用内置组件Transition实现动画
Transition
组件会监控slot
中惟一根元素的呈现和隐没,并会在其呈现和隐没时利用过渡成果
具体的监听内容是:
- 它会对新旧两个虚构节点进行比照,如果旧节点被销毁,则利用隐没成果,如果新节点是新增的,则利用进入成果
- 如果不是上述情况,则它会比照新旧节点,察看其
v-show
是否变动,true->false
利用隐没成果,false->true
利用进入成果
TransitionGroup组件能够监听列表的变动它会对列表的新增元素利用进入成果,删除元素利用隐没成果,对被挪动的元素利用v-move
款式
被挪动的元素之所以可能实现过渡成果,是因为TransisionGroup
外部应用了Flip过渡计划
vue组件封装
次要蕴含三局部:prop、event、slot
- props示意组件接管的参数,最好用对象的写法,这样能够针对每个属性设置类型、默认值或自定义校验属性的值,此外还能够通过type、validator等形式对输出进行验证
- slot能够给组件动静插入一些内容或组件,是实现高阶组件的重要途径;当须要多个插槽时,能够应用具名slot
- event是子组件向父组件传递音讯的重要途径
参考 command + 单击
VUE3
vue3相比拟vue2的一些变动
- vue3去掉了vue构造函数,通过导出一个createApp的办法来创立一个vue我的项目,
- 新增了组合式Api,这样同一个性能的所有业务代码都能够写到一起而不用扩散到组件的各个模块中,
- 对于响应式数据的实现形式不同,放弃了Object.defineProperty的实现形式,而是应用Proxy,
v-if
的优先级当初高于v-for
v-model的实现形式有所不同
当对自定义组件应用
v-model
指令时,绑定的属性名由原来的value
变为modelValue
,事件名由原来的input
变为update:modelValue
<!-- vue2 --><ChildComponent :value="pageTitle" @input="pageTitle = $event" /><!-- 简写为 --><ChildComponent v-model="pageTitle" /><!-- vue3 --><ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event"/><!-- 简写为 --><ChildComponent v-model="pageTitle" />
去掉了
.sync
修饰符,它本来的性能由v-model
的参数代替<!-- vue2 --><ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /><!-- 简写为 --><ChildComponent :title.sync="pageTitle" /><!-- vue3 --><ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /><!-- 简写为 --><ChildComponent v-model:title="pageTitle" />
- 组件的
model
配置被移除 容许自定义
v-model
修饰符<Compon v-model.cap="data1" v-model:text="data2" />
为什么vue3中去掉了vue构造函数?
vue2的全局构造函数带来了诸多问题:
- 调用构造函数的静态方法会对所有vue利用失效,不利于隔离不同利用
- vue2的构造函数集成了太多功能,不利于tree shaking,vue3把这些性能应用一般函数导出,可能充分利用tree shaking优化打包体积
- vue2没有把组件实例和vue利用两个概念辨别开,在vue2中,通过new Vue创立的对象,既是一个vue利用,同时又是一个非凡的vue组件。vue3中,把两个概念区别开来,通过createApp创立的对象,是一个vue利用,它外部提供的办法是针对整个利用的,而不再是一个非凡的组件。
vue3数据响应式的了解
vue3不再应用Object.defineProperty的形式定义实现数据响应式,而是应用Proxy。
除了Proxy自身效率比Object.defineProperty更高之外,因为不用递归遍历所有属性,而是间接失去一个Proxy。所以在vue3中,对数据的拜访是动静的,当拜访某个属性的时候,再动静的获取和设置,这就极大的晋升了在组件初始阶段的效率。
同时,因为Proxy能够监控到成员的新增和删除,因而,在vue3中新增成员、删除成员、索引拜访等均能够触发从新渲染,而这些在vue2中是难以做到的。
vue3中如何定义响应式数据(reactivity api)
API | 传入 | 返回 | 备注 |
---|---|---|---|
reactive | plain-object | 对象代理 | 深度代理对象中的所有成员 |
readonly | plain-object or proxy | 对象代理 | 只能读取代理对象中的成员,不可批改 |
ref | any | { value: ... } | 对value的拜访是响应式的 如果给value的值是一个对象, 则会通过 reactive 函数进行代理如果曾经是代理,则间接应用代理 |
computed | function | { value: ... } | 当读取value值时, 会依据状况决定是否要运行函数 |
利用:
- 如果想要让一个对象变为响应式数据,能够应用
reactive
或ref
- 如果想要让一个对象的所有属性只读,应用
readonly
- 如果想要让一个非对象数据变为响应式数据,应用
ref
- 如果想要依据已知的响应式数据失去一个新的响应式数据,应用
computed
判断:
API | 含意 |
---|---|
isProxy | 判断某个数据是否是由reactive 或readonly |
isReactive | 判断某个数据是否是通过reactive 创立的具体:https://v3.vuejs.org/api/basi... |
isReadonly | 判断某个数据是否是通过readonly 创立的 |
isRef | 判断某个数据是否是一个ref 对象 |
composition api相比于option api有哪些劣势?
从两个方面答复:
- 为了更好的逻辑复用和代码组织
- 更好的类型推导
有了composition api,配合reactivity api,能够在组件外部进行更加细粒度的管制,使得组件中不同的性能高度聚合,晋升了代码的可维护性。对于不同组件的雷同性能,也可能更好的复用。
相比于option api,composition api中没有了指向奇怪的this,所有的api变得更加函数式,这有利于和类型推断零碎比方TS深度配合。
setup
// componentexport default { setup(props, context){ // 该函数在组件属性被赋值后立刻执行,早于所有生命周期钩子函数 // props 是一个对象,蕴含了所有的组件属性值 // context 是一个对象,提供了组件所需的上下文信息 }}
context对象的成员
成员 | 类型 | 阐明 |
---|---|---|
attrs | 对象 | 同vue2 的this.$attrs |
slots | 对象 | 同vue2 的this.$slots |
emit | 办法 | 同vue2 的this.$emit |
生命周期函数
vue2 option api | vue3 option api | vue 3 composition api |
---|---|---|
beforeCreate | beforeCreate | 不再须要,代码可间接置于setup中 |
created | created | 不再须要,代码可间接置于setup中 |
beforeMount | beforeMount | onBeforeMount |
mounted | mounted | onMounted |
beforeUpdate | beforeUpdate | onBeforeUpdate |
updated | updated | onUpdated |
beforeDestroy | ==改== beforeUnmount | onBeforeUnmount |
destroyed | ==改==unmounted | onUnmounted |
errorCaptured | errorCaptured | onErrorCaptured |
- | ==新==renderTracked | onRenderTracked |
- | ==新==renderTriggered | onRenderTriggered |
新增钩子函数阐明:
钩子函数 | 参数 | 执行机会 |
---|---|---|
renderTracked | DebuggerEvent | 渲染vdom收集到的每一次依赖时 |
renderTriggered | DebuggerEvent | 某个依赖变动导致组件从新渲染时 |
DebuggerEvent:
- target: 跟踪或触发渲染的对象
- key: 跟踪或触发渲染的属性
- type: 跟踪或触发渲染的形式
VUEX
vuex是vue的数据状态管理器,外部别离为:
- state数据仓库模块,
- mutations模块,用来扭转state的状态,同步执行,
- actions模块,提交一个mutations办法扭转state状态,异步执行
- getter模块,能够对state进行计算操作,相当于state的计算属性
- modules模块,能够让vuex分模块治理,让每一个模块领有独立的state,mutations,action,getter模块,不便数据状态的治理以及数据状态变动的追踪
VUEX数据状态长久化
将state仓库的数据备份到localStorage中,或者应用相干插件,例如:persistedstate
VUEX的getter个性
- getter能够对state进行计算操作,相当于state的计算属性
- 便于在组件之间复用getter计算属性
VUEX的mutations和action的异同
- action相似于mutations,不同之处在于action提交的是mutations,而不是间接扭转state的状态
- mutations是同步执行,action是一步执行
vue - Router路由
router-link
用于路由跳转,通过to指定跳转门路,默认状况下router-link会被渲染成一个a标签,能够通过指定tag扭转最终渲染的标签,active-class能够指定被激活的款式。
router-view
路由的进口,跳转的组件在router-view里渲染
路由重定向
通过在路由对象里配置redirect实现重定向
路由模式
- hash模式,兼容所有浏览器,地址栏会带有#哈希值
- history模式,只兼容之处HTML5 history Api的浏览器,地址栏不会带有#哈希值
- abstract模式,反对所有js运行环境,如node环境,如果不在浏览器环境里运行,路由会主动切换到该模式
路由守卫
- 全局钩子: beforeEach、 afterEach、beforeResolve
- 单个路由外面的钩子: beforeEnter
- 组件内路由钩子函数:beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave
// 全局前置路由钩子函数beforeEach(to,from,next){ next()}//全局后置路由钩子函数afterEach(to,from){}// 全局解析守卫 这和 beforeEach 相似beforeResolve(){}// 路由独享守卫const routes = [ { path: '/users/:id', component: UserDetails, beforeEnter: (to, from) => { // reject the navigation return false }, },]//组件内的守卫const UserDetails = { template: `...`, beforeRouteEnter(to, from) { // 在渲染该组件的对应路由被验证前调用 // 不能获取组件实例 `this` ! // 因为当守卫执行时,组件实例还没被创立! }, beforeRouteUpdate(to, from) { // 在以后路由扭转,然而该组件被复用时调用 // 举例来说,对于一个带有动静参数的门路 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候, // 因为会渲染同样的 `UserDetails` 组件,因而组件实例会被复用。而这个钩子就会在这个状况下被调用。 // 因为在这种状况产生的时候,组件曾经挂载好了,导航守卫能够拜访组件实例 `this` }, beforeRouteLeave(to, from) { // 在导航来到渲染该组件的对应路由时调用 // 与 `beforeRouteUpdate` 一样,它能够拜访组件实例 `this` },}
残缺的路由钩子触发流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫(2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫(2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创立好的组件实例会作为回调函数的参数传入。
路由跳转
在 Vue 实例中,能够通过 $router
拜访路由实例。能够调用 this.$router.push
导航到不同的页面
// 字符串门路router.push('/users/eduardo')// 带有门路的对象router.push({ path: '/users/eduardo' })// 命名的路由,并加上参数,让路由建设 urlrouter.push({ name: 'user', params: { username: 'eduardo' } })// 带查问参数,后果是 /register?plan=privaterouter.push({ path: '/register', query: { plan: 'private' } })// 带 hash,后果是 /about#teamrouter.push({ path: '/about', hash: '#team' })// 向前挪动一条记录,与 router.forward() 雷同router.go(1)
记录滚动地位
const router = createRouter({ history: createWebHashHistory(), routes: [...], scrollBehavior (to, from, savedPosition) { // return 冀望滚动到哪个的地位 return { top:0, left:0 } }})
axios
特点
- Axios是一个基于 promise 的HTTP库,反对promise所有的API
- 它能够拦挡申请和响应
- 它能够转换申请数据和响应数据,并对响应回来的内容主动转换成JSON类型的数据
- 安全性更高,客户端反对进攻XSRF
axios相干的配置属性
- ‘url’是用于申请的服务器url
- ‘method’ 是创立申请时应用的办法,默认是get,
- 'baseURL’将主动加在url后面,除非url是一个相对URL。
- ’transformRequest‘容许在向服务器发送前,批改申请数据,只能用在’put\post\patch’这几个申请办法。
- ‘headers’自定义申请头。
- ‘params’是行将与申请一起发送的url参数,必须是一个无格局对象或URLSearchParams对象
- ‘auth’示意被告i应用HTTP根底验证,并提供票据,这将设置一个Authorization头,覆写掉现有的热比一使
- headers设置的自定义Authorization头
- ‘proxy’定义代理服务器的主机名称和端口
axios申请拦截器与响应拦截器
// 增加申请拦截器axios.interceptors.request.use(function (config) { // 在发送申请之前做些什么 return config; }, function (error) { // 对申请谬误做些什么 return Promise.reject(error); });// 增加响应拦截器axios.interceptors.response.use(function (response) { // 对响应数据做点什么 return response; }, function (error) { // 对响应谬误做点什么 return Promise.reject(error); });