dom不刷新 vue 加数据后_高频出现的Vue 面试题及答案
本文讲解高频出现的 Vue 面试题及答案。
复习前端面试的知识,是为了巩固前端的基础知识,最重要的还是平时的积累!
注意
:文章的题与题之间用下划线分隔开,答案仅供参考。
Vue
对 MVC、MVP 、MVVM 的理解
MVC 模式的意思是,软件可以分成三个部分。
视图(View):用户界面。
控制器(Controller):业务逻辑。
模型(Model):数据保存。
各部分之间的通信方式如下。
![](/assets/blank.gif)
View 传送指令到 Controller
Controller 完成业务逻辑后,要求 Model 改变状态
Model 将新的数据发送到 View,用户得到反馈
所有通信都是单向的(逆时针)。
MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。
![](/assets/blank.gif)
各部分之间的通信,都是双向的(顺时针)。
View 与 Model 不发生联系,都通过 Presenter 传递。
View 非常薄,不部署任何业务逻辑,称为 "被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
唯一的区别是,它采用双向绑定(data-binding):View 的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。
如何理解 Vue 是异步执行 DOM 更新的 ?
Vue 是异步执行 DOM 更新。
只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。
如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。
然后,在下一个的事件循环
tick
中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。
例如,当你设置 vm.someData = 'new value' ,该组件不会立即重新渲染。
当刷新队列时,组件会在事件循环队列清空时的下一个
tick
更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。
虽然 Vue.js 通常鼓励开发人员沿着 “数据驱动” 的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
深入响应式原理
如何追踪变化
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转 getter/setter。
Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。这里需要注意的问题是浏览器控制台在打印数据对象时 getter/setter 的格式化并不同,所以你可能需要安装 vue-devtools 来获取更加友好的检查接口。
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
观察者订阅了可观察对象,当可观察对象发布事件,则就直接调度观察者的行为,所以这里观察者和可观察对象其实就产生了一个依赖的关系。
![](/assets/blank.gif)
说下对 Virtual DOM 算法的理解 ?
包括几个步骤:
1、用 JavaScript 对象结构表示 DOM 树的结构,然后用这个树构建一个真正的 DOM 树,插到文档当中;
2、当状态变更的时候,重新构造一棵新的对象树,然后用新的树和旧的树进行比较,记录两棵树差异;
3、把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存:既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个缓存。CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM)。
比较两棵虚拟 DOM 树的差异
比较两棵 DOM 树的差异是 Virtual DOM 算法最核心的部分,这也是所谓的 Virtual DOM 的 diff 算法。两个树的完全的 diff 算法是一个时间复杂度为 O(n^3) 的问题。但是在前端当中,你很少会跨越层级地移动 DOM 元素。
所以 Virtual DOM 只会对同一个层级的元素进行对比:
![](/assets/blank.gif)
上面的 div 只会和同一层级的 div 对比,第二层级的只会跟第二层级对比。这样算法复杂度就可以达到 O(n)。
深度优先遍历,记录差异
在实际的代码中,会对新旧两棵树进行一个深度优先的遍历,这样每个节点都会有一个唯一的标记:
![](/assets/blank.gif)
在深度优先遍历的时候,每遍历到一个节点就把该节点和新的的树进行对比。如果有差异的话就记录到一个对象里面。
Virtual DOM 算法主要是实现上面步骤的三个函数:element,diff,patch。然后就可以实际的进行使用:
// 1. 构建虚拟 DOMvar tree = el('div', {'id': 'container'}, [ el('h1', {style: 'color: blue'}, ['simple virtal dom']), el('p', ['Hello, virtual-dom']), el('ul', [el('li')])])// 2. 通过虚拟 DOM 构建真正的 DOMvar root = tree.render()document.body.appendChild(root)// 3. 生成新的虚拟 DOMvar newTree = el('div', {'id': 'container'}, [ el('h1', {style: 'color: red'}, ['simple virtal dom']), el('p', ['Hello, virtual-dom']), el('ul', [el('li'), el('li')])])// 4. 比较两棵虚拟 DOM 树的不同var patches = diff(tree, newTree)// 5. 在真正的 DOM 元素上应用变更patch(root, patches)
当然这是非常粗糙的实践,实际中还需要处理事件监听等;生成虚拟 DOM 的时候也可以加入 JSX 语法。这些事情都做了的话,就可以构造一个简单的 ReactJS 了。
非父子组件如何通信 ?
Vue 官网介绍了非父子组件通信方法:
![](/assets/blank.gif)
在 bus.js 里面 写入下面信息
import Vue from 'vue'export default new Vue();
在需要通信的组件都引入 Bus.js
<div id="emit"><button @click="bus">按钮button>div> </template >import Bus from './bus.js'export default { data() { return { message: '' } }, methods: { bus() { Bus.$emit('msg', '我要传给兄弟组件们,你收到没有') } }}
在钩子函数中监听 msg 事件:
<div id="on"><p>{{message}}p>div></template>import Bus from './bus.js'export default { data() { return { message: '' } }, mounted() { let self = this Bus.$on('msg', (e) => { self.message = e console.log(`传来的数据是:${e}`) }) } }
最后 p 会显示来自 $emit 传来的信息。
什么情况下我应该使用 Vuex ?
虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此,如果您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus[2] 就足够您所需了。
但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
Vue 生命周期图解(vue1.0版本)
参考资料
[1]
GitHub: https://github.com/biaochenxuying/blog
[2]
global event bus: https://cn.vuejs.org/v2/guide/components.html#%E7%9B%91%E5%90%AC%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BA%8B%E4%BB%B6
[3]
1. 对 Vue、Vue-Router、Vuex 源码与架构的理解: https://github.com/biaochenxuying/vue-family-mindmap
[4]
2. Vue 生命周期: https://www.jianshu.com/p/304a44f7c11b
[5]
3. 详解 Vue 生命周期: https://segmentfault.com/a/1190000011381906
[6]
4. Vue 组件间通信六种方式(完整版): https://juejin.im/post/5cde0b43f265da03867e78d3
[7]
5. Vue 学习笔记-实现一个分页组件: https://www.jianshu.com/p/d17d8e35deda
[8]
前端硬核面试专题: https://github.com/biaochenxuying/blog/blob/master/interview/fe-interview.md
dom不刷新 vue 加数据后_高频出现的Vue 面试题及答案相关推荐
- dom不刷新 vue 加数据后_详解Vue 数据更新了但页面没有更新的 7 种情况汇总及延伸总结...
如果你发现你自己需要在 vue 中做一次强制更新,99.9% 的情况,是你在某个地方做错了事. 1. vue 无法检测实例被创建时不存在于 data 中的 property 原因:由于 vue 会在初 ...
- ant design vue 树形控件_官宣!vue.ant.design 低调上线
点击右上方,关注开源中国OSC头条号,获取最新技术资讯 官宣!官宣!官宣! 是的,你没看错就是那个 https://vue.ant.design. 至此,Ant Design 已经全面覆盖了 Reac ...
- vue调试工具如何使用_教你使用Vue.js的DevTools来调试vue项目
Vue DevTools项目的官方主页位于GitHub上:https://http://github.com/vuejs/vue-devtools.你可以找到安装说明,帮助解决一些问题等等.目前该扩展 ...
- 删除vue打包大小限制_压缩Vue.js打包后的体积方法总结(Vue.js打包后体积过大问题)...
问题 由于这次项目是在初学 Vue 之后的第一个正式项目,没有考虑到类似 路由懒加载. 按需加载的问题 ,所以呢,也算是没经验. 到了这些天,项目写得差不多了,准备放到服务器测试,才发现这个问题. 优 ...
- vue 单选框样式_作为一位Vue工程师,这些开发技巧你都会吗?
来源 | http://www.cnblogs.com/chanwahfung/p/12543103.html 路由参数解耦 一般在组件内使用路由参数,大多数人会这样做: export default ...
- vue 构建根组件_构建迷你图Vue组件
vue 构建根组件 Sparklines can be used to quickly visualize data variance. They are small and intuitive to ...
- 怎么改vue项目的标题_如何动态修改Vue项目中的页面title
前言:在项目中,我们有时候需要修改Vue项目中的页面title. 方法有两种,①如果需要动态设置页面的title,可以直接使用document.title:②可以使用router的beforeEach ...
- app vue 真机运行_使用 HBuilder 将 Vue 项目打包成手机 App
在开发移动端 app 时可以选择原生 app 和 webapp, 原生 app 体验好,开发成本高,相对的 webapp 体验要差,开发成本低.webapp 要求很低,可以说只要会开发web 站就能开 ...
- vue图片裁剪组件_使用Vue-Rx的Vue.js图像裁剪组件
vue图片裁剪组件 Vuejs夹 (vuejs-clipper) Vue.js image clipping components using Vue-Rx. 使用Vue-Rx的Vue.js图像裁剪组 ...
最新文章
- Windows Phone 实用开发技巧(10):Windows Phone 中处理图片的技巧
- mysql 事务 数量_如何知道数据库创建以来并发事务的最大数量
- 算法导论-排序(四)计数排序(线性时间排序)
- intellij导入scala工程不识别scala语言
- Docker一些常用命令
- 3大AI事件入围百度2017科技热搜,柯洁对战AlphaGo排名第一
- oracle数据库top用法,Oracle TOP SQLHIT
- 【剧透】2017云栖大会·北京峰会——企业云上业务优化专场
- 跳棋的C语言,跳棋游戏C语言程序设计(数据结构课程设计报告).doc
- VMware 将虚拟磁盘多个文件合并为单个文件
- 尘梦回还服务器在维护中是什么意思,20190925维护公告解读
- 蛋白质二级结构预测Linux,哪些蛋白质二级结构预测软件可以批量使用?
- m4a怎么转换成mp3?
- Ubuntu卸载安装包
- Java设计模式第一章(软件设计原则)(学习笔记)
- 工商名人堂 爱德华·约翰逊二世---富达基金的崛起(转载自新浪)
- 不用action提交表单——JS实现
- java连接高斯数据库,高斯数据库 (gaussDB) - 基于 JDBC 开发 (9)
- python圣诞雪人
- 便宜运行linux芯片,个头小本事大:13 种 20 美元以下的树莓派 Zero 替代品 | Linux 中国...
热门文章
- java中pc寄存器的作用是什么_既然有PC寄存器,栈帧里的返回地址的作用是什么?...
- 系统封装工具_去工具化/脚本化理解,自动化运维落地最佳实践之业务/架构/模型/方法...
- mac hdmi 不能调整音量_搭配这几个软件,你的 AirPods 在安卓、Mac 上会更好用
- 统计学中p值计算公式_大学统计学白上了?800 多科学家联名反对 “统计学意义”,P 值该废了...
- php带参数单元测试_一文搞定单元测试核心概念
- android.mk 比较字变量,Android.mk的用法和基础
- php 单一职责,PHP之单例模式(职责模式)
- 在excel工作表中c1单元格_已知Excel工作表中A1单元格和B1单元格的值分别为“电子科技大学”、“信息中心”,要求在C1单元格显示“...
- linux深度定制,专为国人订制!Linux Deepin新版发布
- mysql的count()函数如何选择索引,千万级表的count()查询优化实例