Vue.js常被提及的面试题
2019-08-14 10:17:25来源:博客园 阅读 ()
对于MVVM的理解
由 Model、View、ViewModel 三部分构成,由MVC衍生。
Model: 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑,
View: 代表UI 组件,它负责将数据模型转化成UI 展现出来,
ViewModel: 是一个同步View 和 Model的对象。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。 (注意)
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
Vue.js双向数据原理
Vue.js 可以说是MVVM 架构的最佳实践,专注于 MVVM 中的 ViewModel,不仅做到了数据双向绑定,而且也是一款相对来比较轻量级的JS 库,API 简洁,很容易上手。
Vue.js 是采用 Object.defineProperty 的 getter 和 setter,并结合观察者模式来实现数据绑定的。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。(注意:据悉vue3.0将采用Proxy替代Object.defineProperty)
图的解析:
Observer :数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,内部采用Object.defineProperty的getter和setter来实现 。
Compile :指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数 。
Watcher :订阅者,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数 。
Dep :消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法 。
执行过程:
当执行 new Vue() 时,Vue 就进入了初始化阶段,一方面Vue 会遍历 data 选项中的属性,并用 Object.defineProperty 将它们转为 getter/setter,实现数据变化监听功能;另一方面,Vue 的指令编译器Compile 对元素节点的指令进行扫描和解析,初始化视图,并订阅 Watcher 来更新视图, 此时Wather 会将自己添加到消息订阅器中(Dep),初始化完毕。
当数据发生变化时,Observer 中的 getter 方法被触发(注意这里触发什么),getter 会立即调用Dep.notify(),Dep 开始遍历所有的订阅者,并调用订阅者的 update 方法,订阅者收到通知后对视图进行相应的更新。同理当表单输入内容发生变化时, 就会触发setter,watcher监听机制就会执行, watcher通知Vue生成新的VDOM树,再通过render函数进行渲染,生成真实DOM 。
通过 Object.defineProperty 实现见简单的双向数据绑定:
<body>
<div id="demo"></div>
<input type="text" id="inp">
</body>
<script>
let obj = {};
let demo = document.querySelector('#demo');
let inp = document.querySelector('#inp');
Object.defineProperty(obj,'name',{
get : () => {
return inp.value;
},
set : (newVal) => {//当该属性被赋值的时候触发
inp.value = newVal;
demo.innerHTML = newVal;
}
});
inp.addEventListener('input',(e) => {
// 给obj的name属性赋值,进而触发该属性的set方法
obj.name = e.target.value;
})
obj.name = 'huqinggui';//在给obj设置name属性的时候,触发了set这个方法
</script>
为什么vue3.0要用Proxy替代Object.defineProperty 实现双向数据绑定(待补充完善)
替换不是因为不好,是因为有更好的方法使用效率更高
那么到底为什么要用Proxy呢?既然想要替代了,说明一个有缺点,一个有优点的那么我们就来分析下他们的优缺点:
Object.defineProperty 的缺点:
总体上说致命的缺点是:
- 不能监听数组的变化
- 必须遍历对象的每个属性
- 必须深层遍历嵌套的对象
细分就是以下几点:
1.对IE11的兼容性(现在除了特殊的需求,基本上对IE都不考虑了)
2. 无法检测数组的变化
Object.defineProperty无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。 而且使用这些方法(push, pop, shift, unshift,splice, sort, reverse
…)是不能触发set的,Vue中能监听是因为对这些方法进行了重写
var a = {},
bValue = 1;
Object.defineProperty(a,"b",{
set: function(value){
bValue = value;
console.log("setted");
},
get: function(){
return bValue;
}
});
a.b = []; //setted
a.b = [1,2,3]; //setted
a.b[1] = 10; //无输出
a.b.push(4); //无输出
a.b.length = 5; //无输出
当a.b被设置为数组后,只要不是重新赋值一个新的数组对象,任何对数组内部的修改都不会触发setter方法的执行。所以要想实现实现数组的双向绑定,则必须通过Arr = newArr;这样的语句实现。同样常见的数组方法也不会触发,在框架中对这些方法进行了重写才能实现效果。
3.只能监听属性,而不是监听对象本身,需要对对象的每个属性进行遍历
对于原本不在对象中的属性难以监听。在Vue 2.x里,是通过 “callback + 遍历 data 对象” 来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择,而Proxy就显示了这方面的优势
4.当对象增删的时候,是监控不到的
比如:data = {a:"a"},这个时候如果我们设置data.test = "test",这个时候是监控不到的。因为在observe data的时候,会遍历已有的每个属性(比如a),添加getter/setter,而后面设置的test属性并没有机会设置getter/setter,所以检测不到变化。同样的,删除对象属性的时候,getter/setter会跟着属性一起被删除掉,拦截不到变化。
ES6中的Proxy的优点:
总的来说呢,Proxy是刚好解决了上述 Object.defineProperty 的缺点:
针对对象:针对整个对象,而不是对象的某个属性,所以也就不需要对 keys 进行遍历。
支持数组:Proxy 不需要对数组的方法进行重载,省去了众多 hack,减少代码量等于减少了维护成本,而且标准的就是最好的。
当然除此之外还有以下几个原因:
Proxy 的第二个参数可以有 13 种拦截方法,这比起 Object.defineProperty() 要更加丰富
Proxy 作为新标准受到浏览器厂商的重点关注和性能优化,相比之下 Object.defineProperty() 是一个已有的老方法。
vue中 key
值的作用 (v-for)
key 的特殊属性主要用在 Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes。如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。(有效的避免就地复用)
有相同父元素的子元素必须有独特的key。重复的key会造成渲染错误。
最常见的用例是结合 v-for:
<ul>
<li v-for="item in items" :key="item.id">...</li>
</ul>
它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:
完整地触发组件的生命周期钩子
触发过渡
<transition>
<span :key="text">{{ text }}</span>
</transition>
当 text 发生改变时,<span> 会随时被更新,因此会触发过渡。
vue中子组件调用父组件的方法
子组件调用父组件的方法可以使用this.$emit()
v-show
和v-if
指令的共同点和不同点?
v-show
指令是通过修改元素的display
CSS属性让其显示或者隐藏。
v-if
指令是直接销毁和重建DOM达到让元素显示和隐藏的效果(注意:v-if 可以实现组件的重新渲染),因此我们要尽量减少v-if的使用,因为它消耗性能。
如何让CSS只在当前组件中起作用?
将当前组件的<style>
修改为<style scoped>
,关键点在scoped,代表作用域,限制css的作用在当前组件。的作用是什么?
<keep-alive></keep-alive>的作用是什么?
<keep-alive></keep-alive>
包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
大白话: 比如有一个列表和一个详情,那么用户就会经常执行打开详情=>返回列表=>打开详情…这样的话列表和详情都是一个频率很高的页面,那么就可以对列表组件使用<keep-alive></keep-alive>
进行缓存,
这样用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新渲染 。
Vue中引入组件的步骤?
引入:
1.采用ES6的import ... from ...
语法
2.CommonJS的require()
方法引入组件
注册
Vue.component('my-component',
{ template: '<div>A custom component!</div>'})
3.使用组件<my-component></my-component>
指令v-el的作用是什么?
提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标.可以是 CSS 选择器,也可以是一个 HTMLElement 实例
在Vue中使用插件的步骤
1. 采用ES6的import ... from ...
语法
2. 使用全局方法Vue.use( plugin )
使用插件,可以传入一个选项对象 ,需要
Vue.use(MyPlugin, { someOption: true })
请列举出3个Vue中常用的生命周期钩子函数?
1.created: 实例已经创建完成之后调用,在这一步,实例已经完成数据观测, 属性和方法的运算, watch/event事件回调. 然而, 挂载阶段还没有开始, $el
属性目前还不可见
2. mounted: el
被新创建的 vm.$el
替换,并挂载到实例上去之后调用该钩子。如果 root
实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el
也在文档内
3. activated::keep-alive
组件激活时调用
请简述下Vuex的原理和使用方法
数据单向流动
一个应用可以看作是由上面三部分组成: View, Actions,State,数据的流动也是从View => Actions => State =>View 以此达到数据的单向流动.
但是项目较大的, 组件嵌套过多的时候, 多组件共享同一个State会在数据传递时出现很多问题.Vuex就是为了解决这些问题而产生的.
Vuex可以被看作项目中所有组件的数据中心,我们将所有组件中共享的State抽离出来,任何组件都可以访问和操作我们的数据中心
Vuex的组成:一个实例化的Vuex.Store由state, mutations和actions三个属性组成:
1.state中保存着共有数据
2.改变state中的数据有且只有通过mutations中的方法,且mutations中的方法必须是同步的
3.如果要写异步的方法,需要些在actions中, 并通过commit到mutations中进行state中数据的更改.
vue watch的高级用法--监听对象的属性变化
1.监听对象需要深度监听 ,如下代码可以监听整个msg对象的变化
watch: {
msg: {
handler(newValue, oldValue) {
console.log(newValue)
},
deep: true
}
}
2. 监听对象里面某个属性的变化,通过computed做中间层实现
computed: {
channel() {
return this.msg.channel
}
},
watch:{
channel(newValue, oldValue) {
console.log('new: %s, old: %s', newval, oldVal)
//这里面可以执行一旦监听的值发生变化你想做的操作
}
}
原文链接:https://www.cnblogs.com/h5hu/p/11234797.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- vue.js开发环境搭建教程 2020-03-16
- vue.js(5)--事件修饰符 2019-08-14
- vue.js(4)--字符串跑马灯 2019-08-14
- vue.js(3)--v-bind与v-on 2019-08-14
- vue.js(2)--v-cloak v-text v-html 2019-08-14
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash