Vue面试专题知识点总结
简介
此篇 js - 【vue 知识总结】 知识点: 全部弄懂了,面试很容易。
一、虚拟 dom
1、虚拟 dom是什么
- virtual dom,虚拟 DOM
- 用 JS 模拟 DOM 结构
- DOM 变化的对比,放在 JS 层来做 ( 图灵完备语言 )
- 优点:提高重绘性能
2、虚拟 dom存在的意义
- DOM 操作非常 “昂贵”
- 将 DOM 对比操作放在 JS 层,提高效率
- 项目越复杂 ,影响就越严重
3、vdom 的如何应用,核心 API 是什么?
- 介绍 snabbdom
- snabbdom :一个 vdom 实现库。
- 核心 API
- h 函数
- h 函数是生成虚拟 DOM 的函数
- h('<标签名>',{ ... 属性 ... },[... 子元素 ...])
- h('<标签名>',{ ... 属性 ... },[ ‘....’])
- patch 函数
- 使用 diff 算法来比较旧 VNode 及新的 VNode 之间的差异然后执行 Patch Operation 或者叫 Patch 函数来高效更新 Dom 节点。
- patch(container,vnode)
- patch(vnode,newVnode)
4、介绍 一下 diff 算法
- 简介
- diff 算法 一直在我们身边,并不是 Vue 和 React 创造出来的概念
- vdom 为何用diff 算法
- DOM 操作是 “昂贵”的,因此尽量减少DOM 操作
- 找出本次 DOM 必须更新的节点来更新,其它的 不更新
- 这个 “ 找出 ” 的过程,就需要 diff 算法
- diff 实现过程
- patch (container,vnode)
- 核心 逻辑createElment
functioncreateElement(vnode) {
let tag = vnode.tag
let attrs = vnode.attr || {}
let children = vnode.children || []
let elem = document.createElement(tag)
for (let attrName in attrs) {
if (attr.hasOwnProperty(attrName)) {
elem.setAttribute(attrName, attrs[attrName])
}
}
children.forEach((childVnode) => {
elem.append(createElement(childVnode))
})
return elem
}
- 核心 逻辑createElment
- patch (vnode,newVnode)
- 核心 逻辑updataChildren
functionupdateChildren(vnode, newVnode) {
let children = vnode.children || []
let newChildren = newVnode.children || []
children.forEach((child, index) => {
let newChild = newChildren[index]
if (newChild == null) {
return
}
if (child.tag === newChild.tag) {
updateChildren(child, newChild)
} else {
replaceNode(child, newChild)
}
})
}
- 核心 逻辑updataChildren
- patch (container,vnode)
- 介绍一下 diff 算法?
- 知道什么是 diff 算法,是linux 的基础命令
- vdom 中 应用 diff算法目的: 是为了 找出需要更新的节点
- diff 实现:patch (container,vnode)和 patch (vnode,newVnode)
- 核心 逻辑 , createElment 和 updataChildren
二、Vue 知识总结
5、框架和库的区别
- ibrary(库)
- 小而巧的库,只提供特定的API;优点就是 船小好调头。可以很方便的从一个库切换到另外的库;但是代码几乎不会改变。
- Framework(框架)
- 大而全的是框架;框架提供了一整套的解决方案;所以,如果在项目中间,想切换到另外的框架,是比较困难的。
- 说一下 使用 jQuery 和 使用框架的区别
- 数据 和 视图 的分离,解耦( 开放封闭原则 )
- VUE 以数据驱动视图,只关心数据变化,DOM 操作被封装
6、Vue与Angular以及React的区别
- vue与angular
- AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。
- vue 与React
- React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。
7、Vue概述
- Vue是什么
- 是一个渐进式的构建用户界面的js框架
- where
- 小到的简单的表单处理,大到复杂的数据操作比较频繁的单页面应用程序
- 为什么用VUE
- 数据驱动
- 组件化
- 工作方式
- 可以通过丰富的指令扩展模板,可以通过各种各样的插件来增强功能
8、MVVM框架模式
- 概念
- MVVM是Model-View-ViewModel的简写。是一个软件架构设计模式,是一种简化用户界面的事件驱动编程方式。
- 每个字母解析
- Model 代表数据模型
- View 代表视图,它负责将数据模型转化成UI 展现出来
- 连接 Model 和 View,简单理解就是一个同步View 和 Model的对象,连接Model和View
9、Vue 三要素 *
9.1、响应式:vue 如何监听到 data 的每个属性变化?
响应式中observe还有dep 还有wather 各自都分担什么任务【observe类】【dep对象】【wather 执行者】--- 弄清楚
- Vue 响应式是什么
- data 属性被代理到 vm 上
- Object.defineProperty(双向数据绑定)
- 定义
- Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
- 缺点 【为什么Vue3.x 升级使用 Proxy 取代 Object.defineProperty】
- Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
- Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。
- Proxy不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
- 定义
- data 属性变化过程
- 修改属性,被响应式 的 set 监听到
- set 中执行 updataComponent ( 异步 )
- updataComponent 重新执行 vm.render()
- 生成的 vnode 和 prevVnode,通过 patch 进行比较
- 渲染到 html 中
- 模拟实现 Vue 如何监听data
let vm={}
let data={
name:'zc',
age:'12'
}
for(let key in data){
if(data.hasOwnProperty(key)){
Object.defineProperty(vm,key,{
get:function () {
return data[key]
},
set:function (newValue) {
data[key] = newValue
}
})
}
}
9.2、模板引擎:vue 的模板如何被解析,指令如何处理?
- 模板是什么?
- 本质:字符串
- 有逻辑,如 v-if 、v-for 等
- 与 html 格式很像,但有很大区别
- 最终还要转换为 html 来显示
- 模板最终必须转化成 JS 代码,因为
- 有逻辑(v-if、v-for),必须用 JS 才能实现 ( 图灵完备 )
- 转换成 html 渲染页面,必须用 JS 才能实现
- 因此,模板最重要转换成 一个 JS 函数 (render 函数)
- vue 中如何解析 模板
- 概述
- 模板必须转换成 render 函数 (编译的第一步是将模板通过 parse 函数解析成 AST(抽象语法树),第二步优化AST(检测出不需要更改的DOM的纯静态子树),第三步根据优化后的抽象语法树生成包含渲染函数字符串的对象。)
- 具体
- 第一步是将模板通过 parse 函数解析成 AST(抽象语法树)
- 解析成AST:parse 函数【源码】
- 在解析模版的过程中,不断触发各种钩子函数,将节点信息通过 start, end 和 chars ,comment方法传递给 Vue.js 的 ast 构建程序,边解析边同时构建模版的 ast。
- 第二步优化AST(检测出不需要更改的DOM的纯静态子树)
- 优化AST:optimize 函数【源码】
- 第三步根据优化后的抽象语法树生成包含渲染函数字符串的对象。
- 生成渲染函数:generate 函数【源码】
- 第一步是将模板通过 parse 函数解析成 AST(抽象语法树)
- 概述
9.3、渲染:vue的模板如何被渲染成html?以及渲染过程
- render 函数 与 vdom
- updataComponent 中实现了生成 vdom 的 patch
- 页面首次渲染执行 updataComponent
- render 函数 - with 的用法
- 总结
- 模板中所有信息都包含在了 render 函数中
- this 即 vm
- price 即 this.price 即 vm.price ,即 data 中的 price
- _c 即 this. _c 即 vm. _c
- 使用
// 使用 with
functionfn1() {
with (obj) {
console.log(name)
console.log(age)
getAddress()
}
}
- 总结
- data 中每次修改属性,执行 updataComponent
10、vue 的整个实现流程?
- 第一步:解析模板成 render 函数
- 第二步:响应式开始监听
- 第三步:首次渲染,显示页面,且绑定依赖
- 第四步:data 属性变化,触发 rerender
11、Vue 生命周期
- 生命周期是什么
- Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
- 作用
- 它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
- vue生命周期总共有几个阶段?
- 它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后
- 第一次页面加载会触发哪几个钩子?
- 第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
- 简单描述每个周期具体适合哪些场景?
- beforecreate:可以在这加个loading事件,在加载实例时触发
- created:初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
- mounted:挂载元素,获取到DOM节点
- updated:如果对数据统一处理,在这里写上相应函数
- beforeDestroy:可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作dom
- 钩子函数
- beforeCreate :组件实例刚创建,data和methods 中的数据未被初始化
- created:组件实例创建完成,data 和 methods 都已经被初始化好了!但DOM还未生成
- beforeMount:模板编译/挂载之前
- mounted:模板编译/挂载之后
- beforeUpdate:组件更新之前
- updated:组件更新之后
- beforeDestroy:组件销毁前调用
- destroyed:组件销毁后调用
12、Vue 组件间的通信(父亲,兄弟,爷孙 等等)
六种方式
- props/$emit
- 父组件A通过props的方式向子组件B传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。
- 适用范围:父子组件中
- on
- 这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案vuex。
- 具体实现方式
var Event=new Vue();
Event.$emit(事件名,数据);
Event.$on(事件名,data => {});
- 适用范围:包括父子、兄弟、跨级
- vuex
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- listeners
- 多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。但如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点大材小用。为此Vue2.4 版本提供了另一种方法----listeners
- provide/inject
- 以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
- children与 ref
弊端:两种方法的弊端是,无法在跨级或兄弟间通信。
常见使用场景可以分为三类
- 父子通信
- 父向子传递数据是通过 props,子向父是通过 events(parent / attrs/$listeners
- 兄弟通信
- Bus;Vuex
- 跨级通信
- Bus;Vuex;provide / inject API、listeners
13、Vuex
- 定义
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- Vuex 背后的基本思想
- 把组件的共享状态抽取出来,以一个全局单例模式管理,在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
- Vuex 和单纯的全局对象有以下两点不同
- Vuex 的状态存储是响应式的。
- 你不能直接改变 store 中的状态。该变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。是因为我们想要更明确地追踪到状态的变化。
- vuex的组成
- state
- Vuex 使用 state来存储应用中需要共享的状态。为了能让 Vue 组件在 state更改后也随着更改,需要基于state创建计算属性。
- getters
- 可以认为是 store 的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
- mutations(同步)
- 是改变状态的执行者,mutations用于同步地更改状态
store.commit({
type: 'increment',
amount: 10//这是额外的参数
})
- 是改变状态的执行者,mutations用于同步地更改状态
- actions(异步)
- 异步地更改状态,action并不直接改变state,而是发起mutation
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
- 异步地更改状态,action并不直接改变state,而是发起mutation
- Module: 模块化store
- 出现的问题
- 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
- 解决方案
- Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
- 出现的问题
- state
vuex的工作流程
- 数据从state中渲染到页面
- 在页面通过dispatch来触发action
- action通过调用commit,来触发mutation
- mutation来更改数据,数据变更之后会触发dep对象的notify,通知所有Watcher对象去修改对应视图(vue的双向数据绑定原理)
应用场景
- 多个视图依赖于同一状态
- 来自不同视图的行为需要改变同一个状态
14、Vue的路由(vue-router)
Vue的路由的实现原理 【必须得很清楚】
- vue-router
- vue-router是什么
- Vue Router 是 Vue.js 官方的路由管理器
- 哪些组件
- <router-link >
- <router-view>
- <keep-alive >
- 定义
- keepalive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的-----组件缓存
- 组件缓存
- 使用 include/exclude
- include
- exclude
- 增加 router.meta 属性
meta: {
keepAlive: true// 需要被缓存
}
- 使用 include/exclude
- activated 当 keepalive 包含的组件再次渲染的时候触发
- deactivated 当 keepalive 包含的组件销毁的时候触发
- 定义
- vue-router是什么
- 动态路由
- 创建:主要是使用path属性过程中,使用动态路径参数,以冒号开头
- 响应路由参数的变化
- this.$route.params
- watch (监测变化) $route 对象
watch: {
$route(to, from){
console.log(to.path)
// 对路由变化做出响应
}
}
- 使用 2.2 中引入的 beforeRouteUpdate 导航守卫
- 嵌套路由
- 需要在 VueRouter 的参数中使用 children 配置
- 导航
- 声明式
<router-link :to="...
- 编程式
router.push(...)
- 声明式
- 重定向和别名
- 重定向
routes: [
{ path: '/a', redirect: '/b' }
]
- 别名
routes: [
{ path: '/a', component: A, alias: '/b' }
]
- 重定向
- vue-router的两种模式
- hash模式(默认)
- 原理:原理是onhashchage事件,可以在window对象上监听这个事件
- 描述:即通过在链接后添加 # + 路由名字,根据匹配这个字段的变化,触发 hashchange 事件,动态的渲染出页面。
- history模式
- 描述:利用了HTML5 History Interface 中新增的pushState()和replaceState()方法。
- 缺点
- 需要后台配置支持
- 如果刷新时,服务器没有响应响应的资源,会刷出404
- hash模式(默认)
- 导航钩子函数(导航守卫)
- “导航”表示路由正在发生改变。
- 作用
- vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的
- 导航守卫有哪些
- 全局前置守卫
- router.beforeEach
- 全局解析守卫(2.5.0 新增)
- router.beforeResolve
- 全局后置钩子
- afterEach
- 和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
- 路由独享的守卫
- beforeEnter 守卫
- 组件内的守卫
- beforeRouteEnter :在渲染该组件的对应路由被 confirm 前调用
- beforeRouteUpdate:在当前路由改变,但是该组件被复用时调用
- beforeRouteLeave:导航离开该组件的对应路由时调用
- 全局前置守卫
- 相关题目
- vue-router是什么?有哪些组件?
- active-class 是哪个组件的属性?
- active-class是router-link终端属性,用来做选中样式的切换,当router-link标签被点击时将会应用这个样式
- 怎么定义vue-router的动态路由?怎么获取传过来的值?
- vue-router有哪几种导航钩子?
- router的区别是什么?
- router为VueRouter的实例,是一个全局路由对象,包含了路由跳转的方法、钩子函数等
- route 是路由信息对象||跳转的路由对象,每一个路由都会有一个route对象,是一个局部对象,包含path,params,hash,query,fullPath,matched,name等路由信息参数。
- 传参是this.router,接收参数是this.route
- vue-router响应路由参数的变化
- vue-router 传参
- vue-router的两种模式
- vue-router实现路由懒加载(动态加载路由)
- 把不同路由对应的组件分割成不同的代码块,然后当路由被访问时才加载对应的组件即为路由的懒加载,可以加快项目的加载速度,提高效率
15、Mixin
- Mixin是什么
- 一种分发Vue组件中可复用功能的非常灵活的一种方式。
- 什么时候使用Mixins
- 页面的风格不用,但是执行的方法和需要的数据类似、
16、vue指令
- 自定义指令
- Vue.directive
- 自定义一个过滤器
- Vue.filter('过滤器的名称',function(){})
17、一句话就能回答的面试题
- css只在当前组件起作用
- 在style标签中写入scoped即可 例如:<style scoped></style >
- v-if 和 v-show 区别
- v-if按照条件是否渲染,v-show是display的block或none;
- vue.js的两个核心是什么?
- 数据驱动、组件系统
- vue几种常用的指令
- v-for 、 v-if 、v-bind、v-on、v-show、v-else
- vue常用的修饰符?
- prevent: 提交事件不再重载页面;.stop: 阻止单击事件冒泡;.self: 当事件发生在该元素本身而不是子元素的时候会触发;.capture: 事件侦听,事件发生的时候会调用
- v-on 可以绑定多个方法吗?
- 可以
- *vue中 key 值的作用?
- 更准确
- 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。使用key可以避免就地复用的情况。所以会更加准确
- 更快
- 利用key的唯一性生成map对象来获取对应节点,比遍历方式更快
- 更准确
- 什么是vue的计算属性?
- 在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。
- 好处
- 使得数据处理结构清晰
- 依赖于数据,数据更新,处理结果自动更新
- 计算属性内部this指向vm实例
- 在template调用时,直接写计算属性名即可
- 常用的是getter方法,获取数据,也可以使用set方法改变数据
- 较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算
- vue等单页面应用( SPA)及其优缺点
- 优点
- 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
- 基于上面一点,SPA 相对对服务器压力小
- 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
- 缺点
- 不支持低版本的浏览器,最低只支持到IE9;
- 第一次加载首页耗时相对长一些
- 不可以使用浏览器的导航按钮需要自行实现前进、后退。
- 不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件)
- 优点
- Vue 的父组件和子组件生命周期钩子函数执行顺序
- 加载渲染过程
- 父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
- 子组件更新过程
- 父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
- 父组件更新过程
- 父 beforeUpdate -> 父 updated
- 销毁过程
- 父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
- 加载渲染过程
- Vue组件中 data 为什么是一个函数?
- 因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题
希望读者依此构建自己的知识树(思维导图)
偷懒一下:可参考我自己总结思维导图 : 点这里
附带:高频面试题积累文档。 来自于(学长、牛客网等平台)
自己开发的博客地址:zxinc520.com
以上是 Vue面试专题知识点总结 的全部内容, 来源链接: utcz.com/a/115911.html