vue方面
谈一谈对diff算法的理解
-
what(diff是什么)::diff是一种算法,是一种虚拟dom出现之后,由虚拟dom计算出真实dom时的所需要一种最小的操作。
-
why(为什么要使用diff):性能高、兼容性、跨平台。
-
where(在哪里用到了diff):两个节点在进行patch的时候,这个时候就需要用到diff了,patch Vnode,主要作用是能够比较出变化,当存在新旧虚拟dom的时候,会使用diff,如果不存在只是一次新增行为,那是初始化,现在说的是新旧dom都存的时候会用到diff.
-
how(diff是怎么比较的):(总分总的答法:)
- 深度优先,同级比较。
- 首先从顶层节点开始比较,如果是元素,那就看他们有没有孩子,如果有孩子,就向下递归,这就是深度优先,在向下比较的过程中,可以给您介绍下重排算法,假设有4种可能性:
- 1、假设新旧节点首位节点相同,则新旧节点index都加1,再向后依次进行比较。
- 2、新旧节点尾部元素相同,则新旧节点index都减1,再向前进行比较。
- 3、旧节点的首位节点与新节点的尾部节点相同,则旧节点首位节点移到队尾,index加1 进行比较,新节点index减1再与旧节点进行比较。
- 4、旧节点尾部节点与新节点首位节点相同,则旧节点尾部节点移到队首,index减1,新节点index加1 再进行递归比较。
- 若这四种情况都不符合,则只能在新节点中循环遍历节点去老节点中找是否有相同的节点,如果找到,则需要进行重排,并进行打补丁操作(patch)。在这个过程中,则才说的4种情形有可能会重复,因为比较的这个节点也可能有子节点,这样就需要进行递归操作。
vue生命周期
- beforeCreate: 在实例初始化之后,数据观测(data/observer)和event/watcher事件配置之前被调用。
- created: 实例创建完成后被立即调用,数据观测、属性和方法的运算,watch/event事件回调,但是挂载阶段还没开始,$el不可见。
- beforeMouted: 挂载开始之前被调用,render首次被调用。
- mouted: el被新创建的vm.$el替换,并挂载到实例之后调用该钩子,
- beforeUpdate: 数据更新前调用,发生在虚拟dom打补丁之前,这里适合在更新之前访问现有的dom. 如手动移除添加的事件监听器。
- updated: 组件dom已经更新,这里可以执行依赖于dom的操作。
- activated: keep-alive组件激活时调用。
- deactivated: keep-alive组件停用时调用。
- beforeDestroy: 组件实例销毁时调用。在这一步,实例仍然可用。
- destroyed:vue实例销毁后调用,调用后,vue实例所有的事件绑定都会被移除。所有的子实例也会被销毁。
keep-alive在哪个生命周期中执行?是怎么做的?
keep-alive在activated这个生命周期中执行,被包裹在keep-alive中的组件状态将会被保留,例如一个选项卡,如果在一个选项卡中滑到了100条数据,如果切换到别一个tab中,再切换回原来的tab,还会在原来滑到100条数据的位置。
父子组件的渲染及更新顺序
一、 加载渲染过程
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
二、子组件更新过程
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
三、父组件更新过程
父beforeUpdate -> 父updated
四、销毁过程
父beforeDestroy -> 子beforeDestory -> 子destoryed -> 父destroyed
组件间通信
一、父子之间通信:
- 父组件向子组件传值:props,可以是对象或数组。
- 子组件向父组件传值:on()触发自定义事件。
二、多层级嵌套需要传递数据时使用vuex
vuex:vuex提供了一个单向数据流,在全局有一个state存放数据,当组件要更改state中的数据时,必须提交一个mutation,action也可以修改状态,但是可以异步操作的。 action与mutation的区别:
- action提交的mutation不是直接修改状态的.
- action可以包含异步操作,而mutation不行。
- action中的回调函数第一个参数是context,是一个与store实例具有相同属性的方法的对象。
- action通过store.dispatch触发,mutation通过store.commit触发。
三、$attrs/$listeners
vuex主要是多层级嵌套时传递数据的,如果仅仅是传递数据,那用vuex就有点大材小用了。这时候使用$attrs就可以。
- $attrs:它包含了除props中的所有(除class和style)的所有属性,当一个组件没有声明任何props时,那这里会包含所有父作用域中的绑定(除class和style外),通常用v-bind="$attrs".
- $attrs中存入所有非props属性,$listeners中存放了父组件中非原生事件。
四、provide/inject
provide/inject这两个必须成对使用。允许祖代组件向后代组件中注入依赖,不论组件嵌套层级有多深。即:祖先组件中通过provide提供变量,然后在子孙组件中通过inject来注入变量。
谈一谈对vuex的理解。
- 数据都存在state中。
- 想要修改状态必须提交mutation.通过store.commit提交。
- action可以实现异步提交mutation。通过store.dispatch触发。
- getter相当于计算属性,在这里对state中的数据进行计算重组。
vue项目怎么优化?
- v-for和v-if尽量不要一起使用。如果非要一起使用,先在computed中把数据过滤一下。
- 路由懒加载。
- 图片懒加载。
- keep-alive缓存组件。
- v-show重用组件。
- 事件销毁。
- 第三插件按需引入。
- 子组件分割,让子组件管理自己的渲染。
如何提升首页的渲染速度?
- 路由懒加载。这样就不会在首页渲染的时候加载所有的组件,会在路由被访问的时候才加载。
- 图片资源过大,实现图片懒加载。
- 禁止线上生成的map文件。
- 启用ngix中的gzip压缩功能。
- 对于一些通用的工具库可以采用CDN的方式引入。
- 优化代码逻辑,组件化,模块化,增加组件的复用性。精灵图。
说一说对$nextTick的理解?
vue.nextTick() 在下次DOM更新循环结束之后执行延迟回调,获取更新后的DOM.当数据变化后,如果想快速的获取dom可以利用nextTick的回调函数。另外还可以说一下js的event-loop(事件循环)。宏任务、微任务。
vue中的修饰符有哪些?
表单组件的修饰符:
- .lazy:
html <input v-model.lazy="msg"/>v-model默认会在input事件触发后将输入框的值与数据进行同步,使用.laxy修饰符可以在使用change事件时将输入框的值与数据进行同步。 - .number:
html <input v-model.number="num"type="number"/>如果想让用户每次输入的值都转化为数字,可以使用.number修饰符。 - .trim:
html <input v-model.trim="msg"/>自动过滤用户输入的空白字符。
事件修饰符
- .stop:
html <a @click.stop="click"></a>阻止单击事件继续传播。 - .prevent:
html <form @submit.prevent="onSubmit"></form>提交表单不再重载页面。 - .capture:
html<div v-on:click.capture="doThis">...</div>添加事件监听时使用事件捕获模式。 - .self:
html <div v-on:click.self="doThat">...</div>只当在event.target是当前元素自身时触发处理函数。 - .once:
html <a v-on:click.once="doThis"></a>点击事件只会触发一次。 - .passive:
html <div @scroll.passive="onScroll" >...</div>滚动事件的默认行业为(即滚动行为)会立即触发,而不会等待onScroll完成,.passive会告诉浏览器你不想阻止事件的默认行为。
vue双向数据绑定原理。
vue响应式原理。
如果想扩展某个现有的组件怎么办?(vue.mixin)
vue.mixin 可以扩展组件,
你怎么理解路由嵌套。
如果要扩展一个element-ui的表格,去根据关键字去查询出所需的列表怎么做?
如果在data中增加一个属性会发生什么? 从数据响应式的方向去回答。
js中渲染DOM与vue中渲染DOM的区别。
js中的数组copy与vue中的数组拷贝有什么区别?
谈一谈对MVC与MVVM的区别?以及MVVM解决了MVC的哪些问题?
vue项目的权限控制怎么做?左侧显示菜单?在什么存入vuex及localStorage中。
js部分
js中闭包?
在一个函数中创建另一个函数就创建了闭包。闭包有权访问其外部作用域中的变量。闭包的作用:
- 闭包可以用来模拟块级作用域,用立即执行一个函数,来使外部不能访问立即执行表达式中的变量。
- 闭包可以用来创建访问对象中的私有变量的公有方法。
- 可以创建单例。
js中的继承有哪几种?
- 原型链的继承:
function Parent(name) {
this.name = name
this.colors = ['red', 'green']
}
Parent.prototype = {
constructor: Parent,
sayName: function () {
console.log(this.name);
}
}
function Child(name) {
this.name = name
}
Child.prototype = new Parent()
let child = new Child('Mike')
child.sayName() //Mike
//接下来说原型链继承的缺点:
var child1 = new Child('Mike')
child1.colors.push('blue')
console.log('child1.colors:==', child1.colors); //["red", "green", "blue"]
var child2 = new Child('Mike')
console.log('child2.colors:==', child2.colors);//["red", "green", "blue"] */
- 构造函数模式的继承
//借用构造函数的继承方法
function Parent() {
this.colors = ['red', 'green']
}
function Child() {
//继承了Parent
Parent.call(this, 'lily') //this指向Child构造函数
//这样做其实是在Child的实例中调用了Parent的构造函数,这样就会在新Child对象上执行Parent构造函数中定义的所有对象初始化代码,
//结果每个Child实例就会有colors的副本了。同时也向Parent中传递了‘lily’参数
}
var child1 = new Child()
child1.colors.push('blue');
console.log('child1.colors:==', child1.colors); //["red", "green", "blue"]
var child2 = new Child()
console.log('child2.colors:==', child2.colors); //["red", "green"]
- 构造函数模式与原型模式相结合 在子构造函数中用call调用父构造函数,并且可以传值,然后再把父的实例赋值给子的原型:即Child.prototype = new Parent()
function Parent(name) {
this.name = name
this.colors = ['red', 'green']
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Child(name, age) { //构造函数继承
Parent.call(this, name)
this.age = age
}
Child.prototype = new Parent() //原型链继承
Child.prototype.sayAge = function () {
console.log(this.age);
}
var instance1 = new Child('Mike', 27)
instance1.colors.push('blue')
console.log(instance1.colors); //["red", "green", "blue"]
instance1.sayAge() //27
var instance2 = new Child('Lily', 29)
console.log(instance2.colors); //["red", "green"]
instance2.sayAge() //29
- 原型式继承:
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"] };
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
//Object.create()的方法实现如下:
function object(o) {
function F() { }
F.prototype = o;
return new F();
}
js中的阻止默认事件和冒泡分别是什么?
vent.preventDefault() event.stopPropagation()
call,apply,bind的区别与联系?如果bind()之后再执行bind()会改变原函数的this指向吗?
call,apply,bind都是修改this的指向的。call(this,参数列表),apply(this,参数是数组),bind(this,参数列表),但是bind返回的是新函数,需要再调用才能修改this指向。
//调用两遍bind会改变原来函数的this指向吗
let obj = {
name: 'mike'
}
let foo = function () {
console.log(this);
}
let bind1 = foo.bind(obj);
bind1() //obj
let bind2 = bind1.bind(obj);
bind2(); //obj
console.log('bind1:', bind1);
console.log('bind2:', bind2);
//由上面的代码可知,调用两次bind不会改变this的指向。因为调用bind之后只要传入的第一个参数是obj,那this就一定指向obj,再者调用bind之后就返回 了一个新的函数,与原来的foo函数已经没有关系了。
js中的数组copy与vue中的数组拷贝有什么区别?(深拷贝与浅拷贝)
其实是一样的,这里可能是想问如何处理vue中如果多个组件都用了同样的数组对象,如果希望各组件中的数据对象相互独立,应该怎么处理?
computed: {
data: function () {
var obj={};
obj=JSON.parse(JSON.stringify(this.templateData)); //this.templateData是父组件传递的对象
return obj
}
}
js中的作用域。
如果在作用域中声明了很多相同的变量是替换它的值还是整个都替换。
替换值
js中的数组copy与vue中的数组拷贝有什么区别?
浏览器从你输入url是怎么渲染页面的?
vue.delete与js的delete的区别?
vue.delete删除对象的属性,如果这个属性是响应式的,确保删除能更新视图,这个方法主要是用于vue不能检测到属性被删除的限制,它的目标对象不能是一个vue实例或vue实例的根数据对象。
js数组中的增加和删除元素的方法?
- pop():删除数据的最后一个元素,并返回删除的元素。
- push():在数组的尾部增加一个或多个元素,并返回数据的长度。
- shift():删除数组的第一个元素,并返回第一个元素的值。
- unshift():将参数添加到原数组的开头,并返回数组的长度。
- concat():把两个数组合并到一个数组中,并返回一个新数组。
- join():将数组中的所有元素放入一个字符串。
- splice():向数组中添加或删除项目,然后返回被删除的项目。
饿了么
1. fiber react的高阶组件。
2. hook 高阶组件。
3. 怎么理解前后端分离? 仅仅是前后端并行开发就是前后端分离了吗?
4. 写过什么node的中间件?或koa2中间件?
5. koa2与express比有什么优势吗?koa2的洋葱模型有什么优点?
6. 强缓存与协议缓存有什么区别?www.jianshu.com/p/9c95db596…
7. 移动端怎么进行优化?怎么加快页面渲染速度? 从加载和渲染的角度分别解释。
8. PWA有了解吗?
9. 如果有一个中台项目,左侧有菜单,有菜单1和菜单2,分别属于不同的项目,有可能是菜单1是react写的,菜单2是vue写的,通过import引入到这一个中台项目中,从菜单1和2点击分别进入不同的项目,如果这个中台项目中有菜单变化了,怎么通知这所有的菜单项目。
(18年出的微前端 single SPA)
10. 说一下对虚拟DOM的理解?
11. 利用node怎么提高程序的稳定性?
12. koa2中有这样的一个程序:代码1,代码2,代码3,代码4,依次执行,如果代码3想用代码4的执行结果,怎么办?
13. cookie缓存,主程序能访问子域的cookie吗?反过来,子域能访问主域的cookie吗? passport怎么实现单点登录。
cookie是一个可以存放4kb的小型文本数据。localstorage一般浏览器可以接受5M的大小。一级域名可以访问二级域名的cookie,但是两个二级域名之间不可以相互访问的。比如aa.baidu.com与bb.baidu.com这两个二级域名之间的cookie是不能相互访问的,但是给cookie的domain设置为.baidu.com,那么aa.baidu.com与bb.baidu.com就能访问同一个cookie了。path设置为‘/’是允许所有路径都可以访问cookie。