(学习视频分享:vue视频教程)
一、Vue.js基本问题
1.1.Vue 响应式原理
1.2.Vue.js 的特点
1.3. Vue.js 双向绑定的原理
Vue.js 3.0, 放弃了Object.defineProperty ,使用更快的ES6原生 Proxy (访问对象拦截器, 也称代理器)
【资料图】
步骤:
1.4.Vue中如何监控某个属性值的变化?
比如现在需要监控data中, obj.a 的变化。Vue中监控对象属性的变化你可以这样:
watch: { obj: { handler (newValue, oldValue) { console.log("obj changed") }, deep: true }
deep属性表示深层遍历,但是这么写会监控obj的所有属性变化,并不是我们想要的效果,所以做点修改:
watch: { "obj.a": { handler (newName, oldName) { console.log("obj.a changed") } } }
还有一种方法,可以通过computed 来实现,只需要:
computed: { a1 () { return this.obj.a }}
利用计算属性的特性来实现,当依赖改变时,便会重新计算一个新值。
1.5.Vue.js 3.0 放弃defineProperty, 使用Proxy的原因
Object.defineProperty缺陷
1.6.Vue 2 中给 data 中的对象属性添加一个新的属性时会发生什么?如何解决?
视图并未刷新。这是因为在Vue实例创建时,新属性并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局 api $set():
this.$set(this.obj, "new_property", "new_value")
1.7.Computed和Watch的区别及运用场景
运用场景:
1.8. Computed 和 Methods 的区别
1.9.虚拟DOM,diff算法
1.10.为何需要Virtual DOM?
1.11.过滤器 (Filter)
1.12.常见的事件修饰符及其作用
1.13.v-show指令和v-if指令的区别是什么?
1.14.v-model 是如何实现的,语法糖实际是什么
作用在表单元素上v-model="message"等同于v-bind:value=“message” v-on:input="message=e v e n t . t a r g e t . v a l u e " 作 用 在 组 件 上 , 本 质 是 一 个 父 子 组 件 通 信 的 语 法 糖 ,通过prop和.emit实现, 等同于:value="message" @input=" $emit("input", $event.target.value)"
1.15.data为什么是一个函数而不是对象
1.16.Vue template 到 render 的过程
1.17.Vue template 到 render 的过程
1.18.axios是什么
易用、简洁且高效的http库, 支持node端和浏览器端,支持Promise,支持拦截器等高级配置。
1.19.sass是什么?如何在vue中安装和使用?
sass是一种CSS预编译语言安装和使用步骤如下。
1.20.Vue.js页面闪烁
Vue. js提供了一个v-cloak
指令,该指令一直保持在元素上,直到关联实例结束编译。当和CSS一起使用时,这个指令可以隐藏未编译的标签,直到实例编译结束。用法如下
1.21.如何解决数据层级结构太深的问题
在开发业务时,经常会岀现异步获取数据的情况,有时数据层次比较深,如以下代码: , 可以使用vm.$set手动定义一层数据:
vm.$set("demo",a.b.c.d)
1.22.在 Vue. js开发环境下调用API接口,如何避免跨域
config/ index.js内对 proxyTable项配置代理。
1.23.批量异步更新策略
1.24.vue 的 nextTick 方法的实现原理
1.25.Vue 组件 data 为什么必须是函数 ?
因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染。 所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。
1.26.v-if和v-for一起使用的弊端及解决办法
由于v-for的优先级比v-if高,所以导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
解决办法:
1.27.vue常用指令
1.28. 组件传值方式有哪些
1.30.vue中 key 值的作用
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM
1.31.为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
Object.defineProperty
本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性(Vue 为什么不能检测数组变动 )。为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组
由于只针对了以上 7 种方法进行了 hack 处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。
1.32.谈一谈 nextTick 的原理
JS 运行机制
JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤:
主线程的执行过程就是一个 tick,而所有的异步结果都是通过 “任务队列” 来调度。 消息队列中存放的是一个个的任务(task)。 规范中规定 task 分为两大类,分别是 macro task 和 micro task,并且每个 macro task 结束后,都要清空所有的 micro task。
for (macroTask of macroTaskQueue) { // 1. Handle current MACRO-TASK handleMacroTask(); // 2. Handle all MICRO-TASK for (microTask of microTaskQueue) { handleMicroTask(microTask); }}
在浏览器环境中 :
常见的 macro task 有 setTimeout、MessageChannel、postMessage、setImmediate
常见的 micro task 有 MutationObsever 和 Promise.then
异步更新队列
vue 的 nextTick 方法的实现原理:
1.33.谈谈 Vue 事件机制,手写on,off,emit,once
Vue 事件机制 本质上就是 一个 发布-订阅 模式的实现。
class Vue { constructor() { // 事件通道调度中心 this._events = Object.create(null); } $on(event, fn) { if (Array.isArray(event)) { event.map(item => { this.$on(item, fn); }); } else { (this._events[event] || (this._events[event] = [])).push(fn); } return this; } $once(event, fn) { function on() { this.$off(event, on); fn.apply(this, arguments); } on.fn = fn; this.$on(event, on); return this; } $off(event, fn) { if (!arguments.length) { this._events = Object.create(null); return this; } if (Array.isArray(event)) { event.map(item => { this.$off(item, fn); }); return this; } const cbs = this._events[event]; if (!cbs) { return this; } if (!fn) { this._events[event] = null; return this; } let cb; let i = cbs.length; while (i--) { cb = cbs[i]; if (cb === fn || cb.fn === fn) { cbs.splice(i, 1); break; } } return this; } $emit(event) { let cbs = this._events[event]; if (cbs) { const args = [].slice.call(arguments, 1); cbs.map(item => { args ? item.apply(this, args) : item.call(this); }); } return this; }}
1.34.vue-router有哪几种导航钩子?
三种:
1.35.vuex是什么?怎么使用?哪种功能场景使用它?
1.36.MVVM和MVC区别?和其他框架(jquery)区别?那些场景适用?
1.37.聊聊你对Vue.js的模板编译的理解
简而言之,就是先转化成AST树,再得到的渲染函数返回VNODE(Vue公司的虚拟DOM节点) 详情步骤:
1.38.< keep-alive>< /keep-alive>的作用是什么,如何使用?
答:包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染; 使用:简单页面时 缓存: < keep-alive include=”组件名”>< /keep-alive>
不缓存: < keep-alive exclude=”组件名”>< /keep-alive>
1.39.vue和react区别
相同点:都鼓励组件化,都有’props’的概念,都有自己的构建工具,Reat与Vue只有框架的骨架,其他的功能如路由、状态管理等是框架分离的组件。
不同点:React:数据流单向,语法—JSX,在React中你需要使用setState()方法去更新状态。Vue:数据双向绑定,语法–HTML,state对象并不是必须的,数据由data属性在Vue对象中进行管理。适用于小型应用,但对于对于大型应用而言不太适合。
1.40.vue生命周期的理解?
参照大神文章:vue笔记 - 生命周期第二次学习与理解
beforeCreate
是new Vue()之后触发的第一个钩子,在当前阶段data、methods、computed以及watch上的数据和方法都不能被访问。
created
在实例创建完成后发生,当前阶段已经完成了数据观测,也就是可以使用数据,更改数据,在这里更改数据不会触发updated函数。可以做一些初始数据的获取,在当前阶段无法与Dom进行交互,如果非要想,可以通过vm.$nextTick来访问Dom。
beforeMount
发生在挂载之前,在这之前template模板已导入渲染函数编译。而当前阶段虚拟Dom已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updated。
mounted
在挂载完成后发生,在当前阶段,真实的Dom挂载完毕,数据完成双向绑定,可以访问到Dom节点,使用$refs属性对Dom进行操作。
beforeUpdate发生在更新之前,也就是响应式数据发生更新,虚拟dom重新渲染之前被触发,你可以在当前阶段进行更改数据,不会造成重渲染。
updated
发生在更新完成之后,当前阶段组件Dom已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新。
beforeDestroy
发生在实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,比如清除计时器。
destroyed
发生在实例销毁之后,这个时候只剩下了dom空壳。组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁。
1.41.Vue2.x和Vue3.x渲染器的diff算法分别说一下
简单来说,diff算法有以下过程
正常Diff两个树的时间复杂度是O(n^3)
,但实际情况下我们很少会进行跨层级的移动DOM,所以Vue将Diff进行了优化,从O(n^3) -> O(n)
,只有当新旧children都为多个子节点时才需要用核心的Diff算法进行同层级比较。
Vue2的核心Diff算法采用了双端比较的算法,同时从新旧children的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。相比React的Diff算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。
Vue3.x借鉴了ivi算法和 inferno算法
在创建VNode时就确定其类型,以及在 mount/patch 的过程中采用位运算来判断一个VNode的类型,在这个基础之上再配合核心的Diff算法,使得性能上较Vue2.x有了提升。(实际的实现可以结合Vue3.x源码看。)
该算法中还运用了动态规划的思想求解最长递归子序列。
1.42.你都做过哪些Vue的性能优化?
编码阶段
SEO优化
打包优化
用户体验
还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。
1.43.hash路由和history路由实现原理说一下
location.hash
的值实际就是URL中#后面的东西。
history
实际采用了HTML5中提供的API来实现,主要有history.pushState()
和history.replaceState()
。
1.44.SPA 单页面的理解,它的优缺点分别是什么
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS 一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转 取而代之的是利用路由机制实现 HTML 内容的变换, UI 与用户的交互,避免页面的重新加载 优点:
缺点:
1.45.vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?
1.46.vue如何实现按需加载配合webpack设置
二、组件 Component
2.1.vue中如何编写可复用的组件 (编写组件的原则)
以组件功能命名 只负责ui的展示和交互动画,不要在组件里与服务器打交道(获取异步数据等) 可复用组件不会因组件使用的位置、场景而变化。尽量减少对外部条件的依赖。
2.2.如何让CSS只在当前组件中起作用?
在每一个Vue.js组件中都可以定义各自的CSS、 JavaScript代码。如果希望组件内写的CSS只对当前组件起作用,只需要在Style标签添加Scoped属性即可
2.3.keep-alive是什么?
如果需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。
两个重要属性,include 缓存组件名称,exclude 不需要缓存的组件名称。
2.4.如何在 Vue. js动态插入图片
对“src”属性插值将导致404请求错误。应使用 v-bind:src (简写:src)格式代替。
2.5.父子组件的生命周期顺序(可参照上方图解)
加载渲染过程: 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程:父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程:父beforeUpdate->父updated
销毁过程:父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
三、Vuex
3.1.vuex的核心概念
3.2.vuex是什么?怎么使用?哪种功能场景使用它?
3.3.多个组件之间如何拆分各自的state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块
3.4.Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?
1.如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
2.如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便
3.5.Vuex中如何异步修改状态
actions与mutations作用类似,都是可以对状态进行修改。不同的是actions是异步操作的。
actions是可以调用Mutations里的方法的。
const actions={addActions(context){context.commit("add",10);//调用mutations中的方法setTimeout(()=>{context.commit("reduce")},5000)//setTimeOut(()=>{context.commit("reduce")},3000);console.log("我比reduce提前执行");},reduceActions({commit}){commit("reduce");}}
3.6.Vuex中actions和mutations的区别
Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } }})
Action Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。 Action 可以包含任意异步操作
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit("increment") } }})
3.7.怎么在组件中批量使用Vuex的state状态?
使用mapState
辅助函数, 利用对象展开运算符将state混入computed对象中
import {mapState} from "vuex" export default{ computed:{ ...mapState(["price","number"]) } }
3.8.Vuex中状态是对象时,使用时要注意什么?
对象是引用类型,复制后改变属性还是会影响原始数据,这样会改变state里面的状态,是不允许,所以先用深度克隆复制对象,再修改。
四、Router
4.1.vue-router 路由模式有几种
4.2.vue-router如何定义嵌套路由
通过children 数组:
const router = new VueRouter({ routes: [ { path: "/parentPage", component: testPage, children: [ { path: "/childrenA", component: childrenComponentA, }, { path: "/childrenB", component: childrenComponentB, }, ], }, { // 其他和parentPage平级的路由 }, ],});
4.3.vue-router有哪几种导航钩子?
参数:有to(去的那个路由)、from(离开的路由)、next(一定要用这个函数才能去到下一个路由,如果不用就拦截)最常用就这几种
4.4. $ route和$ router的区别
1、$route
是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name
等路由信息参数。
2、$router
是“路由实例”对象包括了路由的跳转方法,钩子函数等
实例方法:
1)、push
2)、go 页面路由跳转 前进或者后退this.$router.go(-1)
// 后退
3)、replace push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面, 不会向 history 栈添加一个新的记录
4.5.路由之间跳转的方式
1.声明式(标签跳转) 2.编程式( js跳转)
4.6.active-class是哪个组件的属性
vue-router 模块 的router-link组件
4.7.vue-router实现路由懒加载(动态加载路由)
把不同路由对应的组件分割成不同的代码块,然后当路由被访问时才加载对应的组件即为路由的懒加载,可以加快项目的加载速度,提高效率
const router = new VueRouter({ routes: [ { path: "/home", name: "Home", component:() = import("../views/home")} ]})
4.8.怎么定义vue-router的动态路由以及如何获取传过来的动态参数?
面试官:我难道问不倒这小子了?(面试官持续懵逼中) 对大家有帮助的话三连呀~ 持续更新
【相关视频教程推荐:vuejs入门教程、web前端入门】
以上就是【吐血整理】Vue.js面试题汇总及答案解析(快来收藏)的详细内容,更多请关注php中文网其它相关文章!