-
谈谈你对 MVVM 开发模式的了解
MVVM 分为 Model、View、ViewModel 三者。
Model:代表数据模型,数据和业务逻辑都在 Model 层中定义;
View:代表 UI 视图,负责数据的展现;
ViewModel:负责监听 Model 中数据的扭转并且管制视图的更新,解决用户交互操作;
Model 和 View 并无间接关联,而是通过 ViewModel 来进行分割的,Model 和 ViewModel 之间有着双向数据绑定的分割。因而当 Model 中的数据扭转时会触发 View 层的刷新,View 中因为用户交互操作而扭转的数据也会在 Model 中同步。
这种模式实现了 Model 和 View 的数据主动同步,因而开发者只须要专一对数据的保护操作即可,而不须要本人操作 dom。
-
v-if 和 v-show 有什么区别?
v-show 仅仅管制元素的显示方式,将 display 属性在 block 和 none 来回切换;而 v -if 会管制这个 DOM 节点的存在与否。当咱们须要常常切换某个元素的显示 / 暗藏时,应用 v -show 会更加节俭性能上的开销;当只须要一次显示或暗藏时,应用 v -if 更加正当。
-
简述 Vue 的响应式原理
Vue. js 采纳 ES5 提供的属性个性性能,联合发布者 - 订阅者模式,通过 Object.defineProperty()为各个属性定义 get、set 个性办法,在数据产生扭转时给订阅者公布音讯,触发相应的监听回调。
具体步骤如下。
(1)对须要察看的数据对象进行递归遍历,包含子属性对象的属性,设置 set 和 get 个性办法。当给这个对象的某个值赋值时,会触发绑定的 set 个性办法,于是就能监听到数据变动。
(2)用 compile 解析模板指令,将模板中的变量替换成数据。而后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,增加监听数据的订阅者。一旦数据有变动,就会收到告诉,并更新视图
(3)Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,次要性能如下。
在本身实例化时向属性订阅器(dep)外面增加本人。
本身必须有一个 update()办法。
在 dep.notice()公布告诉时,能调用本身的 updat()办法,并触发 Compile 中绑定的回调函数。
(4)MVVM 是数据绑定的入口,整合了 Observer、Compile 和 Watcher 三者,通过 Observer 来监听本人的 model 数据变动,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变动告诉视图更新的成果。利用视图交互,变动更新数据 model 变更的双向绑定成果。
4、请具体阐明你对 Vue.js 生命周期的了解。
总共分为 8 个阶段,别离为 beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroyed、destroyed。
beforeCreate:在实例初始化之后,数据观测者(data observer)和 event/ watcher 事件配置之前调用。
created:在实例创立实现后立刻调用。在这一步,实例已实现以下的配置:数据观测者,属性和办法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount:在挂载开始之前调用,相干的 render 函数首次调用。
mounted: el 被新创建的 vm.$el 替换,并且在挂载到实例上之后再调用该钩子如果 root 实例挂载了一个文档内元素,当调用 mounted 时 vm.sel 也在文档内。
beforeUpdate:在数据更新时调用,产生在虛拟 DOM 从新渲染和打补丁之前。
updated:因为数据更改导致的虚构 DOM 从新渲染和打补丁,在这之后会调用该钩。
beforeDestroy:在实例销毁之前调用。在这一步,实例依然齐全可用。
destroyed:在 Vue. js 实例销毀后调用。调用后,Vue. js 实例批示的所有货色都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
当应用组件的 kep- alive 性能时,减少以下两个周期。
activated 在 keep- alive 组件激活时调用;
deactivated 在 keep-live 组件停用时调用。
Vue2.5.0 版本新增了一个周期钩子:ErrorCaptured,当捕捉一个来自子孙组件的谬误时调用。
5、请具体阐明你对 Vue.js 生命周期的了解。
总共分为 8 个阶段,别离为 beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroyed、destroyed。
beforeCreate:在实例初始化之后,数据观测者(data observer)和 event/ watcher 事件配置之前调用。
created:在实例创立实现后立刻调用。在这一步,实例已实现以下的配置:数据观测者,属性和办法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount:在挂载开始之前调用,相干的 render 函数首次调用。
mounted: el 被新创建的 vm.$el 替换,并且在挂载到实例上之后再调用该钩子如果 root 实例挂载了一个文档内元素,当调用 mounted 时 vm.sel 也在文档内。
beforeUpdate:在数据更新时调用,产生在虛拟 DOM 从新渲染和打补丁之前。
updated:因为数据更改导致的虚构 DOM 从新渲染和打补丁,在这之后会调用该钩。
beforeDestroy:在实例销毁之前调用。在这一步,实例依然齐全可用。
destroyed:在 Vue. js 实例销毀后调用。调用后,Vue. js 实例批示的所有货色都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
当应用组件的 kep- alive 性能时,减少以下两个周期。
activated 在 keep- alive 组件激活时调用;
deactivated 在 keep-live 组件停用时调用。
Vue2.5.0 版本新增了一个周期钩子:ErrorCaptured,当捕捉一个来自子孙组件的谬误时调用。
6、请形容封装 Vue 组件的作用过程。
组件能够晋升整个我的项目的开发效率,可能把页面形象成多个绝对独立的模块,解决了传统我的项目开发中效率低、难保护、复用性等问题。
应用 Vue.extend 办法创立一个组件,应用 Vue.component 办法注册组件。子组件须要数据,能够在 props 中接收数据。而子组件批改妤数据后,若想把数据传递给父组件,能够采纳 emit 办法。
7、你是怎么意识 vuex 的?
vuex 能够了解为一种开发模式或框架。它是对 Vue. js 框架数据层面的扩大。通过状态(数据源)集中管理驱动组件的变动。利用的状态集中放在 store 中。扭转状态的形式是提交 mutations,这是个同步的事务。异步逻辑应该封装在 action 中。
8、Vue- loader 是什么?它的用处有哪些?
它是解析.vue 文件的一个加载器,能够将 template/js/style 转换成 JavaScript 模块。
用处是通过 vue-loader, JavaScript 能够写 EMAScript 6 语法,style 款式能够利用 scss 或 less, template 能够增加 jade 语法等。
9、请说出 vue.cli 我的项目的 src 目录中每个文件夹和文件的用法。
assets 文件夹寄存动态资源;components 寄存组件;router 定义路由相干的配置;view 是视图;app. vue 是一个利用主组件;main.js 是入口文件。
10、在 Vue.cli 中怎么应用自定义组件?在应用过程中你遇到过哪些问题?
具体步骤如下。
(1)在 components 目录中新建组件文件,脚本肯定要导出裸露的接口。
(2)导入须要用到的页面(组件)。
(3)将导入的组件注入 uejs 的子组件的 components 属性中。
(4)在 template 的视图中应用自定义组件。
11、谈谈你对 vue.js 的 template 编译的了解。
简而言之,就是首先转化成 AST(Abstract Syntax Tree,形象语法树),行将源代码语法结构形象成树状表现形式,而后通过 render 函数进行渲染,并返回 VNode(Vue. js 的虚构 DOM 节点)。
具体步骤如下。
(1)通过 compile 编译器把 template 编译成 AST, compile 是 create Compiler 的返回值,createCompiler 用来创立编译器。另外,compile 还负责合并 option。
(2)AST 会通过 generate(将 AST 转化成 render funtion 字符串的过程)失去 render 函数,render 的返回值是 VNode, VNode 是 Vue.Js 的虚构 DOM 节点,外面有标签名子节点、文本等。
12、如何让 CSS 只在以后组件中起作用?
在每一个 Vue.js 组件中都能够定义各自的 CSS、JavaScript 代码。如果心愿组件内写的 CSS 只对以后组件起作用,只须要在 Style 标签增加 Scoped 属性,即 <style scoped></style>。
13、如何检测数据变动?
因为 JavaScript 个性的限度,Vue. js 不能检测到上面数组的变动,即以下数组中扭转的数据“失落”了。
通过间接索引设置元素,如 app.arr[0]=…
批改数据的长度,如 app. arr.length。
为了解决该问题,Vue.js 扩大了察看数组,为它增加了一个 $set()办法,用该办法批改的数组,能触发视图更新,检测数据变动。
app.$set(app. arr, 5,500);
14、如何检测对象变动?
因为 JavaScript 个性的限度,Vue.js 不能检测到对象属性的增加或删除。因为 Vue.js 在初始化时将属性转化为 getter/setter,所以属性必须在 data 对象中定义,能力在初始化时让 Vue.js 转换它并让它响应,例如以下代码
var data ={
obj:{
a:1
}
}
var app= new Vue ({
el:’#app ‘,
data:data
})
app.obj.a=10
// ‘app.obj.a’ 和 ’data.obj.a’ 当初是响应的
app. obj. b=2
//’app.obj.b’ 不是响应的
data.obj.b=2
//data.obj.b’ 不是响应的
如果须要在实例创立之后增加属性并且让它可能响应,能够应用 $set 实例办法。
app.$set(app.obj,’b’,500)
// ‘app.obj.b’ 和 ’data.obj.b’ 当初是响应的
对于一般数据对象,能够应用全局办法 Vue.set(object,key, value)。
Vue.set(data.obj,”b’,500)
//’app.obj.b’ 和 ’cata,obj.b’ 当初是响应的
15、说一下 Vue.js 页面闪动{{message}}。
Vue. js 提供了一个 v - cloak 指令,该指令始终放弃在元素上,直到关联实例完结编译。当和 CSS 一起应用时,这个指令能够暗藏未编译的标签,直到实例编译完结。用法如下。
[v-cloak]{
display:none;
}
<div v-cloak> {{ title} }</div>
这样 <div> 不会显示,直到编译完结。
16、如何解决数据层级构造太深的问题?
在开发业务时,常常会岀现异步获取数据的状况,有时数据档次比拟深,如以下代码。
<span ‘v-text=”a.b.c.d”></span>
能够应用 vm.$set 手动定义一层数据。
vm.$set (“demo”,a .b.c.d)
17、Vue3.x 响应式数据原理
Vue3.x 改用 Proxy 代替 Object.defineProperty。
因为 Proxy 能够间接监听对象和数组的变动,并且有多达 13 种拦挡办法。并且作为新规范将受到浏览器厂商重点继续的性能优化。
Proxy 只会代理对象的第一层,Vue3 是怎么解决这个问题的呢?
判断以后 Reflect.get 的返回值是否为 Object,如果是则再通过 reactive 办法做代理,这样就实现了深度观测。
监测数组的时候可能触发屡次 get/set,那么如何避免触发屡次呢?咱们能够判断 key 是否为以后被代理对象 target 本身属性,也能够判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行 trigger。
18、Vue3.0 里为什么要用 Proxy API 代替 defineProperty API?
1.defineProperty API 的局限性最大起因是它只能针对单例属性做监听。
Vue2.x 中的响应式实现正是基于 defineProperty 中的 descriptor,对 data 中的属性做了遍历 + 递归,为每个属性设置了 getter、setter。这也就是为什么 Vue 只能对 data 中预约义过的属性做出响应的起因。
2.Proxy API 的监听是针对一个对象的,那么对这个对象的所有操作会进入监听操作,这就齐全能够代理所有属性,将会带来很大的性能晋升和更优的代码。
Proxy 能够了解成,在指标对象之前架设一层“拦挡”,外界对该对象的拜访,都必须先通过这层拦挡,因而提供了一种机制,能够对外界的拜访进行过滤和改写。
3. 响应式是惰性的。
在 Vue.js 2.x 中,对于一个深层属性嵌套的对象,要劫持它外部深层次的变动,就须要递归遍历这个对象,执行 Object.defineProperty 把每一层对象数据都变成响应式的,这无疑会有很大的性能耗费。
在 Vue.js 3.0 中,应用 Proxy API 并不能监听到对象外部深层次的属性变动,因而它的解决形式是在 getter 中去递归响应式,这样的益处是真正拜访到的外部属性才会变成响应式,简略的能够说是按需实现响应式,缩小性能耗费。
19、Proxy 与 Object.defineProperty 优劣比照
1.Proxy 能够间接监听对象而非属性;
2.Proxy 能够间接监听数组的变动;
3.Proxy 有多达 13 种拦挡办法, 不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
4.Proxy 返回的是一个新对象, 咱们能够只操作新的对象达到目标, 而 Object.defineProperty 只能遍历对象属性间接批改;
5.Proxy 作为新规范将受到浏览器厂商重点继续的性能优化,也就是传说中的新规范的性能红利;
6.Object.defineProperty 的劣势如下:
兼容性好,反对 IE9,而 Proxy 的存在浏览器兼容性问题, 而且无奈用 polyfill 磨平,因而 Vue 的作者才申明须要等到下个大版本 (3.0) 能力用 Proxy 重写。
vue 中组件的 data 为什么是一个函数?而 new Vue 实例里,data 能够间接是一个对象
咱们晓得,Vue 组件其实就是一个 Vue 实例。
JS 中的实例是通过构造函数来创立的,每个构造函数能够 new 出很多个实例,那么每个实例都会继承原型上的办法或属性。
Vue 的 data 数据其实是 Vue 原型上的属性,数据存在于内存当中。Vue 为了保障每个实例上的 data 数据的独立性,规定了必须应用函数,而不是对象。
因为应用对象的话,每个实例(组件)上应用的 data 数据是相互影响的,这当然就不是咱们想要的了。对象是对于内存地址的援用,间接定义个对象的话组件之间都会应用这个对象,这样会造成组件之间数据相互影响。
应用函数后,应用的是 data()函数,data()函数中的 this 指向的是以后实例自身,就不会相互影响了。
而 new Vue 的实例,是不会被复用的,因而不存在援用对象的问题。
20. 单页面利用和多页面利用区别及优缺点
答:单页面利用(SPA),艰深一点说就是指只有一个主页面的利用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都蕴含在这个所谓的主页面中。但在写的时候,还是会离开写(页面片段),而后在交互的时候由路由程序动静载入,单页面的页面跳转,仅刷新部分资源。多利用于 pc 端。
多页面(MPA),就是指一个利用中有多个页面,页面跳转时是整页刷新
单页面的长处:用户体验好,快,内容的扭转不须要从新加载整个页面,基于这一点 spa 对服务器压力较小;前后端拆散;页面成果会比拟炫酷(比方切换页面内容时的专场动画)。
单页面毛病:不利于 seo;导航不可用,如果肯定要导航须要自行实现后退、后退。(因为是单页面不能用浏览器的后退后退性能,所以须要本人建设堆栈治理);首次加载时耗时多;页面复杂度进步很多。