总结一波, 先这样吧,慢慢再补充,有问题…
目录
一、JS部分:
1.原型链
- 对象(除了null)中都有__proto__属性,函数是特殊的对象有__proto__和prototype两种属性。
- __proto__为隐式原型,指向原型对象。它的作用就是当访问一个对象的属性时,如果对象内部不存在,就会去它的原型上去找,直到null。
- prototype为显式原型,是函数独有的,它从一个函数指向一个原型对象(也就是实例的原型对象)。它的作用就是让该函数所实例化的对象们,共享属性和方法
PS:
基本数据类型也有__proto__属性,但是我们不能在运行时为其添加属性和方法。虽然基本类型值本质也是个对象,但他是个密封对象,不能增加、修改、删除属性。
- 引用类型和基本类型的主要区别,就是对象的生存期。
- 使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。
- 而自动创建的基本类型的对象,则只存在于一行代码执行的瞬间,然后立即被销毁。这以意味着我们不能在运行时为基本类型添加属性和方法。 980
2.闭包
含义:在一个函数内,创建一个内部函数,内部函数存在对外部函数变量的引用就会导致闭包。(也可以换句话说:能访问外部函数作用域中的变量的函数)作用是,使函数可以在本定义的作用域外的地方被调用。
function foo() {
var a = 1
function bar() {
a++
console.log(a)
}
return bar
}
const myFoo = foo()
myFoo()
好处:
- 缓存变量,参数和变量不会被垃圾回收机制回收
- 保存私有变量
- 实现方法和属性的私有化
坏处:容易导致内存泄漏
3.手写Promise
手写promise
4.数据类型判断
- typeof:返回7种数据类型:number,string,boolean,undefined,symbel,object,function
- instanceof:用来判断对象和数组 ([ ] instanceof Array)
- constructor: 指向构造函数,原型链上的方法,所以不能用来判断null和undefined
- Object.protoptype.tostring.call() - - 相对来说最准确的方式
综合一下:
function gettype(obj) {
var type = typeof obj;
if (type !== 'object') {
return type;
}
//如果不是object类型的数据,直接用typeof就能判断出来
//如果是object类型数据,准确判断类型必须使用Object.prototype.toString.call(obj)的方式才能判断
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
}
5.Map和Set
- Map()
map是一组键值对的结构,具有极快的查找速度。解决了JavaScript的对象键必须是字符串的问题。在map中,Number或者其他数据类型也可以作为键。
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value /或修改
m.has('Adam'); // 是否存在key 'Adam': true
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
- Set()
Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。
var s1 = new Set(); // 空Set
var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}
s.add(4);
s; // Set {1, 2, 3, "3", 4}
s.delete(3);
s; // Set {1, 2, "3", 4}
//数组去重 百试不爽
var arr=[...new Set([1,2,1,2,3])]
// [1, 2, 3]
6.垃圾回收机制
- 标记清楚:在运行时给内存所有变量加上标记,然后去除掉在执行环境中的变量和被这些变量引用的变量。剩下的带有标记的变量视为准备删除的变量,最后垃圾回收机制扫下周期运行时,释放这些变量,回收占用的空间
- 引用计数:引用表,保存了内存里所有资源的引用次数。这个数为0时,就说明用不到了,就释放。
7.安全随机数
Math.random() : 返回介于 0(包含) ~ 1(不包含) 之间的一个随机数。该函数不是加密安全的随机数生成器。
window.crypto.getRandomValues(typedArray) : 返回非0的正整数,可以获取符合密码学安全性要求的随机值。
typedArray是一个基于整数的 TypedArray,其可以是 Int8Array、Uint8Array、Int16Array、 Uint16Array、 Int32Array 或 Uint32Array。
//生成随机随机数
var arr = new Uint16Array(8);
var crypto = window.crypto || window.webkitCrypto
|| window.mozCrypto || window.oCrypto || window.msCrypto;
window.crypto.getRandomValues(arr);
// 生成UUID
window.crypto.randomUUID();
总的来说:
Math.random() 随机数并不是实时生成的,而是直接生成一组随机数(64个),并放在缓存中。当这一组随机数取完之后再重新生成一批,放在缓存中。并且是可以被模拟、计算出来的。
getRandomValues() 方法的底层实现是没有缓存的,并且是实时生成的,因此,性能上是要比 Math.random() 差的
8.贪心算法
贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
//你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
//你拥有的饼干数量和尺寸都足以让所有孩子满足。
//所以你应该输出2.
输入: g = [1,2], s = [1,2,3]
输出: 2
var findContentChildren = function(g, s) {
g.sort(asc);
s.sort(asc);
let gp = 0,
sp = 0;
while (sp < s.length && gp < g.length) {
// 发现满足条件的饼干,喂饱一个孩子
if (s[sp] >= g[gp]) {
gp++;
}
// 继续找下一块饼干
sp++;
}
return gp;
function asc(a, b) {
return a - b;
}
};
console.log(findContentChildren([1,2,2,4,6,7,8,8,8,9,9], [1,3,4,4,5,8,9]))//6
9.js循环
for...of
语句在可迭代对象包括: Array,Map,Set,String,TypedArray,arguments 对象等等.弥补了弥补了forEach
和for-in
循环的短板
10.ES6数组新方法
-
forEach()
和map()
forEach()会修改原来的数组,不会返回执行结果。map()方法会得到一个新的数组并返回。
map的执行速度会更快。 -
filter()
创建一个新数组, 返回符合条件的元素。 -
reduce()
官方:对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
简单来讲,他的主要作用,就是可以取到上次遍历的返回值。进而做累加等操作 -
some()
判断数组中是不是,至少有1个元素,通过了被提供的函数。 -
every()
指数组内的所有元素是否都能通过某个指定函数 -
Array.from()
:
用于将类似数组的对象和可遍历对象转为真正的数组 -
Array.of()
:
用于将一组值,转换为数组。
用来弥补数组构造函数Array()
的不足,基本上可以用来替代Array()
或new Array()
-
copyWithin()
:
将指定位置的成员复制到其他位置,然后返回当前数组,会修改当前数组。 -
find()
和findIndex()
find:找出 第一个 符合条件的数组成员
findIndex: 返回 第一个 符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1 -
fill()
使用给定值,填充一个数组。用于空数组的初始化非常方便。 -
entries()
,keys()
和values()
用于遍历数组。它们都返回一个遍历器对象。
keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历 -
includes()
表示某个数组是否包含给定的值,方法返回一个布尔值。 -
flat()
,flatMap()
flat:用于将嵌套的数组“拉平”,变成一维的数组。返回一个新数组
flatMap:对原数组的每个成员执行一个函数,然后对返回值组成的数组执行flat()方法,返回一个新数组。 -
at()
接受一个整数作为参数,返回对应位置的成员,主要是为了解决运算符[]
不支持负索引。
11.Math方法
- Math.abs() 返回绝对值
- Math.ceil(),Math.floor() 向上取整和向下取整
- Math.max(),Math.min() 最大值和最小值
- Math.round() 四舍五入
- Math.random() 随机数
- Math.pow() 指数运算
- Math.sqrt() 平方根
- Math.log() 自然对数
- Math.exp() e的指数
12.深拷贝&浅拷贝
基本类型:
引用类型:
访问一个引用类型,需要先从栈中获取该对象的指针,然后再通过指针访问堆内存对应的数据。
浅拷贝只拷贝这个对象的指针,原来的对象和拷贝的对象指向的是堆内存中的同一个东西,彼此之间的操作会互相影响。
深拷贝则会在堆内存中重新分配内存,拥有不同的地址,但值是一样的。
- 浅拷贝的方法:“=”赋值、"…"展开运算符、Object.assign() // 一层深拷贝
- 深拷贝: JSON.parse(JSON.stringify())、递归拷贝、var newObj = Object.create(oldObj)、第三方库lodash.clonedeep
13.es2019了解多少
String.prototype.trimStart()
/String.prototype.trimEnd()
头\尾的空格文本去掉Object.fromEntries()
键值对还原成对象结构Array.prototype.flat()
/Array.prototype.flatMap()
数组展平
[1, 2, [3, 4]].flat();// [ 1, 2, 3, 4 ]try...catch
catch的参数改为可选JSON.stringify()
加强格式转化JSON.parse()
添加了对行分隔符(\u2028) 和段落分隔符(\u2029)的支持
14. 隐式转换
- 数字运算:
“+”:将表达式的值转换为String(仅当有一个是String类型);
“-”:将表达式的值转换为Number; - “.”
被隐式转换为对象;
var a = 2;
console.log(a.toString()); // ‘2’; a被转换为对象,可以调用方法 - “if语句”
判断的条件表达式会被隐式转换为Boolean类型 - “==”
JS的非严格匹配时,会进行隐式类型转换
15.在地址栏中输入一个网址,这个过程中发生了什么
- 使用DNS解析,寻找服务器的ip
- TCP连接
- 发送HTTP请求
- 服务器处理HTTP请求并返回报文
- 浏览器解析渲染页面
- 连接结束
16.js中哪些方法可以实现异步操作
(1)定时器都是异步操作
(2)事件绑定都是异步操作
(3)promise
(4)回调函数可以理解为异步
(5)async await
(6)$nextTick
17.常用的数组、字符串方法
- 数组:
cancat()–连接数组、
jion()–通过指定的分隔符进行分隔为字符串
pop()–末尾删除
push()–末尾添加
shift()-- 开头删除
unshift()-- 开头添加
reverse()-- 颠倒数组
slice()-- 查找数组中的某一位,[)区间
splice()-- 添加或删除
sort()-- 排序
tostring-- 转化为字符串 - 字符串;
concat()-- 连接字符串
charAt()-- 查找指定位置的字符
search()-- 查找字符出现的位置
indexOf()-- 查找字符出现的次数
replace()-- 替换符合正则的字符
slice()-- 提取一个子串
substr()-- 按长度提取一个子串
split()-- 分割成数组
ToLowerCase()-- 转化成小写
toUpperCase()-- 转化为大写
trim()-- 去掉空白符
18.阻止事件冒泡
@click.stop : 阻止事件冒泡
19.取消默认事件
@click.prevent : 阻止事件默认行为
20. 简述cookie、localstorage、seesionstorage
名称 | 大小 | 网络请求 | 生命周期 |
---|---|---|---|
cookie | 4kb左右 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 默认是关闭浏览器后失效, 但是也可以设置过期时间 |
localstorage | 5M | 仅在浏览器中保存,不参与和服务器的通信 | 除非手动被清除,否则永久保存 |
SessionStorage | 5M | 仅在浏览器中保存,不参与和服务器的通信 | 仅在当前会话(窗口)下有效,关闭窗口或浏览器后被清除, 不能设置过期时间 |
21. js跨域如何解决
- jsonp跨域,原理:script标签没有跨域限制的漏洞实现的一种跨域方法,只支持get请 求。安全问题会受到威胁。
- postMessage window的一个属性方法。
- websocket
- nginx反向代理
- iframe跨域
22.webpack proxy跨域
首先需要明白webpack proxy跨域只能用作与开发阶段,临时解决本地请求服务器产生的跨域问题。并不适合线上环境。配置在webpack的devServer属性中。webpack中的devsever配置后,打包阶段在本地临时生成了一个node服务器,浏览器请求服务器相当于请求本地服务。
23.js继承的实现
- 原型链继承
- 构造函数继承
- 组合继承
- 原型继承
- 寄生继承
- 寄生组合继承
24.事件冒泡和事件捕获
二、HTML部分
To:前端常见知识点三之HTML
三、Css部分
1.水平垂直居中多种方式
- 绝对定位 + maring:auto
- 绝对定位 + transform反向偏移量值
- display:tabel-cell + vertical-align:center
- 弹性布局:align-items和justify-content 为center
2.弹性布局
懒得写了
3.grid布局
有点多,看链接吧:grid布局
4.超出隐藏
overflow:hidden;
text-overfollw:ellipesis;
white-spce:nowrap
// += 超出两行隐藏:
display:-webkit-box; //将对象作为弹性伸缩盒子模型显示
-webkit-box-orient:vertical; //设置盒子子元素排列方式
-webkit-line-clamp:2; //显示的行数
5.画一个三角形
div{
width:0px;
height:0px;
border-top: 10px solid red;
border-right: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 10px solid transparent;
}
6.less特性
- 变量 :@+变量名
- 混合:直接引用类名下的属性。(.posta {color: red; .bordered;})
- 嵌套规则:可以直接嵌套媒体查询
- 运算:使用()
- 函数:提供了多种函数 ( 比如 width:percentage(0.5) // 会处理成width: 50% )
- 命名空间:打包使用一些属性集
- 作用域:使用一个变量先从自身找,找不到会再向父级找
- 注释:支持" // "注释,打包时会自动过滤掉
- 导入:支持使用@Import导入样式文件
7.BFC
块级格式化上下文,这是一个独立的渲染区域,规定了内部如何布局、并且这个区域的子元素不会影响到外面的元素。多用于清楚浮动,解决高度塌陷、父子margin重叠等问题(不会吧不会吧,现在还有人用浮动。而且用了还不清除浮动 ?diss + 骂骂咧咧10086次)
//清除浮动
.clearfix:after{
content:""; /*内容为空*/
height:0; /*高度为0*/
line-height:0; /*行高为0*/
display:block; /*块级元素*/
visibility:hidden; /*隐藏*/
clear:both; /*清除浮动*/
}
.clearfix{
zoom:1; /*兼容IE678*/
}
8.css选择器权重
style(1000) => ID(100) => Class/伪类/属性选择器(10) => 标签(1) => ‘*’、’>’、’+’ (0)
9.等高布局
父级overflow:hidden
margin-bottom:-300px;
padding-bottom:+300px;
10.你知道的css伪类有哪些
- :first-line | 选择文本的第一行
- :first-letter | 选择这一行的第一字
- :link | 未访问的超链接
- :checked | 选中的复选框
- :lang() | 通过指定的lang值显示样式
11.左边定宽,右边自适应
- flex布局实现
- 浮动实现
- 绝对定位
12.float与flex
设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效。
13.画一条0.5的线
height: 1px;
transform: scale(0.5);
14.画一个三角形?
a{
width: 0;
height: 0;
border-width: 100px;
border-style: solid;
border-color: transparent #0099CC transparent transparent;
transform: rotate(90deg); /*顺时针旋转90°*/
}
四、浏览器部分
To:前端常见知识点三之浏览器
五、Vue部分
1.$nextTick
原理就是微任务
2.$set
问题:
当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,或更新此属性的值,是不会更新视图的。
简言之:下面单个修改属性this.items[0] = {…}是不会更新视图的,除非直接更新this.items = [{…}]
data() {
return {
items: [
{ message: "one", id: "1" },
{ message: "two", id: "2" },
{ message: "three", id: "3" },
],
};
},
mounted() {
//此时对象的值更改了,但是视图没有更新
this.items[0] = { message: "测试", id: "1" };
// 您还可以使用 vm.$set实例方法,这也是全局 Vue.set方法的别名
this.$set(this.items, 0, { message: "测试", id: "4" }); //$set可以触发更新视图
// 调用方法:this.$set或Vue.set( target, key, value )
// target:要更改的数据源(可以是对象或者数组)
// key:要更改的具体数据
// value :重新赋的值
// this.$set或Vue.set 这两个是同一个东西,唯一的区别就是一个是通过原型访问,一个是通过vue实例
},
原因:
由于 JavaScript 的限制,Vue 不能检测数组和对象 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
自己说原因:
- 双向绑定使用
object.defineProperty
劫持数据存在的问题:1.不能监听数组索引和长度的变更;2.无法监听 属性的添加和删除;3. 必须遍历对象的每个属性。 - this.items[0] 不能触发视图更新就是因为defineProperty这个数据劫持方法不能监听数组索引
还不明白,看下面这个Vue数据双向绑定
3.Vue数据双向绑定
2.0
:
Vue实现数据双向绑定主要利用的就是: 数据劫持和发布订阅模式。
自己的观点(不看也罢):用数据劫持实现监听数据变化,用发布订阅的模式,实现一个数据变化通知多个视图更新。
- 所谓发布订阅模式就是,定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个发布者,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
- 所谓数据劫持,就是利用JavaScript的访问器属性,即Object.defineProperty()方法,当对对象的属性进行赋值时,Object.defineProperty就可以通过set方法劫持到数据的变化,然后通知发布者通知所有观察者,观察者收到通知后,就会对视图进行更新。
- Vue 会在初始化实例时会遍历此data()中对象所有的 property,并使用
Object.defineProperty
把这些 property 全部转为 getter/setter。 - 每个组件实例都对应一个 watcher 实例。在 property 被修改时会触发时setter,然后通知 watcher,从而使它关联的组件重新渲染。
简单的setter和getter:
let leo = {}, age = 18;
Object.defineProperty(leo, 'age', {
get(){
// to do something
console.log('监听到请求数据');
return age;
},
set(newAge){
// to do something
console.log('监听到修改数据');
age = newAge > age ? age : newAge
}
})
leo.age = 20; // 监听到修改数据
console.log(leo.age); // 监听到请求数据 // 18
leo.age = 10; // 监听到修改数据
console.log(leo.age); // 监听到请求数据 // 10
3.0
:(把3.0带上算是个加分项)
使用Proxy代替defineProperty
Vue3使用代理模式(Proxy)实现数据劫持,Object.defineProperty只能监听属性,而Proxy能监听整个对象,通过调用new Proxy()
,可以创建一个代理用来替代另一个对象被称为目标,这个代理对目标对象进行了虚拟,因此该代理与该目标对象表面上可以被当作同一个对象来对待。代理允许拦截在目标对象上的底层操作,而这原本是Js引擎的内部能力,拦截行为使用了一个能够响应特定操作的函数,即通过Proxy去对一个对象进行代理之后,我们将得到一个和被代理对象几乎完全一样的对象,并且可以从底层实现对这个对象进行完全的监控。Proxy对象是ES6引入的新特性,Vue3放弃使用了Object.defineProperty,而选择了使用更快的原生Proxy,即是在兼容性方面更偏向于现代浏览器。
说了这么多proxy的优势在于:1.Proxy可以直接监听对象而非属性、2.Proxy可以直接监听数组的变化。解决了之前所说的defineProperty存在的问题。
proxy:
var target = {a: 1};
var proxy = new Proxy(target, {
set: function(target, key, value, receiver){
console.log("watch");
return Reflect.set(target, key, value, receiver);
},
get: function(target, key, receiver){
return target[key];
}
});
proxy.a = 11; // watch
console.log(target); // { a: 11 }
4. Vue生命周期 2.0 => 3.0
beforeCreate => use setup() 开始监控Data对象数据变化、开始初始化事件
created => use setup() 实例已经创建完成,完成了data 数据的初始化,el没有,可以初始化data数据
beforeMount => onBeforeMount 开始执行挂载钩子,编译模板,把data里面的数据和template生成html,完成了el和data 初始化,但还没有挂在html到页面上。
mounted => onMounted 挂载完成,template渲染到了html,一般可以做一些ajax操作
beforeUpdate => onBeforeUpdate 实时监控数据变化
updated => onUpdated 随时更新DOM
beforeUnmount => onBeforeUnmount
unmounted => onUnmounted
errorCaptured => onErrorCaptured
renderTracked => onRenderTracked
renderTriggered => onRenderTriggered
activated => onActivated
deactivated => onDeactivated
- setup:执行时机是在 beforeCreate 之前执行
- errorCaptured:在捕获一个来自后代组件的错误时被调用
(err: Error, instance: Component, info: string) => ?boolean
- renderTracked:
(e: DebuggerEvent) => void
跟踪虚拟 DOM 重新渲染时调用 。renderTracked({ key, target, type }) - renderTriggered:
(e: DebuggerEvent) => void
当虚拟 DOM 重新渲染被触发时调用。和 renderTracked 类似,接收 debugger event 作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。 - activated:被 keep-alive 缓存的组件激活时调用。
- deactivated: 被 keep-alive 缓存的组件失活时调用。
5.虚拟DOM
- 在实际的代码中,会对新旧两棵树进行一个深度优先的遍历,这样每个节点都会有一个唯一的标记
- 在深度优先遍历的时候,每遍历到一个节点就把该节点和新的的树进行对比。如果有差异的话就记录到一个对象里面
6.取消请求
7.vue.js两个核心
数据驱动和组件化
8.修饰符
(1)@keyup.delete、
(2).lazy 将model的更新方式从input改变为change
<inputv-model.lazy=“msg” >
(3).number 将用户输入的值转换为数字类型
(4).trim 自动过滤用户输入的首尾空白字符
(5)@click.once : 事件只触发一次
9.vue核心之虚拟DOM
每次更新时不会直接更新到真实的DOM上,而是通过diff方法比较每次的差异,然后将更新的内容暂存在本地的一个虚拟DOM上,等待更新完成后,再一次性将虚拟DOM映射到真实DOM上
10.key值得作用
key的作用主要是为了高效的更新虚拟DOM。
11.为什么data必须是函数
当data选项是一个函数的时候,这样各个实例中的data有了自己的作用域,互不干扰。
12.子组件调用父组件的方法
(1)This. p e r t e n t . f n ( ) ( 2 ) P r o p s ( t h i s . f a t h e r M e t h o d ( ′ h e l l o ′ ) ; ) ( 3 ) T h i s . pertent.fn() (2)Props (this.fatherMethod('hello');) (3)This. pertent.fn()(2)Props(this.fatherMethod(′hello′);)(3)This.emit(“fn”,”val”)
13.父组件调用子组件的方法
Ref获取子组件实例
(1)this.$ refs.child.fn()
(2)this.$ refs.child.
e
m
i
t
(
“
f
n
”
,
”
v
a
l
”
)
+
t
h
i
s
.
emit( “fn”, ”val” ) + this.
emit(“fn”,”val”)+this. on( “fn”,(val) => {} )
14.组件间的传值
Vuex
Pops
$emit
15.页面级组件间的传值
(1)路由传值:
this .$router.push({
name: ‘routePage’ ,
query/ params : {
routeParams: params
})
用params传值,页面刷新时,参数会消失,用query则不会,但参数会显示在地址栏中。
(2)vuex
16.动态组件
components:{
one: {template:‘
我是线路一
’},two: {template: ‘
我是线路二
’},thr: {template: ‘
我是线路三
’}}
17.Transition过渡组件
(1)name版
出现的过程: name-enter(初始态) => name-enter-active(中间态) => name-enter-to(终止态)
消失的过程: name-leave => name-leave-active => name-leave-to
(2)钩子实现过渡动画
18.keep-alive内置组件的作用
缓存
会在mouted后面增加两个周期:activiated、deactivated
直接用keep-alive标签包裹,或者在router文件中配置keepAlive属性
19.watch和computed的区别
(1)watch,用于监听数据变化,可以监听:props、data、computed内的数据;watch提供两个参数(newValue,oldValue),第一个参数是新值,第二个参数保存旧值;
(2)computed是计算属性,用于处理复杂的逻辑运算,有缓存机制,只有数据改变时才会触发,性能更佳;
20. 父子组件加载顺序
beforeCrete => created => beforeMount
=>子组件:(beforeCrete => created => beforeMount=> mounted)
=>子组件:(beforeCrete => created => beforeMount=> mounted)
=> mouned
21. 浏览器渲染过程
(1)处理 HTML 标记并构建 DOM 树。
(2)处理 CSS 标记并构建 CSS规则树,根据执行顺序解析js文件。
(3)将 DOM 与 CSSOM 合并成一个渲染树。
(4)根据渲染树来布局,以计算每个节点的几何信息。
(5)将各个节点绘制到屏幕上。
22.深度监听对象的属性
在watch函数中添加和监听对象同名的对象
dataName:{
handler(newVal, oldVal){
console.log(newVal)
},
deep:true
}
六、vue-router篇
1.动态路由
Routes:[
{
Path: “/home/:id”
Name: “home”
Compont: Home
}
]
调用:$route.params.id
2.路由守卫
(1)全局前置守卫:router.before Each
(2)全局解析守卫:router.beforeResolve 导航被确认之前,同时在组件被解析之后
(3)全局后置钩子:router.afterEach(to,from)
(4)路由独享守卫:beforeEnter()
(5)组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
3.$router和$route的区别
(1)$router他是vuerouter实例应用,主要实现路由跳转,想跳转不同的路径使用router.push方法
(2)$route是一个跳转的路由对象,每一个路由都会有一个$route对象,是一个局部的对象,可以获取对应的name,path,params,query等
4.vue-router响应路由参数的变化
用watch 检测
watch: { // watch的第二种写法
$route: {
handler (to, from){
console.log(to)
console.log(from)
},
deep: true
}
},
5.vue-router传参
用params传值,页面刷新时,参数会消失,用query则不会,但参数会显示在地址栏中
6.vue-router路由的配置
path、name、component
7.路由懒加载
(1)vue异步组件:
component: resolve => require(['@/components/home'],resolve)
(2)路由懒加载:
const Home = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home')
(3)webpack的require.ensure(): (r就是resolve)
component: r => require.ensure([], () => r(require('@/components/home')), 'demo')
8.如何实现两个路由出口
{
path:'double',
components: {
default:resolve=>require([’…/components/Vue06-a.vue’],resolve),
bottom:resolve=>require([’…/components/Vue06-b.vue’],resolve)
}
}
< router-view class = "view one" > </ router-view >
< router-view class = "view two" name = "a" > </ router-view >
想实现多个router-view就要使用components,并在里面配置router-view的name属性对应的组件。
default是默认路由,就是不设置路由的router-view都会显示default指向的组件。
9.嵌套路由
children属性:
routes: [
{
path: "/user/:id" ,
component: User,
children: [
{ path : "/user/foo/:key" , component : Foo },
{ path : "/user/bar/:key" , component : Bar }
]
}
]
10. 路由跳转的方式有哪些
(1) router-link
(2) this.$router.push() (函数里面调用)
(3) this.$router.replace() (用法同push)
(4) this.$router.go(n)
11.vue-router的两种模式
-
hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。hash模式背后的原理是
onhashchange
事件,可以在window对象上监听这个事件。window.onhashchange = function(event){ console.log(event.oldURL, event.newURL); let hash = location.hash.slice(1); document.body.style.color = hash; }
-
history —— 利用了 HTML5 History Interface 中新增的
pushState()
和replaceState()
方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。 -
因此可以说,hash 模式和 history 模式都属于浏览器自身的特性,Vue-Router 只是利用了这两个特性(通过调用浏览器提供的接口)来实现前端路由。
两者的区别:
- 除了外观上;hash模式#后面的变化并不会导致浏览器向服务器发出请求,不会刷新请求、重新加载页面; history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致
- hash兼容性会比history 模式好,因为history 模式是依赖HTML5 的Web History API,特定浏览器才会支持;
- hash模式不利SEO,爬虫不会读取到 # 后的内容,因为会把 # 当作是锚点,这也导致会与网站里的锚点功能产生冲突
七、vuex篇
1. vuex的属性及其各自的特性
(1)state :存储数据比如一些变量和对象 ,使用语法:this.$store.state
(2)getters :可以认为是计算属性
(3)mutations: 用来更新state里面的数据
(4)actions :提交mutations而不是直接变更状态,actions可以包含任意异步操作
(5)modules : 可以把某个模块都能分割成具有state,actions ,mutations,actions的作用
八、axios篇
1.axios和ajax的区别
(1)Axios 是一个基于 promise 的 HTTP 库。
(2)对Ajax的再封装,基于promise,链式调用
(3)可以拦截请求和响应
(4)自动转换 JSON 数据
(5)Axios的post请求参数默认不是fromdata格式需要用qs转换格式
(6)客户端支持防御 XSRF(跨站请求)
(7)axios体积小 只需在要使用的目录下 npm install axios --save
(8)ajax 需要导入jQuery【体积较大 只是为了ajax去引入是不值得的】
2.get、post的区别
1)get传参方式是通过地址栏URL传递,是可以直接看到get传递的参数,post传参方式参数URL不可见,
2)get传递数据受到URL大小的限制,URL最大长度是2048个字符。post没有长度限制
3)get请求可以被缓存,post不可以被缓存
4)get请求的记录会留在历史记录中,post请求不会留在历史记录
九、ajax的实现过程
1.渐进式框架
每个框架都不可避免的会有自己的一些特点,从而会对使用者有一定的要求,这些要求就是主张,主张有强有弱,他的强势程度会影响在业务开发中的使用方式。
2.MVVM的理解
(1)我们可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为
(2)View是视图层,用户操作界面
(3)ViewModel是链接Model和View的一个桥,当ViewModel对Model进行更新的时候,会通过数据绑定更新到View
3. vue和react、angular的区别
(1)vue使用的是template模版编写。react使用的是jsx语法。
(2)数据流不同:vue可以进行组件与dom之间v-modle双向绑定。react从始至终都只有单向数据流
(3)Vue 似乎是三个框架中最轻量的,也是最简单易用的
(4)vue、react更加灵活、他们的库可以和各种包搭配;Angular 是一个 “完整的解决方案” - 功能齐全,你可以愉快的开始开发。你不需要研究库,路由解决方案或类似的东西。
4. mvc和mvvm区别
mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到View的问题。
性能优化篇
1.页面优化的方法
打包压缩、gizp压缩、精灵图、图片懒加载、图片压缩、避免重定向、缓存页面、路由懒加载
2. 防抖节流
http篇
- 三次握手
1、第一次握手:客户端给服务器发送一个 SYN 报文。
2、第二次握手:服务器收到 SYN 报文之后,会应答一个 SYN+ACK 报文。
3、第三次握手:客户端收到 SYN+ACK 报文之后,会回应一个 ACK 报文。
4、服务器收到 ACK 报文之后,三次握手建立完成。
项目相关(不重要)
1.作弊检测
2. express起一个服务
3. express常用api
4. express连接数据库
5. sql语句
增:insert into xx values()
删:delete from xx where id = 1
改:updata xx set name = “” where id = 2;
查:select name from xx where id = 1
6. 原生Audio播放事件
7.常见的网站漏洞有哪些?
(1)有跨站脚本攻击(XSS)
(2)跨站请求伪造(CSRF)
(3)点击劫持
(4)SQL注入
(5)DDOS攻击
(6)DNS劫持
8.ssl加密
分为对称和非对称加密
(1)对称加密。 客户端和服务端公用一个密钥对消息加解密。(客户端和服务端约定好一个加密钥匙。客户端在发消息浅用该密匙对消息加密,发送给服务器,服务器在用该密匙进行解密拿到消息)
(2)非对称加密。客户端和服务端都有公钥和私钥。公钥加密的内容只有对应的私钥解密。私钥自己留着,公钥发给对方。这样发送消息之前,对方的公钥对消息进行加密,受到后在用自己的私钥进行解密。
9.WebSocket
(1)new一个sockJS()
(2)获取STOMP子协议的客户端对象: Stomp.over(socket);
(3)向服务器发起websocket连接.connect
(4)处理请求和响应.subscribe