发布时间:2025-12-09 21:20:34 浏览次数:4
用正确的标签做正确的事情。
HTML语义化让页面的内容结构化,结构更清晰,便于浏览器、搜索引擎解析;即使在没有css样式的情况下,也以一种文档格式显示,并且是容易阅读的
搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,利于seo优化
使阅读源代码的人更容易将网站分块,便于阅读维护理解
通常当鼠标滑动到元素上的时候显示
alt 是img标签 的特有属性,是图片内容的等价描述,
用于图片无法加载显示、读屏器阅读图片。可提图片高可访问性,
除了纯装饰图片外都必须设置有意义的值,搜索引擎会重点分析。
新增用于绘画的 canvas 和 svg 元素
新增 video(视频) 和 audio(音频) 标签
新增客户端数据存储新方法:sessionStorage、localStorage
新增多个语义化标签元素:
·header、nav、article、section、aside、footer
表单的增强应用:
·表单元素 input 的 type 属性扩充:
·date、time、email、url、search、range、month、color、number ·表单元素 input 通过属性进行表单验证:
·required(必填项)、pattern(正则表达式验证表单输入)
新增地理定位 - Geolocation API 用于获得用户的地理位置
1、cookie
(1)本身用于客户端和服务端通信
(2)但是它有本地存储的功能,于是就被“借用”
(3)document.cookie = …获取和修改即可
(4)cookie用于存储的缺点
①存储量太小,只有4kb
②所有http请求都带着,会影响获取资源的效率
③api简单,需要封装才能用document.cookie
2、localStorage,sesseionStorage
(1)html5专门为存储而设计,最大容量5M
(2)api简单易用
(3)lcoalStorage.setItem(key, value);localStorage.getItem(key);
(4)ios safari隐藏模式下:localStorage.getItem会报错,建议统一使用try-catch封装
3、sessionStorage用于本地存储一个会话(session)中的数据,
这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。
因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。
而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。
特点:
块级元素:独占一行;可设置宽高;margin 和 padding 均有效;
行内元素:不独占一行,可在一行显示;设置宽高无效;margin 上下无效、左右有效;padding 均有效;
行内块元素:不独占一行,可在一行显示;可以设置宽高;margin 和 padding 均有效;
转换:
转为块元素:display: block;
转为行内元素: display: inline;
转为行内块元素:display: inline-block;
共同点:能够使用户不能改变表单中的内容
不同点:
1、readonly只对input和textarea有效,但是disabled对所有的表单元素都是有效的,
包括radio、checkbox
2、readonly可以获取到焦点,只是不能修改。
disabled设置的文本框无法获取焦点
3、如果表单的字段是disabled,则该字段不会发送(表单传值)和序列化
优点:
颜色:新增 RGBA,HSLA 模式,新增透明度
盒子阴影:(box-shadow)
边框:
边框圆角:(border-radius)
边框阴影:(box-shadow)
边框图片:(border-image)
弹性盒子模型:(box-sizing:border-box;)
背景:
background-size :设置背景图片的尺寸
background-origin :设置背景图片的原点(定位、位置)
background-clip :设置背景图片的裁切区域,以”,”分隔,可以设置多背
景,用于自适应布局。
渐变:
linear-gradient:(线性渐变)
radial-gradient :(径向渐变)
新增过渡效果:
transition,配合动态伪类使用
自定义动画:
animation 定义动画:@keyframes 动画名称
媒体查询@media,多栏布局: @media screen and (width:500px) {
…
}
2D 转换:
transform:translate(x,y) 移动
rotate(x,y) 旋转
skew(x,y) 翻转
scale(x,y) 缩放
3D 转换
字体图标 : font-face
弹性布局 :flex
新增多种选择器(结构伪类选择器、动态伪类选择器、属性选择器等)
盒模型分为两类:标准盒模型和怪异盒模型(IE 盒模型)
盒模型的组成部分(由外向内):
margin(外边距)+ border(边框)+ padding(内边距)+ content(盒子内容大小)
注:
标准盒模型的 width 指的是内容 content 的宽度,height 指的是 content 的高度
怪异盒模型的 width 指的是内容、边框、内边距总的宽度(content + border + padding);
height 指的是内容、边框、内边距总的高度
盒子转换方式:
如果 doctype 协议缺失,会由浏览器自己界定。
在 IE 浏览器中 IE9 以下(IE6、IE7、IE8)的版本触发怪异模式,其他浏览器中会默认
为 W3C 标准模式。
box-sizing: content-box 标准盒模型
box-sizing: border-box IE 盒模型
什么是回流?
当一个元素自身的宽高,布局,显示或隐藏,或元素内部的文字结构发生变化
,导致需要重新构建页面的时候,就产生了回流复制
什么是重绘?
当一个元素自身的宽高,布局,及显示或隐藏没有改变,
而只是改变了元素的外观风格的时候,就产生了重绘
什么时候会进行回流?
添加或者删除可见的 DOM 元素的时候
元素的位置发生改变
元素的尺寸发生改变
内容改变
页面第一次渲染的时候
什么时候会进行重绘?
列举一些相关的 CSS 样式:color、background、
background-size、visibility、box-shadow
单行文本: line-height = height
图片: vertical-align: middle;
盒子:1. 定位(子绝父相)实现垂直居中
父元素:相对定位;
子元素:绝对定位;
top:calc(50% - 子元素自身的一半) /子元素需具备高度/
left:calc(50% - 子元素自身的一半) /子元素需具备宽度/
2. 定位+transform: translate(-50%, -50%)(常用)
3. fixed 定位居中
4. flex 弹性布局居中(常用)
给父盒子设置 display:flex; justify-content:center; align-items:center;
link 是 XHTML 标签,除了加载CSS外,还可以定义 RSS 等其他事务;@import 属于 CSS 范畴,只能加载 CSS。
link 引用 CSS 时,在页面载入时同时加载;@import 需要页面网页完全载入以后加载。
link 是 XHTML 标签,无兼容问题;@import 是在 CSS2.1 提出的,低版本的浏览器不支持。
link 支持使用 Javascript 控制 DOM 去改变样式;而@import不支持。
display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。
visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。
opacity 会继承父元素的 opacity 属性,而 RGBA 设置的元素的后代元素不会继承不透明属性。
① 排列方式:
行内元素间会在同一行进行排列(水平方向);
块级元素独占一行,垂直向下排列(垂直方向)
②宽高和内外边距:
行内元素设置宽高无效,宽高随文本内容的变化而变化,但可以设置行高;
行内元素设置内外边距(margin 和 padding)上下无效,左右有效;
③元素嵌套:
块级元素可以包含行内元素和块级元素,还可以容纳内联元素和其他元素;
行内元素不能包含块级元素,只能容纳文本或者其他行内元素
1 给浮动元素的父元素添加高度(不推荐)
2 给父盒子添加 overflow:hidden;来清除浮动(不推荐)
3 空标签法:给父盒子内部的最后面添加一个空标签(必须为块级标签),并给空标
签设置 clear:both;(不推荐)
4.双伪元素清除浮动(推荐):
.clearfix::before,.clearfix::after {
content: ’’;
clear: both;
display: block;
height: 0;
visibility: hidden;
zoom: 1;//兼容IE6
}
在HTML中常用以下四种方式定义CSS
inline(内联式,也称行内样式)、
embedding(嵌入式)、
linking(外部引用式)
导入样式表(@import )。
详细
一:内联式/行内样式:使用该属性可以直接指定样式,当然,该样式仅能用于该元素的内容,对于另一个同名的元素则不起作用。
二:嵌入式(style):用户可在HTML文档头部定义多个style元素,实现多个样式表。
三:外部引用式(link)
①可以在多个文档间共享样式表,对于较大规模的网站,将CSS样式定义独立成一个一个的文档,可有效地提高效率,并有利于对网站风格的维护。
②可以改变样式表,而无需更改HTML文档,这也与HTML语言内容与形式分开的原则相一致。
③可以根据介质有选择的加载样式表。
四:导入样式表:@import url(“css/base.css”);
优先级:就近原则
内联式>内嵌式>外部引用式>导入样式表
基本数据类型
Number、String、Boolean、Null、Undefined、Symbol、bigInt
引用数据类型
object、Array、Date、Function、RegExp
判断方法
typeof
typeof 可以用来区分除了 Null 类型以外的原始数据类型,对象类型的可以从普通对象里面
识别出函数:
问题一:typeof 不能识别 null,如何识别 null?
答案:如果想要判断是否为 null,可以直接使用===全等运算符来判断(或者使用下面的
Object.prototype.toString 方法):
问题二:typeof 作用于未定义的变量,会报错吗?
答案:不会报错,返回"undefined"。
问题三:typeof Number(1)的返回值是什么?
答案:“number”。注意 Number 和 String 作为普通函数调用的时候,是把参数转化为相 应
的原始数据类型,也就是类似于做一个强制类型转换的操作,而不是默认当做构造函数 调
用。注意和 Array 区分,Array(…)等价于 new Array(…)
问题四:typeof new Number(1)的返回值是什么?
答案:“object”。
instanceof
instanceof 不能用于判断原始数据类型的数据:
3 instanceof Number // false
‘3’ instanceof String // false
true instanceof Boolean // false
instanceof 可以用来判断对象的类型:
var date = new Date()
date instanceof Date // true var number = new Number()
number instanceof Number // true var string = new String()
string instanceof String // true
需要注意的是,instanceof 的结果并不一定是可靠的,因为在 ECMAScript7 规范中可以通
过自定义 Symbol.hasInstance 方法来覆盖默认行为。
由上面的示例可知,该方法没有办法区分数字类型和数字对象类型,同理还有字符串类型
和字符串对象类型、布尔类型和布尔对象类型
另外,ECMAScript7 规范定义了符号 Symbol.toStringTag,你可以通过这个符号自定义
Object.prototype.toString 方法的行为:
因为 Object.prototype.toString 方法可以通过 Symbol.toStringTag 属性来覆盖默认行 为,所以
使用这个方法来判断数据类型也不一定是可靠的
创建方法
1、字面量对象 // 默认这个对象的原型链指向 object var o1 = {name: ‘01’};
2、通过 new Object 声明一个对象
var o11 = new Object({name: ‘011’});
3、使用显式的构造函数创建对象
var M = function(){this.name=‘o2’};
var o2 = new M();
o2.proto=== M.prototype
o2 的构造函数是 M
o2 这个普通函数,是 M 这个构造函数的实例
4、object.create() var P = {name:‘o3’};
var o3 = Object.create§;
Array数组、Boolean、Date、Error、Math、Number、Obejct、RegExp、String、Function
Array
reverse() 将数组中各元素颠倒顺序
delete 运算符 只能删除数组元素的值,而所占空间还在,总长度没变(arr.length)
shift() 删除数组中第一个元素,返回删除的那个值,并将长度减 1
pop() 删除数组中最后一个元素,返回删除的那个值,并将长度减 1
unshift() 往数组前面添加一个或多个数组元素,长度要改变。arrObj.unshift(“a” ,
“b,“c”)
push() 往数组结尾添加一个或多个数组元素,长度要改变。arrObj.push(“a” ,“b”,
“c”)
concat( ) 连接数组
slice( ) 返回数组的一部分
sort( ) 对数组元素进行排序
splice( ) 插入、删除或替换数组的元素
Boolean 布尔对象
Boolean.toString( ) 将布尔值转换成字符串
Boolean.valueOf( ) Boolean 对象的布尔值
Date
Date.getDate( ) 返回一个月中的某一天
Date.getDay( ) 返回一周中的某一天
Date.getFullYear( ) 返回 Date 对象的年份字段
Date.getHours( ) 返回 Date 对象的小时字段
Date.getMilliseconds( ) 返回 Date 对象的毫秒字段
Date.getMinutes( ) 返回 Date 对象的分钟字段
Date.getMonth( ) 返回 Date 对象的月份字段
Date.getSeconds( ) 返回 Date 对象的秒字段
Date.getTime( ) 返回 Date 对象的毫秒表示
Error
Error 异常对象
Error.message 可以读取的错误消息
Error.name 错误的类型
Error.toString( ) 把 Error 对象转换成字符串
EvalError 在不正确使用 eval()时抛出
SyntaxError 抛出该错误用来通知语法错误
RangeError 在数字超出合法范围时抛出
ReferenceError 在读取不存在的变量时抛出
TypeError 当一个值的类型错误时,抛出该异常
URIError 由 URl 的编码和解码方法抛出
Math
Math.ceil() 向上取整(整数加 1,小数去掉)
Math.floor() 向下取整(直接去掉小数)
Math.round() 四舍五入
Number
Number.toString( ) 将—个数字转换成字符串
Number.valueOf( ) 返回原始数值
Object
Object.toString( ) 定义一个对象的字符串表示
RegExp
RegExp.exec( ) 通用的匹配模式
RegExp.global 正则表达式是否全局匹配
RegExp.ignoreCase 正则表达式是否区分大小写
RegExp.lastIndex 下次匹配的起始位置
RegExp.source 正则表达式的文本
RegExp.test( ) 检测一个字符串是否匹配某个模式
RegExp.toString( ) 把正则表达式转换成字符串
String
substr() 在原始字符串,返回一个子字符串
substring() 在原始字符串,返回一个子字符串
split() 将一个字符串转成数组
concat( ) 连接字符串
lastIndexOf( ) 从后向前检索一个字符串
Function
Function.apply( ) 将函数作为一个对象的方法调用
Function.arguments[] 传递给函数的参数
Function.call( ) 将函数作为对象的方法调用
Function.caller 调用当前函数的函数
Function.length 已声明的参数的个数
Function.prototype 对象类的原型
Function.toString( ) 把函数转换成字符串
===:三个等号我们称为等同符,当等号两边的值为相同类型的时候,直接比较等号两边
的值,值相同则返回 true,若等号两边的值类型不同时直接返回 false。也就是说三个等号
既要判断值也要判断类型是否相等
= =:两个等号我们称为等值符,当等号两边的值为相同类型时比较值是否相同,类型不同
时会发生类型的自动转换,转换为相同的类型后再作比较。也就是说两个等号只要值相等
就可以
思路是要遍历对象的所有键名和键值是否都一致
1、判断两个对象是否指向同一内存
2、使用 Object.getOwnPropertyNames 获取对象所有键名数组
3、判断两个对象的键名数组是否相等
4、遍历键名,判断键值是否都相等
变量提升
简单说就是在 JavaScript 代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提 升至其对应作用域的最顶端,函数内声明的变量只会提升至该函数作用域最顶层当函数内部定义的一个变量与外部相同时,那么函数体内的这个变量就会被升到最顶端
举例来说:
console.log(a); //
undefined var a = 3; //预编译后的代码结构可以看做如下运行顺序 var a; // 将变量 a 的声明提升至最顶端,赋值逻辑不提升。 console.log(a); // undefined a = 3; // 代码执行到原位置即执行原赋值逻辑
函数提升
函数提升只会提升函数声明式写法,函数表达式的写法不存在函数提升
函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上
在js中变量和函数的声明会提升到最顶部执行
函数的提升高于变量的提升
函数内部如果用 var 声明了相同名称的外部变量,函数将不再向上寻找。
匿名函数不会提升。
闭包就是能够读取其他函数内部变量的函数
闭包基本上就是一个函数内部返回一个函数
特点:1.函数嵌套函数
2.内部函数可以访问外部变量
3.参数和变量不会被回收(回收牵扯出全局变量和局部变量,因为全局变量在页面关闭后销毁,比较占内存资源。局部变量在函数执行完毕后销毁,闭包保护局部变量不会在函数执行完被回收也就是销毁)
不能滥用闭包,会导致内存泄漏(本应该会回收的变量没有被回收)
不需要function关键字来创建函数
省略return关键字
改变this指向
this 指的是调用函数的那个对象
this 在没有运行之前不能知道代表谁;js的this 指向是不确定的;
和定义没有关系,和执行有关.执行的时候,点前面是谁,this 就是谁;
自执行函数里面的this 代表的是 window
定时器书写的时候,window可以省略掉;定时器执行的时候,里面的this 代表的也是 window ;
this 是js的一个关键字,随着函数使用场合不同,this 的值会发生变化。
如果有new关键字,this指向new出来的对象
在事件中,this指向触发这个事件的对象
创建一个空对象,并且this变量引用该对象,同事还继承了该函数的原型
属性和方法被加入到this引用的对象中
新创建的对象this所引用,并且最后隐式返回this
Call
第一个参数是this指向的新环境 第二个参数及以后的参数,是传递给调用者新环境的参数,调用者此时在新环境被中执行 第一个参数可以为函数也可以为this,如果为null,则表示执行window 用来改变this指向
Apply
第一个参数是this指向的新环境 第二个参数要传递给新环境的参数数组
Bind
第一个参数是this指向的新环境 第二个参数要传递给新环境的参数 返回一个改变this 指向的新函数,对原函数没有影响
概念:代码(变量)可以使用的范围就是作用域。主要是为了提高程序的可靠性,也是为了减少命名冲突
全局作用域和局部作用域
全局作用域:指的是整个js文件,定义在全局中的全局变量,可以在局部作用域中使用,函数内部没有声明直接赋值的变量也叫全局变量
局部作用域:主要指的是函数作用域,函数内部也就是局部作用域
在函数内部var定义的变量-,叫做局部变量,局部变量无法被外部获取
概念:当我们点击子元素触发父元素的事件,这种现象,我们叫做事件冒泡,即由子元素向祖先元素传播,就像气泡从水底上浮
event.stopPropagation();阻止事件冒泡
通俗的讲,子代有事,让父级执行,当我们点击li时,子元素会通过事件的冒泡来触发父元素的事件,主要是通过事件冒泡
原理: 不要给每个子节点单独设置事件监听器,而是事件监听设置在其父节点上,然后利用冒泡原理影响设置每个子节点
抽象:把主要特征跟问题抽象出来
封装:把方法写在内部,外部调用
继承:可以从父类继承方法和属性,而子类又有自己独特的属性
浅拷贝:基本数据类型拷贝的是值,引用数据类型拷贝的是地址
深拷贝:引用数据类型拷贝的是开辟新地址中的值
深拷贝的方法
对象和字符串的相转化
var a = JSON.stringify(one);//先转字符串再转对象 var b = JSON.parse(a);
封装开辟新地址的函数
function deepCopy(obj){ var objs = JSON.stringify(obj); var newObj = JSON.parse(objs); return newObj; }
数组的解决方法
数组的解决方法,只要有返回新数组的均可以解决这个问题
slice、 concat 、split等
节流 :在频繁接触的函数中,指的是在一定时间中只执行一次,适应与苏哦有频繁触发的事件
防抖 : 在频繁触发的函数中,只执行最后一次,主要思路,当事件一段事件没有继续触发时,我们的事件处理函数才会执行一次
(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.
概念:同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
jsonp跨域
document.domain + iframe 跨域
nodejs中间件代理跨域
后端在头部信息里面设置安全域名
定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题。
js中可能出现的内存泄漏情况:结果:变慢,崩溃,延迟大等
js中可能出现的内存泄漏原因
全局变量
dom 清空时,还存在引用
定时器未清除
子元素存在引起的内存泄露
垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存
一般使用标记清除方法(mark and sweep), 当变量进入环境标记为进入环境,离开环境标记为离开环境
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
还有引用计数方法(reference counting), 在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。
1.任何对象都有 proto 隐式原型, 等于 构造函数 的 prototype
const obj = {}obj.__proto__ === Object.prototype // true2.任何函数都有 prototype 显示原型 等于 原型对象(就是一个普通对象包含公共属性)
*(通过Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性)
3.对象还具有 constructor 属性,指向构造函数(Person.prototype.constructor == Person)
4.原型链是依赖于__proto__, 查找一个属性会沿着 proto 原型链向上查找,直到找到为止。
5.特殊
每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
于是就这样一直找下去,也就是我们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.proto
特点:
JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
get 通过地址栏拼接参数,但是因为地址栏长度有限,所以get传输数据也有限
post 没有数据传输大小的限制
get不需要设置请求头post需要设置请求头
get请求数据可能被缓存post不会
get只能URL编码,post支持的编码格式众多
| 只有全局作用域和函数作用域 | 有块级作用域 | 有块级作用域 |
| 存在变量提升 | 不存在变量提升 | 不存在变量提升 |
| 可以重复声明 | 不能重复声明 | 不能重复声明 |
| 没有死区 | 存在暂时性死区 | 存在暂时性死区 |
| 可以先声明后赋值 | 可以先声明 后赋值 | 声明即赋值 |
三种状态:pending(进行中),fulfilled(已成功),reject(已失败)
promise是es6引入异步编程新解决方案,语法上promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
Promise构建出来的实例存在以下方法: then() 是实例状态发生改变时的回调函数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数 catch() 用于指定发生错误时的回调函数 finally() 用于指定不管 Promise 对象最后状态如何,都会执行的操作
1)promise构造函数:promise(excutor){}
2)promise.protiotype.then方法
3)promise.prototype.catch方法
async 是一个通过异步执行并隐式返回 Promise 作为结果的函数。是Generator函数的语法糖,并对Generator函数进行了改进。
改进:
答:通过数据劫持结合订阅者发布模式,通过Object.defineProperty(),为各个属性定义get、set方法,在数据发生改变时,给订阅者发布消息,触发相应的事件回调
每一个组件实例都有相应的watch程序实例,他会在组件渲染的过程中把属性记录为依赖,之后当依赖向的setter被调用时,会通知watch重新计算,从而导致它关联的组件得以更新
响应式:
数据响应式:vue采用的是数据劫持结合开发者订阅模式的方式,通过Object.defineProperty()来劫持,set、get在数据变动的时候,发布给订阅者,触发响应式回调
页面响应式:媒体查询、弹性盒子、百分比布局
答:注意:mvvm是vue的设计思想
M:model,指的是后端传递的数据
V:view,指的是视图,也就是所看到的的界面
VM:view Model,视图模型,他是连接的view和model的桥梁,主要是处理业务逻辑对象
MVC: m:模型 v:视图 c:controller控制器,处理逻辑
答:轻量级、组件化、数据双向绑定、虚拟DOM、单页面应用(SPA:一个项目只有一个web页面应用,加载单个HTML页面,并在用户与程序发生交互时,更新该页面的局部内容,但不刷新页面)
组件间数据相互不被影响
答:js中对象是一个引用数据类型,每一个组件都是一个vue的实例,组件共享data属性,只要一个实例对对象进行操作,其他的组件实例中的额数据也会发生变化。
组件中的data写成一个函数,数据就会以函数的形式定义,这样每一个组件实例就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,各个组件实例维护各自的数据。
不使用return会造成这个变量(数据)在项目中,变得全局可见,造成变量污染,使用return包裹,只会在当前组件中可用,不会影响到其他组件
vue全家桶包括:vue-router、vuex、vue-resouerce,再加上vue-cil和sass样式和组件库,就是一个完整测vue项目的核心构成
概括起来就是项目构建工具+路由+状态管理+http请求工具+样式管理/组件库
答:key代表的是唯一、在项目中如果使用for不加key会报警告,渲染时会出现错误,key的作用是为了更高效的更新虚拟dom,其目的就是为了让vue可以区分
答:vue2是通过object.defineProperty()方法来进行数据的劫持,对象新增或者直接通过下标修改数组,界面不会自动更新
解决方法:$set(要操作的数组或者对象,下标或键值,要添加的内容)
答:虚拟dom本质是一个js对象,用于描述视图界面结构,在vue中每个组件都有一个render函数,每一个函数都会返回一个虚拟dom数,这也意味着每一个组件都对应着一个虚拟dom树
真实的dom操作会带来大量的性能损耗,当操作节点过多时,会极大的导致渲染速度变慢,虚拟dom在数据发生改变时,新的dom树会和老的对比,然后vue中会帮我们找出最小的更新量,更新必要的虚拟dom,最后通过虚拟dom来修改真实dom
diff算法:
比较新旧虚拟dom,如果节点类型相同,则比较数据,修改数据;如果节点不同,直接插入新的节点,如果给每一个节点都设置了唯一的key,就可以准确找到需要改变的内容,否则就会出现修改一个地方导致其他地方都改变的情况。
答:尽可能的v-if和v-show不要同时使用,v-for是渲染数组或者对象的,v-for的优先级高,导致每循环一次就回去v-if一次,因为v-if是通过创建和销毁来完成显示隐藏的,所以会造成不停的销毁和创建 ,造成页面的卡顿
解决方法:在v-for的外层或者内层包裹一个元素来使用v-if
答:
computed:计算属性,并且有缓存,只有她所依赖的属性值发生变化computed才会重新计算,并且支持同步
watch:监听器,不支持缓存(可以在data中直接使用),监听的数据发生变化才会触发,watch支持异步,监听的函数可以接收两个参数,一个是最新的值,另一个是改变之前的值
计算属性computed :
支持缓存,只有依赖数据发生改变,才会重新进行计算
不支持异步,当computed内有异步操作时无效,无法监听数据的变化
侦听属性watch:
1.不支持缓存,数据变,直接会触发相应的操作;
2.watch支持异步;
3.监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
2、使用场景
computed
当一个属性受多个属性影响的时候就需要用到computed
最典型的例子: 购物车商品结算的时候
watch
当一条数据影响多条数据的时候就需要用watch,搜索数据
1)当监听一个基本数据类型时,直接使用
2)当监听一个引用数据类型时,执行回调且回调函数名字(handler)不可更改(or默认?)
开启深度监听:deep:true
开始初始执行handler函数:immediate:true
v-if:是真正的条件渲染,同时他也是惰性的,如果在初始渲染时条件为假,则什么也不做,直到第一次变为真时,才会开始渲染,条件切换过程会发生销毁和重建
具有更高的切换开销,如果在运行是条件很少改变,使用v-if比较好
v-show:不管初始条件是什么,元素总是会被选二胺,并且知识简单的基于css(display:none/block)进行切换
具有更高的初始开销,如果切换非常频繁,则使用v-show比较好
答:
概念:vue实例从创建到销毁的过程就是生命周期,也就是从开始创建,出啊石化数据,编译模板,挂载dom->渲染,更新->渲染,卸载等一系列过程
beforeCreate():vue实例创建之前调用
created():vue实例创建完成
beforeMount():视图编译之前
mounted():视图编译完成,vuedom加载之后
beforeUpdate():数据改变之前
updated():数据改变之后
beforeDestory():vue销毁之前
destory():vue销毁之后
第一次页面加载触发的-生命周期
beforeCreate():vue实例创建之前调用
created():vue实例创建完成
beforeMount():视图编译之前
mounted():视图编译完成,vuedom加载之后
v-model:主要用于表单类的双向绑定,本质是一个语法糖,可以理解为一个快捷方式,是通过v-bind、v-on来实现的
主要有三个修饰符:
.number 将输入的字符转为有效的数字,不加则是默认字符串类型
.lazy 取代input,监听change事件,当发生改变的时候才会触发
.trim 过滤首尾空格
v-for:列表循环遍历、数组、对象、字符串、数字均可以
v-if:用来确定标签是否渲染
v-show:根据表达式的真假值,切换元素的display:block/none,当条件变化时该指令触发过渡效果
v-text:更新元素的textCount,如果需要更新部分textCount,则需要使用插值{{Mustache}}
v-on:绑定事件监听器,事件类型由参数指定,表达方式可以是一个方法的名字或者是一个内联语句,如果没有修饰符也可以省略 简写形式@
v-bind:主要是用来动态绑定属性,简写为:
v-slot:提供具名插槽或者需要接收prop的插槽,缩写为#
v-once:值渲染元素和组件一次,随后的重新渲染,元素/组件及其所有的子节点被视为静态内容并跳过,这可以用于优化更新性能
14.常见的修饰符及其作用
.stop:等同于js中event.stopPropagation(),防止事件冒泡
.prevent :等同于js中event.preventDefault(),阻止默认行为
.capture:当元素发生冒泡时,先触发带有修饰符的元素,若有多个修饰符,则由内而外触发。如 p1中嵌套p2中嵌套p3.capture中嵌套p4,那么执行顺序为:p3=》p4=》p2=》p1
.slef:只触发自己范围内的事件,不包含子元素
.once:只触发一次
答:1.父组件向子组件传递数据
父组件内设置要传的数据,在父组件中引用的子组件上绑定一个自定义属性并把数据绑定在自定义属性上,在子组件添加props接收即可
2.子组件向父组件传递数据
子组件通过vue实例方法$ emit进行触发并且可以携带参数,父组件监听使用@(v-on)绑定的事件进行监听,然后方法处理
3.兄弟组件之间传递数据
3.1 引入第三方 new vue 定义为 eventBus
3.2)在组件中 created 中订阅方法 eventBus.$ on(“自定义事件名”,methods 中的方法名)
3.3) 在另一个兄弟组件中的 methods 中写函数,在函数中发布 eventBus 订阅的方法
eventBus.$emit("自定义事件名”)
3.4) 在组件的 template 中绑定事件(比如 click)
4.祖孙之间的传值
provide 定义的对象会加载到子组件或者孙子组件中
inject 接收祖先组件中provide函数return出的内容
5.可以通过vuex传值
6.可以使用本地存储进行传值(cookie、localstorge、sessionStorage)
项目使用keep-alive时,可搭配组件name进行缓存过滤
DOM做递归组件时需要调用自身的name
vue-dectools 调试工具里显示的组件名称是由vue中组件name决定的
Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:
加载渲染过程 :
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
子组件更新过程 :
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父组件更新过程 :
父 beforeUpdate -> 父 updated
销毁过程 :
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
主要包括以下几个模块:
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:
vue-router 有 3 种路由模式:hash、history、abstract,对应的源码如下所示:
switch (mode) {case 'history':this.history = new HTML5History(this, options.base)breakcase 'hash':this.history = new HashHistory(this, options.base, this.fallback)breakcase 'abstract':this.history = new AbstractHistory(this, options.base)breakdefault:if (process.env.NODE_ENV !== 'production') {assert(false, `invalid mode: ${mode}`)}}其中,3 种路由模式的说明如下:
(1)hash 模式的实现原理
早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 ‘#search’:
https://www.word.com#search
hash 路由模式的实现主要是基于下面几个特性:
当你修改了data的值然后马上获取这个dom元素的值,
是不能获取到更新后的值,你需要使用$nextTick这个回调,
让修改后的data值渲染更新到dom元素之后在获取,才能成功。
在data()中的修改后,页面中无法获取data修改后的数据,
使用$nextTick时,当data中的数据修改后,可以实时的渲染页面
build 文件夹是保存一些 webpack 的初始化配置。
config 文件夹保存一些项目初始化的配置
node_modules 是 npm 加载的项目依赖的模块
src 目录是我们要开发的目录:
assets 用来放置图片
components 用来放组件文件
app.vue 是项目入口文件
main.js 项目的核心文件
需要做 vuex 数据持久化,一般使用本地储存的方案来保存数据,
可以自己设计存储方案,也可以使用第三方插件。
推荐使用 vuex-persist插件,
它是为 Vuex 持久化储存而生的一个插件。不需要你手动存取 storage,
而是直接将状态保存至 cookie 或者 localStorage中。
模块: 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。
当应用变得非常复杂时,store 对象就有可能会变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。
命名空间: 默认情况下,模块内部的 action、mutation、getter
是注册在全局命名空间的 — 这样使得多个模块能够对同一 mutation 或 action 做出响应。
如果希望你的模块具有更高的封装度和复用性,
你可以通过添加 namespaced:true 的方式使其成为带命名的模块。
当模块被注册后,他所有 getter、action、及 mutation 都会自动根据模块注册的路径调整命名。
1、工厂模式 - 传入参数即可创建实例
虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。
2、单例模式 - 整个程序有且仅有一个实例
vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。
3、发布-订阅模式。(vue 事件机制)
4、观察者模式。(响应式数据原理)
5、装饰器模式(@装饰器的用法)
6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,
该行为有不同的实现方案 - 比如选项的合并策略。
这里只列举针对 Vue 的性能优化,整个项目的性能优化是一个大工程。
对象层级不要过深,否则性能就会差。
不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
v-if 和 v-show 区分使用场景
computed 和 watch 区分场景使用
v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
防止内部泄露,组件销毁后把全局变量和时间销毁
图片懒加载
路由懒加载
异步路由
第三方插件的按需加载
适当采用 keep-alive 缓存组件
防抖、节流的运用
服务端渲染 SSR or 预渲染
资源压缩合并,减少HTTP请求
非核心代码异步加载
利用浏览器缓存
使用CDN
预解析DNS
动态脚本加载
defer
async
defer是在html解析完毕才执行,如果有多个则按加载顺序执行
async是加载完毕后立即执行,如果是多个,执行顺序与加载顺序无关
在开发中,可能会遇到这样的情况。有些资源不需要马上用到,
但是希望尽早获取,这时候就可以使用预加载。
预加载其实是声明式的 fetch ,强制浏览器请求资源,
并且不会阻塞 onload 事件,可以使用以下代码开启预加载
link rel=“preload” href=“http://example.com”
预加载可以一定程度上降低首屏的加载时间,
因为可以将一些不影响首屏但重要的文件延后加载,唯一缺点就是兼容性不好。
懒执行就是将某些逻辑延迟到使用时再计算。
该技术可以用于首屏优化,对于某些耗时逻辑并不需要在首屏就使用的,
就可以使用懒执行。懒执行需要唤醒,一般可以通过定时器或者事件的调用来唤醒。