主题
Vue
1. 对于 MVVM 的理解
MVVM 是 Model-View-ViewModel 的缩写
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。View代表UI组件, 它负责将数据模型转化成UI展现出来。ViewModel监听模型数据的改变和控制视图行为 、处理用户交互, 简单理解就是⼀个同步View和Model的对象, 连接Model和View- 在
MVVM架构下,View和Model之间并没有直接的联系, 而是通过ViewModel进行交互,Model和ViewModel之间的交互是双向的, 因此View数据的变化会同步到Model中, 而Model数据的变化也会立即反应到View上。 ViewModel通过双向数据绑定把View层和Model层连接了起来, 而View和Model之间的同步⼯作完全是自动的, ⽆需⼈为⼲涉, 因此开发者只需关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题, 复杂的数据状态维护完全由MVVM来统⼀管理
- 在
2. 请详细说下你对 vue 生命周期的理解
总共分为 8 个阶段 创建前/后, 载⼊前/后,更新前/后,销毁前/后
- 创建前/后: 在
beforeCreate阶段,vue实例的挂载元素el和数据对象data都为undefined, 还未初始化 。在created阶段,vue实例的数据对象data有了,el还没有 - 载⼊前/后:在
beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换 。在mounted阶段,vue实例挂载完成,data.message成功渲染 - 更新前/后: 当
data变化时,会触发beforeUpdate和updated方法 - 销毁前/后:在执行
destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
什么是 vue 生命周期?
Vue 实例从创建到销毁的过程,就是生命周期 。从开始创建 、初始化数据 、编译模板 、挂载 Dom→ 渲染 、更新 → 渲染 、销毁等⼀系列过程,称之为 Vue 的生命周期。
vue 生命周期的作用是什么?
它的生命周期中有多个事件钩⼦ ,让我们在控制整个 Vue 实例的过程时更容易形成好的逻辑。
vue 生命周期总共有几个阶段?
它可以总共分为 8 个阶段:创建前/后 、载⼊前/后 、更新前/后 、销毁前/销毁后。
第⼀次页面加载会触发哪几个钩子?
会触发下面这⼏个 beforeCreate 、 created 、 beforeMount 、 mounted 。
DOM 渲染在哪个周期中就已经完成?
DOM 渲染在 mounted 中就已经完成了
3. Vue 实现数据双向绑定的原理:Object.defineProperty()
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的⽅式, 通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调 。当把⼀个普通Javascript对象传给Vue实例来作为它的data选项时,Vue将遍历它的属性,用Object.defineProperty()将它们转为getter/setter。用户看不到getter/setter,但是在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化vue的数据双向绑定 将MVVM作为数据绑定的⼊⼝ ,整合Observer,Compile和Watcher三者, 通过Observer来监听自⼰的model的数据变化, 通过Compile来解析编译模板指令 (vue中是用来解析), 最终利用watcher搭起observer和Compile之间的通信桥梁, 达到数据变化 — >视图更新;视图交互变化 (input) — > 数据model变更双向绑定效果。
4. Vue 组件间的参数传递
- 父组件与子组件传值
父组件传给⼦组件:⼦组件通过 props ⽅法接受数据;
⼦组件传给父组件: $emit ⽅法传递参数
- 非父子组件间的数据传递,兄弟组件传值
eventBus ,就是创建⼀个事件中心,相当于中转站, 可以用它来传递事件和接收事件 。项目比较⼩时,用这个比较合适 ( 虽然也有不少⼈推荐直接用 VUEX , 具体来说看需求)
5. Vue 的路由实现: hash 模式 和 history 模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取 。特点:hash虽然在URL中,但不被包括在HTTP请求中 ;用来指导浏览器动作,对服务端安全⽆用,hash不会重加载页面 。history模式:history采用HTML5的新特性;且提供了两个新⽅法:pushState(),replaceState()可以对浏览器历史记录栈进⾏修改, 以及popState事件的监听到状态变更
6. vue 路由的钩子函数
首页可以控制导航跳转, beforeEach , afterEach 等,⼀ 般用于页面 title 的修改 。⼀些需要登录才能调整页面的重定向功能。
beforeEach主要有 3 个参数to,from,next。to:route即将进⼊的目标路由对象。from:route当前导航正要离开的路由。next:function⼀定要调用该⽅法resolve这个钩⼦ 。执⾏效果依赖next⽅法的调用参数 。可以控制网页的跳转
7. vuex 是什么?怎么使用? 哪种功能场景使用它?
- 只用来读取的状态集中放在
store中; 改变状态的⽅式是提交mutations, 这是个同步的事物; 异步逻辑应该封装在action中 - 在
main.js引⼊store, 注⼊ 。新建了⼀个目录store,… export - 场景有:单页应用中, 组件之间的状态 、音乐播放 、登录状态 、加⼊购物车
vuex
state:Vuex使用单⼀状态树,即每个应用将仅仅包含⼀个store实例,但单⼀状态树和模块化并不冲突 。存放的数据状态,不可以直接修改里面的数据mutations:mutations定义的⽅法动态修改Vuex的store中的状态或数据getters:类似vue的计算属性, 主要用来过滤⼀些数据。action:actions可以理解为通过将mutations里面处里数据的⽅法变成可异步的处理数据的⽅法, 简单的说就是异步操作数据 。view层通过store.dispath来分发actionmodules:项目特别复杂的时候, 可以让每⼀个模块拥有自⼰的state、mutation、action、getters,使得结构非常清晰, ⽅便管理
8. v-if 和 v-show 区别
v-if 按照条件是否渲染, v-show 是 display 的 block 或 none ;
9. $route 和 $router 的区别
$route 是“路由信息对象”, 包括 path , params , hash , query , fullPath , matched , name 等路由信息参数。
而 $router 是“路由实例”对象包括了路由的跳转方法,钩⼦函数等
10. 如何让 CSS 只在当前组件中起作用?
将当前组件的 <style> 修改为 <style scoped>
11. <keep-alive></keep-alive> 的作用是什么?
<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染
比如有⼀个列表和⼀个详情,那么用户就会经常执⾏打开详情=>返回列表=>打开详情 …这样的话列表和详情都是⼀个频率很高的页面,那么就可以对列表组件使用 <keep-alive></keep-alive> 进⾏缓存, 这样用户每次返回列表的时候,都能从缓存中快速渲染, 而不是重新渲染
12. 指令 v-el 的作用是什么?
提供⼀个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标.可以是 CSS 选择器,也可以是⼀个 HTMLElement 实例,
13. 在 Vue 中使用插件的步骤
- 采用
ES6的import...from... 语法或CommonJS的require()方法引⼊插件 - 使用全局方法
Vue.use( plugin )使用插件,可以传⼊⼀个选项对象Vue.use(MyPlugin, { someOption: true })
14. 请列举出 3 个 Vue 中常用的生命周期钩子函数?
created: 实例已经创建完成之后调用,在这⼀步,实例已经完成数据观测, 属性和方法的运算,watch/event事件回调. 然而, 挂载阶段还没有开始,$el属性目前还不可⻅mounted:el被新创建的vm.$el替换, 并挂载到实例上去之后调用该钩⼦ 。如果root实例挂载了⼀个文档内元素, 当mounted被调用时vm.$el也在文档内。activated:keep-alive组件激活时调用
15. vue-cli 工程技术集合介绍
问题⼀: 构建的 vue-cli 工程都到了哪些技术,它们的作用分别是什么?
vue.js:vue-cli工程的核心, 主要特点是 双向数据绑定和组件系统。vue-router:vue官方推荐使用的路由框架。vuex:专为Vue.js应用项目开发的状态管理器, 主要用于维护vue组件间共用的⼀些变量和方法。axios( 或者fetch、ajax): 用于发起GET、或POST等http请求, 基于Promise设计。vuex等:⼀个专为vue设计的移动端 UI 组件库。- 创建⼀个
emit.js文件,用于vue事件机制的管理。 webpack:模块加载和vue-cli工程打包器。
问题二:vue-cli 工程常用的 npm 命令有哪些?
- 下载
node_modules资源包的命令:
shell
npm install- 启动
vue-cli开发环境的npm命令:
shell
npm run devvue-cli生成 生产环境部署资源 的npm命令:
shell
npm run build- 用于查看
vue-cli生产环境部署资源文件大小的npm命令:
shell
npm run build --report在浏览器上自动弹出⼀个 展示 vue-cli 工程打包后 app.js 、manifest.js 、 vendor.js 文件里面所包含代码的页面 。可以具此优化 vue-cli 生产环境部署的静态资源,提升页面的加载速度
16. NextTick
nextTick 可以让我们在下次 DOM 更新循环结束之后执行延迟回调,用于获得更新后的 DOM
17. vue 的优点是什么?
- 低耦合 。视图 (
View) 可以独立于Model变化和修改,⼀个ViewModel可以绑定到不同的"View"上, 当View变化的时候Model可以不变, 当Model变化的时候View也可以不变 - 可重用性 。你可以把⼀些视图逻辑放在⼀个
ViewModel里面,让很多view重用这段视图逻辑 - 可测试 。界面素来是比较难于测试的, 而现在测试可以针对
ViewModel来写
18. 路由之间跳转?
声明式 (标签跳转)
vue
<router-link :to="index" />编程式 ( js 跳转)
js
router.push("index");19. 实现 Vue SSR
其基本实现原理
app.js作为客户端与服务端的公用入口, 导出Vue根实例,供客户端entry与服务端entry使用 。客户端entry主要作用挂载到DOM上, 服务端entry除了创建和返回实例, 还进行路由匹配与数据预获取webpack为客服端打包⼀个Client Bundle, 为服务端打包⼀个Server Bundle。- 服务器接收请求时,会根据
url,加载相应组件, 获取和解析异步数据,创建⼀个读取Server Bundle的BundleRenderer,然后生成html发送给客户端。 - 客户端混合,客户端收到从服务端传来的
DOM与自⼰的生成的DOM进行对比, 把不相同的DOM激活,使其可以能够响应后续变化, 这个过程称为客户端激活 。为确保混合成功,客户端与服务器端需要共享同⼀套数据 。在服务端, 可以在渲染之前获取数据,填充到stroe里, 这样,在客户端挂载到DOM之前, 可以直接从 store 里取数据 。首屏的动态数据通过window.__INITIAL_STATE__发送到客户端
Vue SSR 的实现, 主要就是把 Vue 的组件输出成⼀个完整 HTML , vue-server-renderer 就是干这事的
Vue SSR 需要做的事多点 ( 输出完整 HTML ), 除了 complier -> vnode , 还需如数据获取填充至 HTML 、客户端混合 ( hydration ) 、缓存等等 。 相比于其他模板引擎( ejs , jade 等), 最终要实现的目的是⼀样的,性能上可能要差点
20. Vue 组件 data 为什么必须是函数
每个组件都是 Vue 的实例。
组件共享 data 属性, 当 data 的值是同⼀个引用类型的值时, 改变其中⼀个会影响其他
21. Vue computed 实现
建立与其他属性 ( 如: data 、 Store ) 的联系;
属性改变后, 通知计算属性重新计算
实现时, 主要如下:
- 初始化
data, 使用Object.defineProperty把这些属性全部转为getter/setter。 - 初始化
computed, 遍历computed里的每个属性,每个computed属性都是⼀个watch实例 。每个属性提供的函数作为属性的getter,使用Object.defineProperty转化。 Object.definePropertygetter依赖收集 。用于依赖发生变化时,触发属性重新计算。- 若出现当前
computed计算属性嵌套其他computed计算属性时, 先进行其他的依赖收集
22. Vue complier 实现
模板解析这种事,本质是将数据转化为⼀段 html , 最开始出现在后端, 经过各种处理吐给前端 。随着各种 mv* 的兴起,模板解析交由前端处理。
总的来说, Vue complier 是将 template 转化成⼀个 render 字符串
可以简单理解成以下步骤:
parse过程,将template利用正则转化成AST抽象语法树 。optimize过程,标记静态节点,后diff过程跳过静态节点,提升性能。generate过程,生成render字符串
23. 怎么快速定位哪个组件出现性能问题
用 timeline 工具 。 大意是通过 timeline 来查看每个函数的调用时常,定位出哪个函数的问题,从而能判断哪个组件出了问题
