vue出镜率比较高的十大面试题

1、vue的底层原理

vue是M-V-VM模式,通过modelView作为中间层,进行双向数据的绑定和变化
①通过document.createDocumentFrament()方法建立虚拟Dom树
②一旦被检测到数据发生变化,会通过Object.defineProperty定义的数据拦截
③拦截到数据变化从而通过订阅-发布模式触发观察者,从而改变虚拟dom中具体数据
④最后通过更新虚拟Dom的元素值,从而改变最后dom树的值,完成双向绑定

 

2、Vue Router 路由模式 hash 和 history 的实现原理,以及他们的特性

hash模式实现原理:location.hash的值就是url中#后面的内容。
以下几个特性:
① url中hash值只是客户端一种状态,向服务端发送请求时hash部分不会被发送
② hash值的改变,都会在浏览器增加一个历史记录,因此能通过浏览器回退、前进按钮控制hash的切换
③ 可以用hashchange事件去监听hash变化,从而对页面进行跳转(渲染)
④ 可以通过a标签设置href属性,当用户点击后hash值会发生变化,或者通过js对location.hash赋值改变url的hash值

history模式实现原理:
H5 提供了HistoryAPI 来实现URL的变化,history.pushState() 和 history.repalceState()两个API可以在不进行刷新情况下操作浏览器历史记录
不同的是,前者是新增一个历史记录,后者是直接替换当前记录。

以下几个特性:
① pushState和repalceState两个API来操作实现url的变化
② 可以用popstate事件来监听url变化,从而对页面进行跳转
③ pushState或repalceState不会触发popstate事件,这时需要手动触发页面跳转
④ history路由模式需要后台配置支持,需要在服务端增加一个覆盖所有情况的候选资源,如果url匹配不到静态资源,应该返回同一个app依赖的index.html页面

 

3、什么是虚拟DOM,为什么他能提高性能? 说下diff算法

虚拟dom也就是虚拟节点,是通过js的Object对象模拟dom中的节点,然后通过特定的render方法将其渲染成真正的DOM节点
当改变元素的节点或者属性时候,并不是真正改变dom元素,而是做一次diff算法做一次对比,他会以最小的代价更新dom
虚拟Dom相当于在js和真实Dom之间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能
虚拟Dom工作的三个简单步骤:
1)没当数据发生变化时候,整个页面将在虚拟dom中重新渲染
2)然后计算之前的dom与新的dom中间差异
3)完成计算后,将只用实际更改的内容更新真实dom

diff算法:
根据真实dom生成一个虚拟dom,当虚拟dom某个节点数据变化改变后会生成一个新的vnode,然后新的和旧的对比,一边对比一边打补丁
发现有不一样的就直接修改在真实的dom上。
当数据发生改变时,set方法会调用Dep.notify通知所有订阅者,订阅者就会调用patch给真实的DOM打补丁,更新相应的视图

 

4、vue如何实现组件和逻辑复用

组件复用可以使用slot作用域插槽,让子组件暴露出属性 直接在父组件使用
逻辑复用可以使用Mixin 混入模式,将一些逻辑封装,然后混入到需要该功能的组件中

说说你对mixin的理解,以及应用场景 ?
mixin,一个混入对象可以包含任意组件选项。多个实例引用了相同的方法或者属性,可将这些重复的内容抽取出来作为mixin的js
export导出去,在需要引用vue文件通过mixin属性注入。他允许封装一块在应用的其他组件都可以使用的函数
比如有两个非常相似的组件,基本功能一致,但个别地方又有差异,这时候可以使用mixin

 

5、页面刷新后vuex的state数据为什么会丢失,如何解决

原因:因为store里的数据是把保存在运行内存中,当页面刷新时,会重新加载vue实例,store里面的数值就会重新赋值初始化
解决方法:在页面向后台请求数据,并且在页面刷新前,将vuex中数据存储到localStorage或sessionStorage中

export default {
name: 'App',
created() {
//在页面加载时读取sessionStorage里的状态信息
if(sessionStorage.getItem('store')){
this.$store.replaceState(Object.assign(
{},
this.$store.state,
JSON.parse(sessionStorage.getItem('store'))
))
}
//在页面刷新时将vuex里的信息保存在sessionStorage中
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('store', JSON.stringify(this.$store.state));
})
}
}

 

