Vue面试题
(掌握)简单说下setTimeout(fn, 0)中的0代表的是什么?如果我想在vue实现此功能可以用什么方法代替
js运行是基于单线程的,意味着一段代码执行时,其他代码将进入队列等待,一旦线程有空闲就执行后续代码。如果代码中设定了一个setTimeout
,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为 0,就代表立即插入队列,但并不是立即执行,仍然要等待前面代码执行完毕。
所以setTimeout
并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲。
可以用Vue中的
image
Vex有5种属性,分别是 state、getter、mutation、action、module:
1、state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
2、getters
类似vue的计算属性,主要用来过滤一些数据。
3、mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
4、actions
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
const store = new Vuex.Store({ //store实例
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
5、modules
项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
#(掌握)七、vue如何自定义一个过滤器
1、局部过滤器
Html:
<div id="app">
<input type="text" v-model="msg" />
{{msg| 过滤器名称 }}
</div>
JS:
var vm=new Vue({
el:"#app",
data:{
msg:''
},
filters: {
过滤器名称: function (value) {
if (!value) return ''
...
return value
}
}
})
2、全局过滤器
Vue.filter('过滤器名称', function (value) {
if (!value) return ''
...
return value
})
#(掌握)八、对keep-alive 的了解?
keep-alive
包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
使用方法:
<keep-alive>
<component>
<!-- 该组件将被缓存! -->
</component>
</keep-alive>
#(掌握)十一、Vue 组件 data 为什么必须是函数
每个实例可以维护一份被返回对象的独立的拷贝。data是一个函数的话,这样每复用一次组件,就会返回一份新的data
,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data
,就会造成一个变了全都会变的结果。
#(掌握)十二、Vue 中怎么自定义指令
1、全局注册
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
2、局部注册
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
#(掌握)十三、nextTick 是做什么的
$nextTick
是在下次 DOM
更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick
,则可以在回调中获取更新后的DOM。
#(掌握)十四、$route
和 $router
的区别
$router
为 VueRouter
实例,想要导航到不同 URL
,则使用 $router.push
方法
$route
为当前 router
跳转对象里面可以获取 name
、 path
、 query
、 params
等
#(掌握)十五、vue-cli生成的项目文件夹assets和public(static) 的区别
vue-cli2生成的项目目录是static
vue-cli3以上生成的项目目录是public
- 相同点:
assets和public(static) 都是存放静态资源的文件。项目所需要的静态文件、图片、样式文件都可以放在这两个文件夹下
- 不同点:
在assets中存放的静态资源,在项目打包时会将这些静态资源与代码、index.html文件一起一同进行打包压缩,上传到服务器
在public(static)中存放的静态资源,不会被打包压缩格式化等流程,而是直接进入打包好的目录,直接上传到服务器
#(掌握)十六、DOM渲染在哪个周期中就已经完成
DOM 渲染在 mounted 中就已经完成了。
#(掌握)十七、VNode是什么?虚拟DOM是什么?
Vue在页面上渲染的节点,及其子节点称为“虚拟节点 (Virtual Node)”,简写为“VNode”。“虚拟 DOM”是由 Vue 组件树建立起来的整个 VNode 树的称呼。
#(掌握)十八、什么是RESTful API?怎么使用?
是一个api的标准,无状态请求。请求的路由地址是固定的,如果是tp5则先路由配置中把资源路由配置好。标准有:.post .put .delete
#(掌握)二十、如何让CSS只在当前组件中起作用?
将当前组件的<style>
修改为 <style scoped>
#(掌握)二十一、 修改第三方库的样式
/deep/
>>>
#(掌握)二十二 、那你能讲一讲MVVM吗?
MVVM是Model-View-ViewModel
缩写,也就是把MVC
中的Controller
演变成ViewModel
。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。
#(掌握)二十三、那你知道Vue3.x响应式数据原理吗?
Vue3.x改用Proxy
替代Object.defineProperty。因为Proxy可以直接监听对象和数组的变化,并且有多达13种拦截方法。并且作为新标准将受到浏览器厂商重点持续的性能优化
Proxy只会代理对象的第一层,那么Vue3又是怎样处理这个问题的呢?(拓展)
判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive
方法做代理, 这样就实现了深度观测。
监测数组的时候可能触发多次get/set,那么如何防止触发多次呢?(拓展)
我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger。
#(掌握)二十四、再说一下vue2.x中如何监测数组变化
使用了函数劫持的方式,重写了数组的方法,Vue将data中的数组进行了原型链重写(push,pop,shift,unshift,splice...),指向了自己定义的数组原型方法。这样当调用数组api时,可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监测数组变化。
#(掌握)二十五、Computed和Watch
Computed
本质是一个具备缓存的watcher,依赖的属性发生变化就会更新视图。 适用于计算比较消耗性能的计算场景。当表达式过于复杂时,在模板中放入过多逻辑会让模板难以维护,可以将复杂的逻辑放入计算属性中处理。
Watch
没有缓存性,更多的是观察的作用,可以监听某些数据执行回调。当我们需要深度监听对象中的属性时,可以打开deep:true
选项,这样便会对对象中的每一项进行监听。这样会带来性能问题,优化的话可以使用字符串形式
监听。
#(掌握)二十六.再说一下虚拟Dom以及key属性的作用
由于在浏览器中操作DOM是很昂贵的。频繁的操作DOM,会产生一定的性能问题。这就是虚拟Dom的产生原因
。
Vue2的Virtual DOM借鉴了开源库snabbdom
的实现。
Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象。
(也就是源码中的VNode类,它定义在src/core/vdom/vnode.js中。)
VirtualDOM映射到真实DOM要经历VNode的create、diff、patch等阶段。
「key的作用是尽可能的复用 DOM 元素。」
新旧 children 中的节点只有顺序是不同的时候,最佳的操作应该是通过移动元素的位置来达到更新的目的。
需要在新旧 children 的节点中保存映射关系,以便能够在旧 children 的节点中找到可复用的节点。key也就是children中节点的唯一标识。
#(掌握)二十七.Vue中组件生命周期调用顺序说一下
组件的调用顺序都是先父后子
,渲染完成的顺序是先子后父
。
组件的销毁操作是先父后子
,销毁完成的顺序是先子后父
。
加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程
父 beforeUpdate -> 父 updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
#(了解)二十八.SSR了解吗?
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端
。
SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreate
和created
两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求。
#(了解)在vuejs中实现防止模板渲染时闪烁的方法
[v-cloak] {
display: none;
}
<div v-cloak>
{{ message }}
</div>
#(了解)十九、聊聊你对Vue.js的template编译的理解?
简而言之,就是先转化成AST树,再得到的render函数返回VNode(Vue的虚拟DOM节点)。
详情步骤:
首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 抽象语法树 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创建编译器的。另外compile还负责合并option。
然后,AST会经过generate(将AST语法树转化成render funtion字符串的过程)得到render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等)
#(了解)谈谈Vue.extend和Vue.component
Vue.extend
返回的是一个扩展实例构造器,也就是预设了部分选项的Vue实例构造器。其主要用来服务于Vue.component
。
Vue.component()`会注册一个全局的组件,其会自动判断第二个传进来的是Vue继续对象(`Vue.extend`)还是普通对象(`{...}`),如果传进来的是普能对象的话会自动调用`Vue.extend
#(了解)九、vue常用的修饰符?
.prevent: 提交事件不再重载页面;
.stop: 阻止单击事件冒泡;
.self: 当事件发生在该元素本身而不是子元素的时候会触发;
.capture: 事件侦听,事件发生的时候会调用;
#(了解)十、什么是vue的计算属性?
在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:
① 使得数据处理结构清晰;
② 依赖于数据,数据更新,处理结果自动更新;
③ 计算属性内部this指向vm实例;
④ 在template调用时,直接写计算属性名即可;
⑤ 常用的是getter方法,获取数据,也可以使用set方法改变数据;
⑥ 相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。
#(了解)五、Vue的路由实现
1、hash模式
在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取; 特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
2、history模式
history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。 history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
#(了解)vue-router 有几种导航钩子?
1、全局守卫: router.beforeEach
2、全局解析守卫: router.beforeResolve
3、全局后置钩子: router.afterEach
4、路由独享的守卫: beforeEnter
5、组件内的守卫: beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave