vue面试题(一)

1=>为什么data是一个函数 【理解】 ok

每复用一次组件,就会返回一分新的data。
也就说:【每个组件实例创建】一个【私有】的数据空间。各个组件维护各自的数据。
如果单纯的写成对象形式,那么所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
data(){
    return{
        
    }
}

3=> vue的生命周期 8+2 ok

我们都知道vue常用的8个生命周期,但是这几个生命周期你熟悉吗
activated keep-alive 专属,组件被激活时调用 [ai k t v ti de]
第一次进入也会触发activated  

deactivated keep-alive 专属,组件被销毁时调用 【di ai k t v ti de】

4=> 怎样理解 Vue 的单项数据流 ok

数据总是从父组件传到子组件,
子组件没有权利修改父组件传过来的数据,[如果你强行更改,vue会有红色的警告,告诉你这个是单向的]
只能请求父组件对原始数据进行修改。

这样会防止从子组件意外改变父组件的状态,
从而导致你的应用的数据流向难以理解。

5=> v-if 和 v-for 为什么不建议一起使用 ok

v-for和v-if不要在同一标签中使用,
因为解析时先解析v-for然后在解析v-if,[会消耗性能的哈]
如果遇到需要同时使用时可以嵌套一层元素  
<template></template>

5.0 template 的作用

template的作用是模板占位符,可帮助我们包裹元素.
但在循环过程当中,template不会被渲染到页面上

template标签不支持v-show指令,
即v-show="false"对template标签来说不起作用。
template标签支持v-if、v-else-if、v-else、v-for这些指令。

5.1=> vue3 v-for和v-if做了更改

很幸运 vue 3.x 中, v-if 总是优先于 v-for。

6==>Vue如何检测【数组变化】 ok

数组考虑性能原因没有用 defineProperty 对数组的每一项进行拦截,
而是选择对7种数组(push,shift,pop,splice,unshift,sort,reverse)方法进行重写(AOP切片思想)。
所以在 Vue 中修改数组的索引和长度无法监控到。

需要通过以上7种变异方法修改数组才会触发数组对应的watcher进行更新。【这一句自己理解就可以了】

07==> Vue的父子组件生命周期钩子函数执行顺序 ok

加载渲染过程
父beforeCreate -> 父created -> 父beforeMount ->
->子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
【你可以理解页面渲染,这样就好理解了】

子组件更新过程
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

父组件更新过程
父beforeUpdate -> 父updated

销毁过程
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

8. 虚拟DOM是什么?有什么优缺点?

由于在浏览器中频繁操作DOM代价是很昂贵的。会产生一定性能问题。这就是虚拟Dom的产生原因。

Vue2的Virtual DOM 借鉴了开源库 snabbdom 的实现。
Virtual DOM本质就是用一个[原生的JS对象]去[描述]一个[DOM节点],是对真实DOM的一层抽象。
上面这一句话就翻译为代码 就是
<div>
 <p>123</p>
</div>
对应的virtual DOM(伪代码):
var Vnode = {
 tag: 'div',children: [
  { tag: 'p',text: '123' }
 ]
};

优点:
1、保证性能下限:虽然它的性能并不是最优的;但是比起粗暴的DOM操作性能要好很多,还有不错的性能,

2、无需手动操作DOM:我们不需手动去操作DOM,只需要写好代码逻辑,
框架会【根据虚拟DOM】和【数据双向绑定】,帮我们自动更新视图,极大提高我们的开发效率。

3、跨平台:虚拟DOM可以进行更方便地跨平台操作,