6、如何理解Vue中的Render渲染函数,他和JSX有什么不同

Vue一般使用template来创建HTML,然后有时候,我们需要使用js来创建html,这时候我们需要使用render函数
render函数return一个createElement组件中的子元素存储在组件实列中,createElement返回的是包含的信息会告诉VUE页面上需要渲染什么样的节点。
一般用render函数封装东西会比较灵活,尤其是配置和模板分离。

JSX是JavScript和XML结合一种的格式,Js在解析JSX时会先创建虚拟DOM,JSX最后会被编译为JavaScript代码执行
JSX相当于createElement的语法糖,这种形式可以直接使用template模板格式在render函数里写

 

7、Proxy代理与Object.defineProperty的优劣对比

vue是基于数据劫持的双向绑定,数据劫持有两种,分别是Object.defineProperty和Proxy代理
Vue3.0以Proxy来替代Object.defineProperty数据劫持
Proxy优势:
1)可以直接监听对象,而非属性
2)可以直接监听数组的变化
3)有很多拦截方法
4)返回一个新对象,可以只操作新对象即可

 

8、说一下formData上传表单的实现原理

先创建一个formData对象,通过append向form对象添加数据(键值队)
let formData = new FormData();
formData.append(name,value)

通过axios上传文件,配置添加请求头,添加上传进度监听事件
let config = {
header: {"Content-Type,multipart/form-data"},
onUploadProgress: e =>{
let percent = (progressEvent.loaded / progressEvent.total * 100) | 0
//调用onProgress方法来显示进度条,需要传递个对象 percent为进度值
params.onProgress({ percent: percent })
}
}
上传成功 调用onSuccess方法,上传失败 调用onError方法
axios.post().then((response) => {
console.log(response)
params.onSuccess(response.info)
}).catch((error) =>{
params.onError(error)
})

 

9、vue项目中做过哪些优化处理 ?

①v-if 、v-show区分使用场景
v-if是真正的条件渲染,条件成立才会渲染,否则不会渲染,v-show只是操作display属性来控制元素,不管条件是否成立都会渲染。如果需要频繁切换使用v-show较为合适
②v-for遍历时给item添加key,并且避免同时使用v-if
在数据进行遍历渲染时,需要为每一项item设置唯一的key值,方便vue内部机制准确查找该数据。当state更新时,新的状态值和旧的对比,可以更快的定位到diff
③事件的销毁
如果是非组件本身的事件,比如addEventListener方式是不会自动销毁的,需要手动移除,以免造成内存泄漏
created(){
addEventListener('click','this.click',false)
},
beforeDestroy(){
removeEventListener('click', this.click, false)
}
④路由懒加载
vue单页面应用,一次加载过多资源造成用时过长甚至会出现白屏情况
运用懒加载可以当路由被访问时候才加载,
import方式和require.ensure()方式
{
path: '/about',
name: 'about',
meta: {
breadcrumb: "关于我们"
},
component: () => import('@/view/about')
}
⑤图片懒加载
对于图片过多的页面,为了提高加载速度,可以使用懒加载。将页面内未出现在可视区域的图片先不加载,等滚动到可视区域时再做加载
可以使用vue-lazyload插件
⑥第三方插件的按需引入
项目中引入第三方插件时,如果直接引入整个插件会造成项目提交过大
可以借助babel-plugin-component插件只引入需要的组件,从而减小项目的体积
⑦webpack对图片进行压缩
使用image-webpack-loader插件
⑧开启 gzip 压缩

 

10、vue3.0新增了哪些东西,和2.0有什么区别 ?

vue3.0采用了ts来编写
vue3.0将组件的逻辑都写在了函数内部,setup()会取代之前的data()函数,返回一个对象,暴露给模板,而且只在初始化的时候调用一次
相对2.0,压缩包体积更小
1)双向绑定,3.0使用es6的proxy,相对于object.defineProperty有很多优势
2)虚拟dom的对比更新,只更新vdom绑定的动态数据的部分
3)2.0无论是否使用一些功能和方法都需要下下来,3.0将全局的API和内部的一些组件通过ES的模块进行导出webpack在打包时候就会更加的快捷

posted @ 2022-03-10 16:55  紫诺花开  阅读(998)  评论(0编辑  收藏  举报