一、Vue.js
1. Vue.js 是什么
Vue.js是一个轻巧、高性能、可组件化的MVVM库,拥有非常容易上手的API;
Vue.js是一个构建数据驱动的Web见面的库
官方解释:Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
2. Vue.js 的特性
- 轻量级的框架
- 双向数据绑定
- 指令
- 插件化(组件化)
2. MVVM 框架
- MVVM(Model-View-ViewModel)是对 MVC(Model-View-Control)和 MVP(Model-View-Presenter)的进一步改进。
[scode type=“blue”] 『View』:视图层(UI 用户界面) 『ViewModel』:业务逻辑层(一切 js 可视为业务逻辑) 『Model』:数据层(存储数据及对数据的处理如增删改查) [/scode]
MVVM 将数据双向绑定(data-binding)作为核心思想,View 和 Model 之间没有联系,它们通过 ViewModel 这个桥梁进行交互。
Model 和 ViewModel 之间的交互是双向的,因此 View 的变化会自动同步到 Model,而 Model 的变化也会立即反映到 View 上显示。
当用户操作 View,ViewModel 感知到变化,然后通知 Model 发生相应改变;反之当 Model 发生改变,ViewModel 也能感知到变化,使 View 作出相应更新。
3. 简述 Vue.js 的优点
- 低耦合。视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的 “View” 上,当 View 变化的时候 Model 可以不变,当 Model 变化的时候 View 也可以不变。
- 可重用性。你可以把一些视图逻辑放在一个 ViewModel 里面,让很多 View 重用这段视图逻辑。
- 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
- 方便测试。界面素来是比较难于测试的,开发中大部分 Bug 来至于逻辑处理,由于 ViewModel 分离了许多逻辑,可以对 ViewModel 构造单元测试。
- 易用 灵活 高效。
4. Vue中响应式数据的理解
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
然而他的缺点就很明显了;只能监控最外层的属性,如果是多层的,就要进行全量递归。get里面会做依赖搜集(dep[watcher, watcher]) set里面会做数据更新(notify,通知watcher更新)
5. Vue中如何检测数组对象的变化
[scode type=“blue”]由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。[/scode]
一、对于对象
Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应式的
vm.b = 2
// `vm.b` 是非响应式的
对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。
Vue.set(vm.someObject, 'b', 2)
您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:
this.$set(this.someObject,'b',2)
有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })` this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
二、对于数组
Vue 不能检测以下数组的变动:
当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // 不是响应性的 vm.items.length = 2 // 不是响应性的
为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue相同的效果,同时也将在响应式系统内触发状态更新:
// Vue.set Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:
vm.$set(vm.items, indexOfItem, newValue)
为了解决第二类问题,你可以使用 splice :
vm.items.splice(newLength)
push 向数组的末尾添加一个或更多元素,并返回新的长度。
let fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.push("Kiwi") //console.log(fruits) //["Banana", "Orange", "Apple", "Mango"]
shift 删除并返回数组的第一个元素。
let arr = [1,2,3,4,5]; let b = arr.shift(); console.log(b) // 1 //取出第一个元素 console.log(arr) //[2, 3, 4, 5] //取出第一元素后的数组
pop 删除数组的最后一个元素并返回删除的元素。
let arr = [1,2,3,4,5]; let b = arr. pop(); console.log(b) // 5 //取出第一个元素 console.log(arr) //[1,2, 3, 4] //取出最后一个元素后的数组
splice() 方法向/从数组添加/删除项目,并返回删除的项目。
let fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2, 0, "Lemon", "Kiwi"); //// 在位置 2,添加 2 个元素 console.log(fruits) //["Banana","Orange","Lemon","Kiwi","Apple","Mango"]
unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
let fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.unshift("Lemon","Pineapple"); console.log(fruits) //["Lemon","Pineapple","Banana","Orange",Apple,"Mango"]
sort 方法用于对数组的元素进行排序。
let fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits. sort(); console.log(fruits) //["Apple","Banana","Mango","Orange"]
reverse 方法用于颠倒数组中元素的顺序。
let fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.reverse(); console.log(fruits) //["Mango","Apple","Orange","Banana"]
因为这些方法都会改变数组本身。 数组里的索引和长度是无法被监控的。
5. Vue中如何进行依赖收集
Vue初始化的时候,挂载之后会进行编译。生成renderFunction。
当取值的时候,就会搜集watcher,放到dep里面。
当用户更改值的时候,就会通知watcher,去更新视图。
6.如何理解Vue中的模板编译原理
这个问题的核心是如何将template转换成render函数。
- 将template模块转换成ast语法书 - parserHTML
- 对静态语法做标记(某些节点不改变)
- 重新生成代码 - codeGen,使用with语法包裹字符串
7.Vue生命周期钩子是如何实现的
Vue的生命周期钩子是回调函数,当创建组件实例的过程中会调用相应的钩子方法。 内部会对钩子进行处理,将钩子函数维护成数组的形式。
8.Vue组件生命周期有哪些
- beforeCreate 在实例初始化之后,数据观测observer 和event、watcher事件配置之前被调用
- created 实例已经创建完成,在这一步,以下配置被完成
- 数据观测
- 属性和方法的运算
- watch/event时间回调
- $el尚未生成
- beforeMount 在挂载之前被调用,render尚未被调用
- mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用
- beforeUpdate 数据更新时,被调用,发生在虚拟Dom重新渲染和打补丁之前
- update 由于数据更改导致的虚拟Dom重新渲染和打补丁,在这之后调用
- beforeDestroy 实例销毁之前调用
- destroyed 实例销毁之后调用,调用后Vue实例的所有东西都会被解绑,所有的事件监听会被移除,子实例被销毁,该钩子在服务端渲染期间不被调用
- keep-alive(activated & deactivated
9.vue.mixin的使用场景和原理
Vue的mixin的作用就是抽离公共的业务逻辑,原理类似对象的继承,当组件初始化的时候,会调用mergeOptions方法进行合并,采用策略模式针对不同的属性进行合并。如果混入的数据和本身组件的数据有冲突,采用本身的数据为准。
缺点:命名冲突、数据来源不清晰
10.Vue的组件data为什么必须是一个函数
组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果
11. nextTick的原理
nextTick是一个微任务。
- nextTick中的回调是在下次Dom更新循环结束之后执行的延迟回调
- 可以用于获取更新后的Dom
- Vue中的数据更新是异步的,使用nextTick可以保证用户定义的逻辑在更新之后执行
未完待续……
「人生在世,留句话给我吧」