缺点:
1、无法进行极致优化:虽然虚拟DOM + 合理的优化,足以应对大部分应用的性能需要,但在一些【性能要求极高】的应用中虚拟DOM无法没满足
2、首次渲染大量DOM时,由于多了一层DOM计算,会比innerHTML插入慢。
```w


#### 1=> Vue3.0 和 2.0 的【响应式原理】区别

Vue3.x 改用 Proxy[pu luo k she] 替代 Object.defineProperty[di fai n prɒ pə ti]。
因为 Proxy 可以直接监听对象和数组的变化,
因为 defineProperty是不可以直接对数组进行监听
Vue2 中修改数组的索引和长度无法被监控到。


#### 2=> Vuex 页面刷新数据丢失怎么解决?

在刷新页面的时候,将vuex中的只存在本地
也可以使用第三方插件。 vuex-persist (pəˈsɪ s t])插件,
它是为 Vuex 持久化储存而生的一个插件。


#### 3 你都做过哪些 Vue 的性能优化?

语法方面:
v-if 和 v-show 区分使用场景
computed 和 watch 区分场景使用
v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if

//数据方面
对象层级不要过深,否则性能就会差。
不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)

// 加载-缓存
图片懒加载
路由懒加载
第三方插件的按需加载
适当采用 keep-alive 缓存组件
防抖、节流的运用


#### 4 Vue.mixin 的使用场景和原理 【没有理解】

你自己组织一下mixin的使用,这个太复杂了

在日常开发中,我们经常会遇到在不同组件中经常用到一些相同或者相似的代码,
这些代码的功能相对独立,可以通过vue 的 mixin 功能抽离公共的业务逻辑,原理类似“对象的继承”,
当组件初始化时会调用 mergeOptions 方法进行合并,
采用策略模式针对不同的属性进行合并。当组件和混入对象含有相同名选项时,
这些选项将以恰当的方式进行“合并”。


#### 5. nextTick 使用场景和原理

场景:进行tab切换的时候,当显示A组件的时候。
A组件的input自动聚焦。这个时候获取A组件的input实例就会出现undefiend

为什么会出现undefined?
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。

原理:
nextTick 将回调延迟到下次 DOM 更新循环之后执行


#### 6、 keep-alive 使用场景和原理

keep-alive 是 Vue 内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载。
常用的两个属性 include/exclude,符合条件的组件或者页面进行缓存。 [include 是页面中的name ]
include的类型可以是字符串,数组,正则。

两个生命周期 activated/deactivated,用来得知当前组件是否处理活跃状态。
keep-alive 运用了 LRU 算法,选择最近【久未使用的组件】予以淘汰。
keep-alive其实还有一个属性max,最大允许缓存多少个,如果超出最大个数。
会将已缓存组件中最久没有被访问的实例会被销毁掉。


#### 7、Vue.set 方法原理

在两种情况下修改 Vue 是不会触发视图更新的。
1、给响应式对象新增属性,这个时候是不会跟新视图的
2、直接更改【数组下标】来修改数组的值。

我们可以通过 Vue.set(this.userInfo,'sex','男')
或者 this.$forceUpdate() 来解决这个问题

set 原理如下
因为是响应式数据,
我们给对象和数组本身新增了__ob__属性,代表的是 Observer【饿 b zɜ və(r)】 实例。
如对象新增不存在的属性,首先会把新的属性进行响应式跟踪。
然后会触发对象 ob 的dep收集到的 watcher【ˈwɑːtʃər]】 去更新视图.
【使用splice方法向数组内添加元素时】该元素会自动被变成响应式的
源码:https://blog.csdn.net/leelxp/article/details/107212555


#### 8、v-for为什么要加key

1.提高渲染速度,提升效率。
{当两个元素位置发生改变时vue不会对整个列表进行重新渲染,
而只是更换一下dom的顺序,这样可以减少资源消耗。}

2.处理勾选时候的bug。 比如列表中有 【A,B,C】
我们勾选B,向列表中添加D,列表是[D,A,C]此时却勾选了A

3.key值应该是唯一的。最后使用id值。
为什么使用id值,而不是index


#### 9 assets 和static【不会打包】的区别

答:相同点:assets【a sai s 】和static两个都是存放静态资源文件,
图片,字体图标,都可以放在这两个文件下。

不相同点:
build的时候会将assets中放置的静态资源文件进行打包压缩上传.
最终会放置在static文件中跟着index.html一同上传至服务器。

static中放置的静态资源文件就不会打包压缩
而是【直接进入打包好的目录】,直接上传至服务器
static体积也就相对于assets中打包后的文件提交较大点。在服务器中就会占据更大的空间。

建议:将项目中样式文件js文件等都可以放置在assets中,
走打包这一流程。减少体积。

而项目中引入的第三方的资源文件如iconfoont.css等文件可以放置在static中,
因为这些引入的第三方文件已经经过处理,我们不再需要处理,直接上传。

cli2版本会有




#### 11 .vue的两个核心点

答:数据驱动、组件系统
数据驱动:保证数据和视图的一致性。
组件系统:页面中的所有模块可以看作全部是由[组件树]构成的。

#### 12. vue-router 有哪几种导航钩子?

答:三种,
第一种:是全局导航钩子:
router.beforeEach(to,from,next){}
router.afterEach(to,next){}
作用:跳转前进行判断拦截。 2个

第二种:组件内的钩子
beforeRouteEnter (to,next) { }
beforeRouteLeave(to,next){ }

第三种:单独路由独享钩子
beforEnter:(to,form,next) => {

}


#### 13.vue3 导航钩子是否发生了变化

#### 14. $route 和 $router 的区别

答:$router是VueRouter的实例,{可以导航到不同的URL,使用$router.push方法。}
返回上一个历史history用$router.to(-1) 或者 $router.back()

$route为当前router跳转对象。里面可以获取当前路由的name,path,parmas等。


#### 14.vue初始化页面闪动问题

有些时候看到类似于{{message}}的字样,虽然一般情况下这个时间很短暂,但是我们还是有必要让解决这个问题的。
首先在css里加上
[v-cloak] { [k ləʊ k][掩盖]
display: none;
}
如果没有彻底解决问题,则在根元素加上:style="{display: 'block'}"
还可以使用v-text来解决


#### 15. Vue2中注册在router-link上事件click无效解决方法

使用@click.native。原因:router-link会阻止click事件,.native指直接监听一个原生事件。


#### 16. Vue里面router-link在电脑上有用,在安卓上没反应怎么解决?

答:Vue路由在Android机上有问题。
【通过工具查看一下该标签是否被正确解析了,如果没有使用使用一些插件来进行解决】babel问题,


#### 17. vue-loader是什么?使用它的用途有哪些?

答:vue文件的一个加载器,将template/js/style转换成js模块


明天往下看

#### 18. 说说你对 SPA 单页面的理解,它的优缺点分别是什么?

1.用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
2.SPA 相对对服务器压力小;
3.前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;

缺点:
初次加载耗时多:因为要在加载页面的时候将 JavaScript、CSS 统一加载,
SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。


####  19. v-model 的原理?

我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,
我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。


#### 10vue常用的修饰符 【没有理解】

.stop等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);
.capture:与事件冒泡的方向相反,事件捕获由外到内;
.self:只会触发自己范围内的事件,不包含子元素;
.once:只会触发一次


#### 20. Proxy 与 Object.defineProperty 优劣对比

Proxy 的优势如下:
Proxy 可以直接监听对象而非属性;
Proxy 可以直接监听数组的变化;
Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;

Object.defineProperty 的优势如下:
兼容性好,支持 IE9,
而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,
因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。


#### 21 vue的自定义指令

和css样式有关的操作 放在bind函数中
bind: function (el) {},

和js行为有关的操作 可以写在inserted()这个函数中去
inserted: function (el) { el.focus() },

updated(el) {
//当v-model跟新的时候,就会执行这个函数 这个函数会执行多次
},

el->表示被绑定了指令的那个元素,这个el是一个原生的js对象
运用的场景:绑定按钮权限的时候,我就使用了 自定义指令

  
  
#### 1.v-show 与 v-if 有什么区别?ok+

v-if 是真正的条件渲染,也是惰性的;
如果在初始渲染时条件为假,则什么也不做——
直到[条件第一次变为真]时,才会开始渲染

v-show 不管初始条件是什么,元素总是会被渲染.
并且只是简单地基于 CSS 的 “display” 属性进行切换。

频繁切换使用v-show,切换较少使用v-if


#### 2.computed 和 watch 的区别和运用的场景?ok

computed: 是计算属性,computed 的值有缓存。
只有它[依赖的属性值]发生改变,computed 的值时才会重新计算。

watch: 更多的是「观察」的作用,类似于某些[数据的监听回调]。
每当监听的数据变化时,都会执行回调,进行后续操作。

场景:
当我们需要数值进行计算,并且依赖于其它数据时,应该使用 computed。 如
{form表单中的input都必须有有值, 按钮才能够进行点击 我们就可以使用computed }

当我们需要在数据变化时【执行异步】或【开销较大】的操作时,应该使用 watch


#### 3. v-model 的原理?ok

v-model 在内部为不同的输入元素[使用不同的属性]并[抛出不同]的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。


#### 4.  vue-router 路由模式有几种? ok

vue-router 有 3 种路由模式:hash、history、abstract,对应的源码如下所示:
hash: 使用 hash 值来作路由。支持所有浏览器。
history : 有些浏览器不支持
abstract : [ æ bˈstræ k t] 支持所有 JavaScript 运行环境,如 Node.js 服务器端。
如果发现没有浏览器的 API,路由【会自动强制进入】这个模式.


#### 5. 如果被问到 Vue 怎么实现数据双向绑定 等会优化一下 明天你可以优化一下

大家肯定都会回答 通过 Object.defineProperty() 对数据进行劫持,
但是 Object.defineProperty() 只能对属性进行数据劫持。
不能对整个对象进行劫持,同理无法对数组进行劫持.
但是我们在使用 Vue 框架中都知道,Vue 能检测到对象和数组(部分方法的操作)的变化.
那它是怎么实现的呢?我们查看相关代码如下:
observeArray (items: Array) {
for (let i = 0,l = items.length; i < l; i++) {
observe(items[i]) // observe 功能为监测数据的变化
}
}

/**

  • 对属性进行递归遍历
    */
    let childOb = !shallow && observe(val) // observe 功能为监测数据的变化

复制代码通过以上 Vue 源码部分查看,
我们就能知道 Vue 框架是通过遍历数组 和递归遍历对象,从而达到利用 Object.defineProperty() 也能对对象和数组(部分方法的操作)进行监听。


#### 6.  虚拟 DOM 实现原理?

虚拟 DOM 的实现原理主要包括以下 3 部分:
1.用一个[原生的JS对象]去[描述]一个[DOM节点],是对真实DOM的一层抽象。
2.diff 算法 — 比较两棵虚拟 DOM 树的差异;【dif算法比较两颗树直接的差异】
3.pach 【帕克】算法 — 将两【个虚拟DOM对象的差异】应用到【真正的 DOM 树】。


#### 7、Vue 中的 key 有什么作用? ok

key 是 Vue中vnode的唯一标记,通过这个key,我们的diff操作可以更准确、更快速。

2.更准确表现在sameNode函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。
(我的理解:通过 sameNode函数对比key值,避免了就地复用的情况,所以会更加的准确)

3.更快速:利用key的唯一性生成map对象,来获取对应节点,比遍历方式更快。


本文的地址 :https://juejin.cn/post/6844903918753808398#heading-22



地址来源:https://zhuanlan.zhihu.com/p/92407628
本文的源地址:https://www.cnblogs.com/wenshaochang123/p/14888494.html

==============================================
#### 1. 当数据发生变化时,vue是怎么更新节点的?

渲染真实DOM的开销是很大的,
比如有我们修改了某个数据,
如果直接渲染到真实dom上会引起整个dom树的重绘和重排。
diff算法能够帮助我们,更新修改那一小块dom而不要更新整个dom

我们先根据真实DOM生成一颗 virtual DOM,
当 virtual DOM 某个节点的数据改变后会生成一个新的 Vnode ,
然后 Vnode 和 oldVnode 作对比,
发现有不一样的地方就直接修改在真实的DOM上,然后使 oldVnode 的值为 Vnode 。
diff的过程就是调用名为 patch 的函数,比较新旧节点,一边比较一边给 真实的DOM 打补丁


#### 2. virtual DOM和真实DOM的区别?

virtual DOM是将真实的DOM的数据抽取出来,以对象的形式模拟树形结构。比如dom是这样的:
或者说

123

对应的virtual DOM(伪代码): var Vnode = { tag: 'div',text: '123' } ] }; (温馨提示: VNode 和 oldVNode 都是对象,一定要记住) ``` #### diff的比较方式? ``` 在采取diff算法比较新旧节点的时候,比较只会在同层级进行,不会跨层级比较。

