备注
.triangle{
width:0;
height:0;
border:100px solid red;
border-top-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
}
1rem与网站根标签font-size有关,若html根标签设置font-size:20px,那么这里的1rem为20px;
1em与父元素有关,若父元素设置的font-size:20px;那么在子组件中2em就表示为40px;
1vh(Viewport Height)表示可视化窗口高度的的1%;
1vw(Viewport Width)表示可视化窗口宽度的的1% ;
1px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的;
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。
.line{ border:1px solid gray; transform:scaleY(0.5)}
link 属于 html 标签,而@import 是 css 提供的
页面被加载时,link 会同时被加载,而@import 引用的 css 会等到页面加载结束后加载。
link 方式样式的权重高于@import
层叠性、继承性、优先级
id 选择器,class 选择器,标签选择器,伪元素选择器,伪类选择器等
优先级:important > 内敛样式 > id 选择器 > class 选择器 > 标签选择器
8 个语义元素: header section footer aside nav main article figure(经测试,只要figure有样式,其它语义标签只是display:block)
内容元素:
mark 高亮 { background-color:mark;color:marktext }
progress 进度新的表单控件
input type新加属性 date time search color datetime-local
canvas 绘图
支持内联 SVG。
多媒体元素 audio(audio中source) video embed track
本地离线存储,把需要离线存储在本地的文件列在一个 manifest 配置文件
web 存储 localStorage、SessionStorage
CSS3 边框如 border-radius,box-shadow 等;
CSS3 背景如 background-size,background-origin 等;
CSS3 2D,3D 转换如 transform 等;CSS3 动画如 animation等。
1、伪类可以从状态类伪类、结构类伪类、其它伪类和表单相关伪类进行分类。
状态类伪类:** :hover、:link、:active、:visited、:focus**
结构类伪类:** :first-child、:last-child、:nth-child(n)**
其它伪类: :fullscreen全屏显示、:lang()匹配指定语言
表单相关伪类: :checked选中、:disabled禁用、:required必填、:read-only只读
2、伪元素:::before、::after、::first-letter、::first-line、::selection、::placeholder
1、简单理解:同时适配PC+平板+手机等设备,网站的布局会根据视口来调整模块的大小和位置。
2、基本原理:通过媒体查询 监测不同设备 做屏幕尺寸处理, 需要注意为了处理移动端,页面头部必须有meta声明viewport
重绘:元素样式改变不改变布局,浏览器重绘对元素进行更新,如颜色改变;
回流:元素的大小、结构变化,浏览器重新渲染页面,如width,height改变;
transition 需要触发一个事件才能改变属性
animation 不需要触发任何事件的情况下才会随时间改变属性值,并且 transition 为 2 帧,从from … to,而 animation 可以一帧一帧的
严格模式:又称标准模式,是指浏览器按照 W3C 标准解析代码。
混杂模式:又称怪异模式或兼容模式,是指浏览器用自己的方式解析代码。
如何区分:浏览器解析时到底使用严格模式还是混杂模式,与网页中的 DTD 直接相关。
意义:严格模式与混杂模式存在的意义与其来源密切相关,如果说只存在严格模式,那么许多旧网站必然受到影响,如果只存在混杂模式,那么会回到当时浏览器大战时的混乱,每个浏览器都有自己的解析模式。
CSS可以影响可替换元素的位置,但不会影响到可替换元素自身的内容。例如 元素,可能具有自己的样式表,但它们不会继承父文档的样式。 典型的可替换元素有:
opacity作用于元素以及元素内所有内容,会继承父元素的opacity属性
rgba()只作用于元素的颜色或者背景图,子元素不会继承其属性
1、使用zoom,可以改变页面上元素的尺寸,属于真实尺寸。
zoom:50%,表示缩小到原来的一半
zoom:0.5,表示缩小到原来的一半
2、transform:scale(0.8)
calc()函数支持加减乘除四种运算。
加减号两边一定要有空格
任何长度值都可以使用calc函数进行计算:% vh vw px em等
calc函数使DOM元素更加灵活的响应视口改变,还可以通过calc函数实现元素的绝对剧中定位(position:absolute;top:calc(50vh - Xpx))
因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。
1、clientWidth/clientHeight 返回的是元素的内部宽度,它的值只包含 content + padding
2、offsetWidth/offsetHeight 返回的是元素的布局宽度,它的值包含 content + padding + border 包含了滚动条。
3、scrollWidth/scrollHeight 返回值包含 content + padding + 溢出内容的尺寸, scrollTop 属性返回的是一个元素的内容垂直滚动的像素数。 scrollLeft 属性返回的是元素滚动条到元素左边的距离。
构造两棵树,DOM 树和 CSSOM 规则树, 当浏览器接收到服务器相应来的 HTML 文档后,会遍历文档节点,生成 DOM 树, CSSOM 规则树由浏览器解析 CSS 文件生成
ser-Agent中文名为用户代理,简称UA,是HTTP协议中的一部分,属于头域的组成部分。它是一个特殊的字符串头。
服务器用来识别客户使用的操作系统、版本、CPU类型、浏览器版本、浏览球渲染引擎、浏览器语言、浏览器插件等。 网页一般根据这个标识来显示不同的排版。
1 对象不同:cookie是针对每个网站的信息,session:是针对每个用户的;
2 存储数据大小不同:cookie存储的数据不超过3K,session存储在服务器上可以任意存储数据
3 生命周期不同:cookie的生命周期当浏览器关闭的时候就消亡了,session的生命周期是间隔的,从创建时开始计时如在30min内没有访问session,那么session生命周期就被销毁
4 存储位置不同:cookie数据保存在客户端,session数据保存在服务器端
5 数据类型不同:两者都是key-value结构,但针对value的类型是有差异的,cookie的value只能是字符串类型,session的value是object类型。
window.addEventListener('copy',(e)=>{
e = window.event || e
e.preventDefault()
e.clipboardData.setData('text','覆盖默认复制内容')
})
在浏览网站的时候,如果网页禁止复制,快速的操作方法是:
控制台console里面输入:document.body.contentEditable = true
涉及到页面传值时,特别有用
e.target:触发事件的元素
e.currentTarget:绑定事件的元素
举例:
有一个父元素绑定了事件,父元素中有A B两个子元素,当我们点击A或者B元素的时候,这个时候e.target指的是A或B,e.currentTarget指的是父元素。
即:
如果绑定的事件所在组件没有子元素,则用e.target===e.currentTarget一样;
如果事件绑定在父元素中,且该父元素有子元素,当用e.currentTarget时,不管点击父元素所在区域还是子元素(当前事件),都正确执行,若用e.target时,点击父元素所在区域无错,点击子元素区域,执行报错,报错的原因是事件没绑定在子元素上,是在父元素上,子元素要用e.currentTarget才正确!
总之:使用e.target时要注意,e.currentTarget就无所谓了
bind,call,apply的作用都是用来改变this指向的
1、apply方法接收两个参数,第一个参数是this的指向,第二个参数是函数接收的参数,已数组形式传入,且当第一个参数为null、undefined的时候,this默认指向window对象
2、call方法接收的第一个参数也是this的指向,后面传入的是一个参数列表,其他与apply相同。
3、bind和call方法相似,知识它改变this的指向后不会立即执行,而是返回一个永久改变this指向的函数
合理的title、description、 keywords:搜索对着三项的权重逐个减小,title强调重点,description把页面内容高度概括(不可过分堆砌关键词)、keywords列出重要关键词。
重要内容不用js输出,爬虫不会执行js获取内容
非装饰性图片必须加alt
提高网站速度(网站速度是搜索引擎排序的一个重要指标)
谨慎使用display属性
减少使用iframe框架
服务端渲染 ……
属性 | 说明 |
---|---|
Object.keys(obj) | 返回对象自身的所有可遍历属性 |
for(let v of Object.values(obj)){} | 配合 for…of 使用,遍历对象的值 |
for(let [k,v] of Object.entries(obj)){} | 配合 for…of 使用,遍历键值对 |
Object.getOwnPropertyNames(obj) | 返回对象自身的所有属性(包括不可遍历的) |
Object.getOwnPropertyDescriptors(obj) | 返回该对象所有属性的描述对象 |
Object.getOwnPropertyDescriptor(obj,‘name’) | 返回该对象’name’属性的描述对象 |
Object.defineProperty(obj,‘a’,{}) | 通过描述对象,定义对象某个属性的配置 |
object.defineProperties(obj,{}) | 通过描述对象 ,定义对象的多个属性配置 |
Object.preventExtensions(obj) | 阻止对象可扩展 |
Object.isExtensible(obj) | 判断一个对象是否可扩展 |
Object.seal(obj) | 禁止对象的配置 |
Object.isSealed(obj) | 判断对象是否可配置 |
Object.getPrototypeOf(obj) | 获取参数对象的原型 |
Object.setPrototypeOf(target,source) | 为参数对象设置其原型对象 |
Object.create(obj) | 传入的参数为创建对象的原型 |
Object.is(a,b) | 判断两个参数是否完全相等 |
Object.assign(target,source) | 将 source 的自有可枚举属性复制到模板对象 |
属性 | 说明 |
---|---|
Object.prototype.valueOf() 返回当前对象所对应的值 | |
Object.prototype.toString() 返回当前对象所对应的字符串 | |
Object.prototype.toLocaleString() 返回当前对象对应的本地字符串形式 | |
Object.prototype.hasOwnProperty(‘foo’) 判断某个属性是否为自身的属性 | |
Object.prototype.isPrototypeOf() 判断当前对象是否为另一个对象的原型 | |
Object.prototype.propertyIsEnumerable() 判断对象的某个属性是否可以枚举 |
JSON.stringify(JSON.parse(obj)) === ‘{}’
Object.keys(obj).length === 0
解释:是一种相似数组的对象,js 中类数组对象有不少,例如arguments、 NodeList、 HTMLCollection、 jQuery等
类数组拥有的特性:
可使用length
数字下标方式访问对象
a[0]
不能使用数组原型方法如slice、push
a.push(0) // 报错
使用 instanceof 操做不属于 Array
a instanceof Array; // false
a instanceof Object; // true
能够被转换为真数组
Array.from(arr) 或者 [...arr]
arr instanceof Array; // true
强类型语言是一种强制类型定义的语言,即一旦某一个变量被定义类型,如果不经强制转换,那么它永远就是该数据类型。代表:C/C++、Delphi、VB等;
弱类型语言某一个变量被定义类型,该变量可以根据环境变化自动进行转换,不需要经过现行强制转换。代表:JS、PHP等;代表:Java、JavaScript、VBScript、Perl、Python等;
强类型原因在速度上可能略逊于弱类型语言,但是强类型定义语带来的严谨性又避免了不必要的错误
动态性语言是指在运行期间才去做数据类型检查的语言,编程时不用给任何变量指定数据类型,其会在第一次赋值给变量时,在内部将数据类型记录下来。JavaScript、Python和Ruby就是一种典型的动态类型语言。
静态类型语言与动态类则刚好相反,它的数据类型在编译期间检查,也就是说在写程序时要声明所有变量的数据类型,C/C++是静态类型语言的典型代表,其他静态语言还有TypeScript、C#、Java等。
对于动态语言与静态语言的区分,其根本在于判断是在运行期间去做数据类型还是在编译期间检查
1 通过 Object()方法来创建 let obj = new Object({a:1})
2 通过字面量创建对象 let obj ={a:1}
3 通过自定义函数创建对象
function Image(width,height){
this.width=width;
this.height=height;
this.content=function{
console.log("图片的高是"+this.height+"宽是"+this.width);
}
}
var image=new Image("300px","300px");
image.content();
4 通过工厂模式创建对象
function createPerson(name, age, gender) {
//创建一个新的对象
var obj = new Object()
//向对象中添加属性
obj.name = name
obj.age = age
obj.gender = gender
obj.sayName = function () {
alert(this.name)
}
return obj
}
5 通过原型模式
function Person(){};
Person.prototype.name="Mary";
Person.prototype.age=18;
Person.prototype.job="teacher";
Person.prototype.sayName=function (){
alert(this.name);
}
var person1=new Person();
person1.sayName(); //Mary-来自原型
var person2= new Person();
person2.sayName(); //Mary-来自原型
1、内建对象
由 ES 标准中定义的对象,在任何的 ES 实现中都可以实现,比如: Math String Number Boolean Function Object…
2、宿主对象
由 JS 的运行环境提供的对象,目前来讲主要指由浏览器提供的对象,比如 BOM DOM
3、自定义对象
由开发人员自己创建的对象
Cookie并不提供修改、删除操作。如果要修改某个Cookie,只需要新建一个同名的Cookie来覆盖原来Cookie
1 如果没有显示设置cooke过期时间,cookie不会存入本地硬盘,仅存留于内存中。
当我们关闭浏览器的时候,cookie会自动删除,生命周期无需我们操控
//取cookies
function getCookie(name){
let arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
if (arr != null) return unescape(arr[2]);
return null;
}
//删除cookie
function delCookie(name){
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(name);
if (cval != null)
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString()+";path=/";
}
2 使用三方库js-cookie->Cookies.remove(‘name’, { path: ‘’ })
xml和json都是数据传输的载体,并且具有跨平台跨语言的特性,区别如下:
数据体积方面。JSON 相对于 XML 来讲,数据的体积小,传递的速度更快些。
数据交互方面。JSON 与 JavaScript 的交互更加方便,更容易解析处理,更好的数据交互。
数据描述方面。JSON 对数据的描述性比 XML 较差。
传输速度方面。JSON 的速度要远远快于 XML。
误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。
实际上HTTP协议从未规定GET/POST的请求长度限制是多少。对get请求参数的限制是来源与Web浏览器,浏览器限制了url的长度,为了明确这个概念我们必须再次强调下面几点:
HTTP协议未规定GET和POST的长度限制
GET的最大长度显示是因为浏览器限制了URL的长度
不同浏览器 限制的最大长度不一样:若支持IE最大长度为2083byte,若只支持Chrome,最大长度为8182byte
let regex = /xyz/;
let regex = new RegExp(‘xyz’,‘i’)
使用 __wxConfig.envVersion 区分
envVersion: ‘develop’, //开发版
envVersion: ‘trial’, //体验版
envVersion: ‘release’, //正式版
1、利用 Array.some 方法判断数组中是否还存在数组,es6 展开运算符连接数组
let arr = [1, 2, [3, 4]]
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr)
}
2、使用数组的 concat 方法
let arr = [1, 2, [3, 4]]
let result = []
result = Array.prototype.concat.apply([], arr)
3、 使用数组的 concat 方法和扩展运算符
var arr = [1, 2, [3, 4]]
var result = []
result = [].concat(...arr)
4、es6 中的 flat 函数也可以实现数组的扁平化
let arr = [1,2,['a','b',['中','文',[1,2,3,[11,21,31]]]],3];
let result = arr.flat( Infinity )
注意:flat方法的infinity属性,可以实现多层数组的降维
基本数据类型和引用数据类型:
基本数据类型:Number、String 、Boolean 、Null、Undefined 、Symbol
引用数据类型:数组和对象,Object 是 JavaScript 中所有对象的父对象
基本数据类型存储在栈中,引用数据类型(对象)存储在堆中,指针放在栈中。
两种类型的区别是:
存储位置不同;原始数据类型直接存储在栈中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
引用数据类型存储在堆中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
它的功能是把对应的字符串解析成JS代码并运行;应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。
for…in循环:会遍历对象自身和继承的可枚举属性
Object.keys():只遍历对象自身可枚举的属性
JSON.stringify():只串行化对象自身的可枚举属性
Object.assign():只拷贝对象自身的可枚举属性
原因:iOS上浏览器怎么区分用户是只要单击操作还是要双击进行缩放操作。所以设置了300ms的延迟时间,加以判断用户是单击还是双击缩放,浏览器会在捕获用户第一次单击时,保持300ms的时间:若在300ms内若捕获不到第二次单击,则用户就是单纯执行单击操作;若在300ms内,用户有第二次单击操作,则对该区域进行缩放操作。
粗暴型,禁用缩放
利用 FastClick,其原理是: 检测到 touchend 事件后,立刻出发模拟 click 事件,并且把浏览器 300 毫秒之后真正出发的事件给阻断掉
二进制转十进值:(1010101).toString(2) ‘toString()中转进值’
十进制数转二进制:Number.parseInt(10100,2)
计算机是通过二进制存储数据的,所以在计算0.1 + 0.2的时候,是计算这两个数二进制的和,然而这俩数都是无限循环的数,因此再次转成十进值的时候就会转成一个无限循环的多位数
解决:Number.parseFloat((0.1+0.2).toFixed(10))
另外还有一个Number.EPSILON值,根据规格,它表示 1 与大于 1 的最小浮点数之间的差,Number.EPSILON实际上是 JavaScript 能够表示的最小精度。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了。
遗留问题:1.1+2.2的和与3.3进行比较,误差大于Number.EPSILON,即0.3000000000000003 > 0.30000000000000022204返回了true
Array.isArray(value) 返回true则是数组,否则不是数组
Object.prototype.toString.call(value) 若为’[object Array]'则为数组,都为不是数组
value instanceof Array 若返回true则为数组。
Array.prototype.isPrototypeOf(value) 若返回true则为数组
两者都是浅拷贝
let outObj = {
inObj: {a: 1, b: 2}
}
let newObj = Object.assign({}, outObj)
newObj.inObj.a = 2
console.log(outObj) // { inObj: {a: 2, b: 2} }
let outObj = {
inObj: {a: 1, b: 2}
}
let newObj = {...outObj}
newObj.inObj.a = 2
console.log(outObj) // { inObj: {a: 2, b: 2} }
**深拷贝方法 **
JSON.stringify()
JSON.parse()
意外的全局变量;在js文件开头添加 ‘use strict’,开启严格模式;
未清理的DOM元素引用; var a = document.getElementById(‘id’); document.body.removeChild(a); 解决:a = null;
被遗忘的定时器或者回调; 解决:调用clearInterval或者clearTimeout
闭包
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet(): string{
return "Hello, " + this.greeting;
}
}
let greeter = new Greeter("world");
Promise的出现是为了解决异步产生的回调地狱,使得开发人员用新的方式来编写程序。
而Promise出现引出的新问题是如果有多个Promise要执行,虽然Promise.all可以解决,但是如果存在Promise先后的执行顺序,Promise就不能很好的解决了。
然后 async await出现,允许异步程序用同步代码的方式写程序,也就是说async await解决了Promise产生的一些问题,且是建立在Promise的基础上实现的,返回的仍然是一个Promise。
输入网址后做域名解析
根据ip地址查找服务器,开始请求数据
服务器返回数据,浏览器开始解析
浏览器再次请求页面中使用的资源文件
解析展示整个页面
模板字符串、箭头函数、promise、const/let、解构赋值、扩展运算符(…)、class类的继承、Symbol、Map、async/await
1.比较两个操作数相等时,有运算符根据运算符优先级,要先算==两侧的,然后再去强制转换类型,最后再去比较;
2.数组(对象,函数)会先通过调用toString()转换为字符串后再转换为数值
3.注意在比较时出现NaN,null,undefined时,不强制转换为数字类型
4.在关系运算符中,null,undefined会被Number()强制转换成数字类型;
JS对象都有一个prototype属性,指向它的原型对象,原型对象是用来存放实例对象的共有属性和公有方法的,它有个constructor属性,指向它的构造函数。
每个实例对象都有_ proto _属性,当试图访问一个对象的属性时,如果没有在该对象上找到,它还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。在这个查找的过程中形成的链式结构就被称作原型链。
同源指的是域名、协议、端口号相同
async 和await两种语法 ,可以让异步代码像同步代码一样
1 普通函数的调用,this指向的是window
2对象方法的调用,this指的是该对象,且是最近的对象
3 构造函数的调用,this指的是实例化的新对象
4 apply和call调用,this指向参数中的对象
5 匿名函数的调用,this指向的是全局对象window
6 定时器中的调用,this指向的是全局变量window
7 箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this,否则this的值则被设置为全局对象
8 onclick和addEventerListener是指向绑定事件的元素(ev.currentTarget)
主要是this 的指向不同:
普通函数的 this 指向的是谁调用该函数就指向谁。
箭头函数的 this 指向的是在你书写代码时候的上下文环境对象的 this,如果没有上下文环境对象,那么就指向最外层对象 window。
call, apply,bind 会改变普通函数的 this,但不会改变箭头函数的 this
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖:电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送
节流:电梯第一个人进来后,15秒后准时运送一次
babel是什么? Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持
Webpack的proxy功能是通过配置反向代理来实现的,可以解决前端开发中的跨域问题
工作原理:
在Webpack的配置文件中,可以通过配置devServer.proxy选项来设置代理。代理服务器会拦截前端发送的请求,并将请求转发到目标服务器。在转发请求时,代理服务器会修改请求的域名、端口等信息,以实现跨域请求。目标服务器接收到代理服务器转发的请求,并返回响应结果。代理服务器将响应结果返回给前端应用程序。
解决跨域问题的原因:
浏览器的同源策略限制了前端应用程序通过XMLHttpRequest或Fetch API等方式向不同域的服务器发送请求。
代理服务器作为一个位于浏览器和目标服务器之间的中间层,实际上是在同一域内与目标服务器进行通信,因此不受同源策略的限制。
当前端应用程序通过代理服务器发送请求时,请求的源被修改为与代理服务器相同的域,从而绕过了浏览器的同源策略限制。
1、执行npm install,检查项目的node_modules是否已经存在安装模块,如果存在就不会进行安装(即使已经有了新版本) (npm install -f 不管本地是否已经安装了模块,都会重新安装。)
2、检查是否有package-lock.json文件, a. 没有lock文件,直接获取package.json的版本 b. 有package-lock.json文件,当package.json的版本规范与package-lock.json版本兼容时,按lock文件安装,如果不兼容按package安装。
3、检查缓存(npm config get cache)
4、如果有缓存,直接解压到node_modules
5、如果没有缓存,下载压缩包,存放在~/.npm目录,解压压缩包到node_modules
6、生成package-lock.json文件
使用 Vue.nextTick()是为了可以获取更新后的 DOM 。
触发时机:在同一事件循环中的数据变化后,DOM 完成更新,立即执行 Vue.nextTick()的回调。
应用场景:
1、在 Vue 生命周期的 created()钩子函数进行的 DOM 操作一定要放在 Vue.nextTick()的回调函数中。 原因:是 created()钩子函数执行时 DOM 其实并未进行渲染。
2、在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的 DOM 结构的时候,这个操作应该放在 Vue.nextTick()的回调函数中。
原因:Vue 异步执行 DOM 更新,只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变,如果同一个 watcher 被多次触发,只会被推入到队列中一次。
1、 defineProperty API 的局限性最大原因是它只能针对单例属性做监听。 Vue2.x 中的响应式实现正是基于 defineProperty 中的 descriptor,对 data 中的属性做了遍历 + 递归,为每个属性设置了 getter、setter。 这也就是为什么 Vue 只能对 data 中预定义过的属性做出响应的原因,在 Vue 中使用下标的方式直接修改属性的值或者添加一个预先不存在的对象属性是无法做到 setter监听的,这是 defineProperty 的局限性。
2 、Proxy API 的监听是针对一个对象的,那么对这个对象的所有操作会进入监听操作, 这就完全可以代理所有属性,将会带来很大的性能提升和更优的代码。 Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
3、 响应式是惰性的 在 Vue.js 2.x 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就需要递归遍历这个对象,执行 Object.defineProperty 把每一层对象数据都变成响应式的,这无疑会有很大的性能消耗。 在 Vue.js 3.0 中,使用 Proxy API 并不能监听到对象内部深层次的属性变化,因此它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗。
建议放在created里
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
如果在mounted钩子函数中请求数据可能导致页面闪屏问题
其实就是加载时机问题,放在created里会比mounted触发早一点,如果在页面挂载完之前请求完成的话就不会看到闪屏了。
请求的数据对DOM有影响,那么使用created,如果请求的数据对DOM无影响,可以放在mounted
vue2 的输入框的双向绑定,其实就相当于传递了value属性, 并触发了input事件:
<!-- Vue 2 -->
<input v-model="searchValue"><input>
<!-- 相当于 -->
<input :value="searchValue" @input="searchValue=$event"><input>