123

456
上面的代码会分别比较同一层的两个div以及第二层的p和span,但是不会拿div和span作比较。 ```

diff流程图

当数据发生改变时,set方法会让调用 Dep.notify 通知所有订阅者Watcher,
订阅者就会调用 patch 给真实的DOM打补丁,patch (oldVnode,vnode ){ 比较这两个节点,然后做出对应的处理 }
更新相应的视图。

patch 函数的分析

function patch (oldVnode,vnode) {
 if (sameVnode(oldVnode,vnode)) {
  patchVnode(oldVnode,vnode)
 } else {
  const oEl = oldVnode.el // 当前oldVnode对应的真实元素节点
  let parentEle = api.parentNode(oEl) // 父元素
  createEle(vnode) // 根据Vnode生成新元素
  if (parentEle !== null) {
   api.insertBefore(parentEle,vnode.el,api.nextSibling(oEl)) // 将新元素添加进父元素
   api.removeChild(parentEle,oldVnode.el) // 移除以前的旧元素节点
   oldVnode = null
  }
 }
 // some code 
 return vnode
}


patch函数接收两个参数 oldVnode 和 Vnode 分别代表新的节点和之前的旧节点.
如果两个节点都是一样的,那么就深入检查他们的子节点。
如果两个节点不一样那就说明 Vnode 完全被改变了,就可以直接替换 oldVnode 。

虽然这两个节点不一样但是他们的子节点一样怎么办?
别忘了,diff可是逐层比较的,
如果[第一层不一样那么就不会继续深入比较第二层了。
(我在想这算是一个缺点吗?相同子节点不能重复利用了...)

PathVnode 函数做的事情

这个函数做了以下事情:
找到对应的真实dom,称为 el
判断 Vnode 和 oldVnode 是否指向同一个对象,
如果是,那么直接 return 如果他们都有文本节点并且不相等,那么将 el 的文本节点设置为 Vnode 的文本节点。
如果 oldVnode 有子节点而 Vnode 没有,则删除 el 的子节点
如果 oldVnode 没有子节点而 Vnode 有,则将 Vnode 的子节点真实化之后添加到 el 如果两者都有子节点,则执行 updateChildren 函数比较子节点,这一步很重要
其他几个点都很好理解,我们详细来讲一下updateChildren

diff

diff 算法时发生在虚拟Dom之间的。
是新的虚拟dom和老的虚拟dom之间的比较。【注意一下】
然后算出最小量之间的跟新,最后渲染到真正的Dom上

比较:

1=>为什么data是一个函数 【理解】 ok

每复用一次组件,就会返回一分新的data。
也就说:【每个组件实例创建】一个【私有】的数据空间。各个组件维护各自的数据。
如果单纯的写成对象形式,那么所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
data(){
    return{
        
    }
}

2=> Vue组件通讯有哪些方式? ok

1、props(父给子) 和 $emit (子传递父) 很熟悉  ok
4、父组件中通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。(官方不推荐在实际业务中适用,但是写组件库时很常用。)
7、vuex 状态管理。 ok

明天去处理一下
6、envetBus 兄弟组件数据传递,这种情况下可以使用事件总线的方式。 ok
2、$parent 和 $children 获取当前父组件和当前组件的子组件。
3、$attrs 和 $listeners A -> B -> C。Vue2.4开始提供了$attrs和$listeners来解决这个问题。
5、$refs 获取组件实例。 

回答的越多,可以让自己加分
面试官会觉得你的技术还不错

3=> vue的生命周期 8+2 ok

我们都知道vue常用的8个生命周期,但是这几个生命周期你熟悉吗
activated keep-alive 专属,组件被激活时调用 [ai k t v ti de]
第一次进入也会触发activated  

deactivated keep-alive 专属,组件被销毁时调用 【di ai k t v ti de】

4=> 怎样理解 Vue 的单项数据流 ok

数据总是从父组件传到子组件,
子组件没有权利修改父组件传过来的数据,[如果你强行更改,vue会有红色的警告,告诉你这个是单向的]
只能请求父组件对原始数据进行修改。

这样会防止从子组件意外改变父组件的状态,
从而导致你的应用的数据流向难以理解。

5=> v-if 和 v-for 为什么不建议一起使用 ok

v-for和v-if不要在同一标签中使用,
因为解析时先解析v-for然后在解析v-if,[会消耗性能的哈]
如果遇到需要同时使用时可以嵌套一层元素  
<template></template>

5.1=> vue3 v-for和v-if做了更改

很幸运 vue 3.x 中, v-if 总是优先于 v-for。

6==>Vue如何检测【数组变化】 ok

数组考虑性能原因没有用 defineProperty 对数组的每一项进行拦截,
而是选择对7种数组(push,reverse)方法进行重写(AOP切片思想)。
所以在 Vue 中修改数组的索引和长度无法监控到。
需要通过以上7种变异方法修改数组才会触发数组对应的watcher进行更新。【这一句自己理解就可以了】

07==> Vue的父子组件生命周期钩子函数执行顺序 ok

加载渲染过程
父beforeCreate -> 父created -> 父beforeMount ->
->子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
【你可以理解页面渲染,这样就好理解了】

子组件更新过程
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

父组件更新过程
父beforeUpdate -> 父updated

销毁过程
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

8. 虚拟DOM是什么?有什么优缺点?

由于在浏览器中频繁操作DOM代价是很昂贵的。会产生一定性能问题。这就是虚拟Dom的产生原因。

Vue2的Virtual DOM 借鉴了开源库 snabbdom 的实现。
Virtual DOM本质就是用一个[原生的JS对象]去[描述]一个[DOM节点],是对真实DOM的一层抽象。
上面这一句话就翻译为代码 就是
<div>
 <p>123</p>
</div>
对应的virtual DOM(伪代码):
var Vnode = {
 tag: 'div',text: '123' }
 ]
};

优点:
1、保证性能下限:虽然它的性能并不是最优的;但是比起粗暴的DOM操作性能要好很多,还有不错的性能,

2、无需手动操作DOM:我们不需手动去操作DOM,只需要写好代码逻辑,
框架会【根据虚拟DOM】和【数据双向绑定】,帮我们自动更新视图,极大提高我们的开发效率。

3、跨平台:虚拟DOM可以进行更方便地跨平台操作,

缺点:
1、无法进行极致优化:虽然虚拟DOM + 合理的优化,足以应对大部分应用的性能需要,但在一些【性能要求极高】的应用中虚拟DOM无法没满足
2、首次渲染大量DOM时,由于多了一层DOM计算,会比innerHTML插入慢。

1=> Vue3.0 和 2.0 的【响应式原理】区别

Vue3.x 改用 Proxy[pu luo k she] 替代 Object.defineProperty[di fai n prɒ pə ti]。
因为 Proxy 可以直接监听对象和数组的变化,
因为 defineProperty是不可以直接对数组进行监听
Vue2 中修改数组的索引和长度无法被监控到。

2=> Vuex 页面刷新数据丢失怎么解决?

在刷新页面的时候,将vuex中的只存在本地
也可以使用第三方插件。  vuex-persist (pəˈsɪ s t])插件,
它是为 Vuex 持久化储存而生的一个插件。

3 你都做过哪些 Vue 的性能优化?

语法方面:
v-if 和 v-show 区分使用场景
computed 和 watch 区分场景使用
v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if

//数据方面
对象层级不要过深,否则性能就会差。
不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)

// 加载-缓存
图片懒加载
路由懒加载
第三方插件的按需加载
适当采用 keep-alive 缓存组件
防抖、节流的运用

4 Vue.mixin 的使用场景和原理 【没有理解】

你自己组织一下mixin的使用,这个太复杂了

在日常开发中,我们经常会遇到在不同组件中经常用到一些相同或者相似的代码,
这些代码的功能相对独立,可以通过vue 的 mixin 功能抽离公共的业务逻辑,原理类似“对象的继承”,
当组件初始化时会调用 mergeOptions 方法进行合并,
采用策略模式针对不同的属性进行合并。当组件和混入对象含有相同名选项时,
这些选项将以恰当的方式进行“合并”。

5. nextTick 使用场景和原理

场景:进行tab切换的时候,当显示A组件的时候。
A组件的input自动聚焦。这个时候获取A组件的input实例就会出现undefiend

为什么会出现undefined?
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。

原理:
nextTick 将回调延迟到下次 DOM 更新循环之后执行

6、 keep-alive 使用场景和原理

keep-alive 是 Vue 内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载。
常用的两个属性 include/exclude,符合条件的组件或者页面进行缓存。 [include 是页面中的name ]
include的类型可以是字符串,数组,正则。

两个生命周期 activated/deactivated,用来得知当前组件是否处理活跃状态。
keep-alive 运用了 LRU 算法,选择最近【久未使用的组件】予以淘汰。
keep-alive其实还有一个属性max,最大允许缓存多少个,如果超出最大个数。
会将已缓存组件中最久没有被访问的实例会被销毁掉。

7、Vue.set 方法原理

在两种情况下修改 Vue 是不会触发视图更新的。 
1、给响应式对象新增属性,这个时候是不会跟新视图的
2、直接更改【数组下标】来修改数组的值。

我们可以通过 Vue.set(this.userInfo,'男') 
或者 this.$forceUpdate() 来解决这个问题

set 原理如下
因为是响应式数据,我们给对象和数组本身新增了__ob__属性,代表的是 Observer【饿 b zɜ və(r)】 实例。
如对象新增不存在的属性,首先会把新的属性进行响应式跟踪。
然后会触发对象 __ob__ 的dep收集到的 watcher【ˈwɑːtʃər]】 去更新视图.
【使用splice方法向数组内添加元素时】该元素会自动被变成响应式的
源码:https://blog.csdn.net/leelxp/article/details/107212555

8、v-for为什么要加key

1.提高渲染速度,提升效率。
{当两个元素位置发生改变时vue不会对整个列表进行重新渲染,
而只是更换一下dom的顺序,这样可以减少资源消耗。}

2.处理勾选时候的bug。 比如列表中有 【A,C】
我们勾选B,向列表中添加D,C]此时却勾选了A

3.key值应该是唯一的。最后使用id值。
为什么使用id值,而不是index

9 assets 和static【不会打包】的区别

答:相同点:assets【a sai s 】和static两个都是存放静态资源文件,
图片,字体图标,都可以放在这两个文件下。

不相同点:
build的时候会将assets中放置的静态资源文件进行打包压缩上传.
最终会放置在static文件中跟着index.html一同上传至服务器。

static中放置的静态资源文件就不会打包压缩
而是【直接进入打包好的目录】,直接上传至服务器
static体积也就相对于assets中打包后的文件提交较大点。在服务器中就会占据更大的空间。

建议:将项目中样式文件js文件等都可以放置在assets中,
走打包这一流程。减少体积。

而项目中引入的第三方的资源文件如iconfoont.css等文件可以放置在static中,
因为这些引入的第三方文件已经经过处理,我们不再需要处理,直接上传。

cli2版本会有

11 .vue的两个核心点

答:数据驱动、组件系统
数据驱动:保证数据和视图的一致性。
组件系统:页面中的所有模块可以看作全部是由[组件树]构成的。

12. vue-router 有哪几种导航钩子?

答:三种,
第一种:是全局导航钩子:
router.beforeEach(to,next){}
router.afterEach(to,next){} 
作用:跳转前进行判断拦截。 2个

第二种:组件内的钩子   
beforeRouteEnter (to,next) { }
beforeRouteLeave(to,next){ }

第三种:单独路由独享钩子
beforEnter:(to,next) => { 
	
}

13.vue3 导航钩子是否发生了变化


14. $route 和 $router 的区别

答:$router是VueRouter的实例,{可以导航到不同的URL,使用$router.push方法。}
返回上一个历史history用$router.to(-1) 或者 $router.back()

$route为当前router跳转对象。里面可以获取当前路由的name,parmas等。

14.vue初始化页面闪动问题

有些时候看到类似于{{message}}的字样,虽然一般情况下这个时间很短暂,但是我们还是有必要让解决这个问题的。
首先在css里加上
[v-cloak] { [k ləʊ k][掩盖]
	display: none; 
}
如果没有彻底解决问题,则在根元素加上:style="{display: 'block'}"
还可以使用v-text来解决

15. Vue2中注册在router-link上事件click无效解决方法

使用@click.native。原因:router-link会阻止click事件,.native指直接监听一个原生事件。

16. Vue里面router-link在电脑上有用,在安卓上没反应怎么解决?

答:Vue路由在Android机上有问题。
【通过工具查看一下该标签是否被正确解析了,如果没有使用使用一些插件来进行解决】babel问题,

17. vue-loader是什么?使用它的用途有哪些?

答:vue文件的一个加载器,将template/js/style转换成js模块

明天往下看

18. 说说你对 SPA 单页面的理解,它的优缺点分别是什么?

1.用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
2.SPA 相对对服务器压力小;
3.前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;

缺点:
初次加载耗时多:因为要在加载页面的时候将 JavaScript、CSS 统一加载,
SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。

19. v-model 的原理?

我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,
我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。

10vue常用的修饰符 【没有理解】

.stop等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);
.capture:与事件冒泡的方向相反,事件捕获由外到内;
.self:只会触发自己范围内的事件,不包含子元素;
.once:只会触发一次

20. Proxy 与 Object.defineProperty 优劣对比

Proxy 的优势如下:
Proxy 可以直接监听对象而非属性;
Proxy 可以直接监听数组的变化;
Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
Proxy 返回的是一个新对象,而 Object.defineProperty 只能遍历对象属性直接修改;
Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;

Object.defineProperty 的优势如下:
兼容性好,支持 IE9,
而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,
因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。

21 vue的自定义指令

和css样式有关的操作 放在bind函数中
bind: function (el) {},和js行为有关的操作  可以写在inserted()这个函数中去
inserted: function (el) {  el.focus() },updated(el) {
	//当v-model跟新的时候,就会执行这个函数  这个函数会执行多次  
},el->表示被绑定了指令的那个元素,这个el是一个原生的js对象
运用的场景:绑定按钮权限的时候,我就使用了 自定义指令

1.v-show 与 v-if 有什么区别?ok+

v-if 是真正的条件渲染,也是惰性的;
如果在初始渲染时条件为假,则什么也不做——
直到[条件第一次变为真]时,才会开始渲染

v-show 不管初始条件是什么,元素总是会被渲染.
并且只是简单地基于 CSS 的 “display” 属性进行切换。

频繁切换使用v-show,切换较少使用v-if

2.computed 和 watch 的区别和运用的场景?ok

computed: 是计算属性
只有它[依赖的属性值]发生改变,computed 的值时才会重新计算。

watch: 更多的是「观察」的作用,类似于某些[数据的监听回调]。
每当监听的数据变化时,都会执行回调,进行后续操作。
===================================================
场景:
当我们需要数值进行计算,并且依赖于其它数据时,应该使用 computed。 如
{form表单中的input都必须有有值, 按钮才能够进行点击 我们就可以使用computed  }

当我们需要在数据变化时【执行异步】或【开销较大】的操作时,应该使用 watch

3. v-model 的原理?ok

v-model 在内部为不同的输入元素[使用不同的属性]并[抛出不同]的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。

4. vue-router 路由模式有几种? ok

vue-router 有 3 种路由模式:hash、history、abstract,对应的源码如下所示:
hash: 使用 hash 值来作路由。支持所有浏览器。
history : 有些浏览器不支持
abstract : [ æ bˈstræ k t] 支持所有 JavaScript 运行环境,如 Node.js 服务器端。
如果发现没有浏览器的 API,路由【会自动强制进入】这个模式.

5. 如果被问到 Vue 怎么实现数据双向绑定 等会优化一下 明天你可以优化一下

大家肯定都会回答 通过 Object.defineProperty() 对数据进行劫持,
但是  Object.defineProperty() 只能对属性进行数据劫持。
不能对整个对象进行劫持,同理无法对数组进行劫持.
但是我们在使用 Vue 框架中都知道,Vue 能检测到对象和数组(部分方法的操作)的变化.
那它是怎么实现的呢?我们查看相关代码如下:
observeArray (items: Array<any>) {
    for (let i = 0,l = items.length; i < l; i++) {
        observe(items[i])  // observe 功能为监测数据的变化
    }
}

/**
* 对属性进行递归遍历
*/
let childOb = !shallow && observe(val) // observe 功能为监测数据的变化

复制代码通过以上 Vue 源码部分查看,
我们就能知道 Vue 框架是通过遍历数组 和递归遍历对象,从而达到利用  Object.defineProperty() 也能对对象和数组(部分方法的操作)进行监听。

================================

6. 虚拟 DOM 实现原理? ok

虚拟 DOM 的实现原理主要包括以下 3 部分:
1.用一个[原生的JS对象]去[描述]一个[DOM节点],是对真实DOM的一层抽象。
2.diff 算法 — 比较两棵虚拟 DOM 树之间的差异;
3.patch 【pai qi】算法 — 将两【个虚拟DOM对象的差异】应用到【真正的 DOM 树】。

7、Vue 中的 key 有什么作用? ok

key 是 Vue中vnode的唯一标记,通过这个key,我们的[diff操作]可以[更准确]、[更快速]。

2.(我的理解:通过 sameNode函数对比key值,避免了就地复用的情况,所以会更加的准确)

3.更快速:利用key的唯一性生成map对象,来获取对应节点,比遍历方式更快。

本文的地址 :https://juejin.cn/post/6844903918753808398#heading-22
地址来源:https://zhuanlan.zhihu.com/p/92407628
本文的源地址:https://www.cnblogs.com/wenshaochang123/p/14888494.html

================================================================

1. 当数据发生变化时,vue是怎么更新节点的? ok 【跟新数据和跟新节点有点不一样哈~】

渲染真实DOM的开销是很大的,
比如有我们修改了某个数据,
如果直接渲染到真实dom上会引起整个dom树的重绘和重排。
diff算法能够帮助我们,更新修改那一小块dom而不要更新整个dom

用一个[原生的JS对象]去[描述]一个虚拟dom,然后 新的Vnode 和 oldVnode 作对比,
发现有不一样的地方,就使用新的值去替代旧值。
其中使用了diff算法。
在采取diff算法比较:新旧节点进行比较,比较只会在同层级进行,不会跨层级比较。
如果两个节点都是一样的,那么就深入检查他们的子节点。
果两个节点不一样那就说明 Vnode 完全被改变了,就可以直接替换 oldVnode 。

2. virtual DOM和真实DOM的区别? ok 这个回答的不好,可以在更改一下

Virtual DOM本质就是用一个[原生的JS对象]去[描述]一个[DOM节点],是对真实DOM的一层抽象。
或者说 
<div>
 <p>123</p>
</div>
对应的virtual DOM(伪代码):
var Vnode = {
 tag: 'div',text: '123' }
 ]
};
(温馨提示: VNode 和 oldVNode 都是对象,一定要记住)

3. diff的比较方式?ok

diff算法的比较方式:新旧节点进行比较,比较只会在同层级进行,不会跨层级比较。
如果两个节点都是一样的,那么就深入检查他们的子节点。
果两个节点不一样那就说明 Vnode 完全被改变了,就可以直接替换 oldVnode 。
<div>
 <p>123</p>
</div>
 
<div>
 <span>456</span>
</div>
上面的代码会分别比较同一层的两个div以及第二层的p和span,但是不会拿div和span作比较。

04 patch 函数的分析 ok

function patch (oldVnode,oldVnode.el) // 移除以前的旧元素节点
   oldVnode = null
  }
 }
 // some code 
 return vnode
}

diff算法在比较的时候调用了一个patch函数: 
patch 函数接收两个参数 oldVnode 和 Vnode 分别代表旧节点个新节点
如果两个节点都是一样的,那么就深入检查他们的子节点。【以此类推】
如果两个节点不一样那就说明 Vnode 完全被改变了,就可以直接替换 oldVnode 。

虽然这两个节点不一样但是他们的子节点一样怎么办?
别忘了,diff可是逐层比较的,
如果[第一层不一样那么就不会继续深入比较第二层了。
(我在想这算是一个缺点吗?相同子节点不能重复利用了...)
【别忘记了,在实际大开发中几乎不会遇见这样的情况】

2=> Vue组件通讯有哪些方式? ok

1、props(父给子) 和 $emit (子传递父) 很熟悉  ok
4、父组件中通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。(官方不推荐在实际业务中适用,但是写组件库时很常用。)
7、vuex 状态管理。 ok

明天去处理一下
6、envetBus 兄弟组件数据传递,这种情况下可以使用事件总线的方式。 ok
2、$parent 和 $children 获取当前父组件和当前组件的子组件。
3、$attrs 和 $listeners A -> B -> C。Vue2.4开始提供了$attrs和$listeners来解决这个问题。
5、$refs 获取组件实例。 

回答的越多,可以让自己加分
面试官会觉得你的技术还不错

比较: diff算法的文章

原文地址:https://www.cnblogs.com/IwishIcould

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1==&gt;简述一下src与href的区别 src用于替换当前元素; href用于在当前文档和引用资源之间确立联系 2==&gt;、谈谈以前端角度出发做好SEO需要考虑什么? a.&#160;了解搜
什么是window对象?什么是document对象? window对象代表浏览器中打开的一个窗口。 document对象代表整个html文档。实际上, document对象是window对象的一个属性
1 》vue-router有哪几种导航钩子? 第一种:是全局导航钩子:router.beforeEach(to,from,next) 第二种:&#160;组件内的钩子 beforeRouteEnter
1=&gt;为什么data是一个函数 【理解】 组件的data写成一个函数, 这样每复用一次组件,就会返回一分新的data。 也就说:给每个组件实例创建一个私有的数据空间。 各个组件维护各自的数据。
01 vue3的新特征 1.组合式API. setUp作为组合函数的入口函数 2.Teleport 传送门 3.片段 template下可以有多个标签 4.用于创建自定义渲染器。我的理解是 creat
// var&#160;arr=[1,2,23,23,4,5,5]; // var&#160;newarr=new&#160;Set(arr);&#160;//去重 // console.log([.
摆好姿势 摆好姿势 如何使下面的等式成立 if(a==1&amp;&amp;a==3&amp;a==5){ console.log(666) } var a=[1,3,5] a.join=a.shif
1=&gt;为什么data是一个函数 【理解】 ok 每复用一次组件,就会返回一分新的data。 也就说:【每个组件实例创建】一个【私有】的数据空间。各个组件维护各自的数据。 如果单纯的写成对象形式,
以下是收集一些面试中经常会遇到的经典面试题以及自己面试过程中无法解决的问题,通过对知识的整理以及经验的总结,重新巩固自身的前端基础知识,如有错误或更好的答案,欢迎指正。:) 在网页中,一个元素占有空间
1 Action是不是线程安全的?如果不是 有什么方式可以保证Action的线程安全?如果是,说明原因不是声明局部变量,或者扩展RequestProcessor,让每次都创建一个Action,或者在s
解决js兼容性问题使用 event对象 function eventHandler(event) { event = event || window.event} 获取滚动条属性 var scrollTop = document.documentElment.scrollTop || document.body.scrollTop
浏览器的内核 IE: trident内核,Firefox:gecko内核,Safari:webkit内核,Opera:以前是presto内核,Opera现已改用Google Chrome的Blink内核,Chrome:Blink(基于webkit,Google与Opera Software共同开发) HTML中的Doctype有什么作用 此标签可告知浏览器文档使用哪种HTML或XHTML规范。(重点:告诉浏览器按照何种规范解析页面) div+css的布局较table布局有什么...
如何创建函数第一种(函数声明): function sum1(num1,num2){ return num1+num2; } 第二种(函数表达式): var sum2 = function(num1,num2){ return num1+num2; } 第三种(函数对象方式): var sum3 = new Function("num1","num2","return num1+num2");三种弹窗的单词以及三种弹窗的功能1.alert //弹出对话框并输出一段提示信...
js的垃圾回收机制是什么原理垃圾回收机制有两种方法第一种是标记清除法:当变量进入执行环境时,就标记这个变量为”进入环境”,当变量离开环境的时候,则将其标记为”离开环境”,垃圾收集器在运行的时候会给储存在内存中的所有变量都加上标记,然后它会去掉环境中的标量以及被环境中的变量引用的标记,而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了,最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间 第二种是引用计数法:当声明了一个变量并将
Ajax 是什么? 如何创建一个Ajax?AJAX全称是Asychronous JavaScript And Xml(异步的 JavaScript 和 XML)它的作用是用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新,早期的浏览器并不能原生支持ajax,可以使用隐藏帧(iframe)方式变相实现异步效果,后来的浏览器提供了对ajax的原生支持其主要通过XMLHttpRequest(标准浏览器)、ActiveXObject(IE浏览器)对象实现异步通信效果实现方式(gitee上的案例):
谈一谈let与var和const的区别let为ES6新添加申明变量的命令,它类似于var,但是有以下不同: let命令不存在变量提升,如果在let前使用,会导致报错let暂时性死区的本质,其实还是块级作用域必须“先声明后使用”的性质,let 暂时性死区的原因:var 会变量提升,let 不会。let,const和class声明的全局变量不是全局对象的属性const可以在多个模块间共享const声明的变量与let声明的变量类似,它们的不同之处在于,const声明的变量只可以在声明时赋值,不可
解释一下为何[ ] == ![ ] // ---&gt; true首先看一张图![ ] 是 false原式:[ ] == false根据第八条,false通过tonumber()转换为0原式:[ ] == 0根据第十条,[ ]通过ToPrimitive()转换为' '原式:' ' == 0根据第六条原式:0 == 0尝试实现new function ObjectClass() {//对象 console.log(arguments[...
谈谈对Node的理解Node.js 在浏览器外运行V8 JavaScript引擎,单线程 非阻塞I/O 事件驱动,适应于数据高并发,适合多请求,但不适合高运算,有权限读取操作系统级别的API,npm 仓库,常用框架:Express,koa,Socket.io,AdonisJs,NestJS什么是gulp?作用?机制是什么?gulp是基于node的自动化构建工具作用:1 自动压缩JS文件2 自动压缩CSS文件3 自动合并文件4 自动编译sass5 自动压缩图片6 自动刷
vue和react的区别React严格上只针对MVC的view层,Vue则是MVVM模式virtual(虚拟) DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制组件写法不一样,React推荐的做法是 JSX + inline style,也就是把HTML和CSS全都写进JavaScript了,即'all in
谈谈对react的理解react是基于v(视图层)层的一款框架,虚拟dom和diff算法react特点:声明式设计高效,其中高效以现在虚拟dom,最大限度减少与dom的交互和diff算法灵活,体现在可以与已知的框架或库很好的配合JSX,是js语法的扩展组件化,构建组件,是代码的更容易得到复用,比较建议在大型项目的开发单项数据,实现单项数流,从而减少代码复用react有哪几个生命周期自己的总结分为三个阶段,初始,运行中,销毁初始化: 执行getDefaultProps钩子