Vue学习系列(一)——初识Vue.js核心
前言
vue.js是一套构建用户界面的渐进式框架,vue.js的目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。
vue通过DOM事件操作和指令来进行视图层和模型层的相互通讯,会为每一处需要动态更新的DOM节点创建一个指令对象。每当一个指令对象观测的数据变化时,它便会对所绑定的目标节点执行相应的DOM操作。基于指令的数据绑定使得具体的DOM操作都被合理地封装在指令定义中,业务代码只需要涉及模板和对数据状态的操作即可,这使得应用的开发效率和可维护性都大大提升。
因此,数据绑定,组件是整个vue的核心。响应的数据绑定就是数据驱动视图的概念。它让你在写 Web 应用介面时,只需要关注两件事:数据如何展示和数据如何变化。一旦数据发生变化时,比如用户输入,或者 ajax 请求返回后数据发现修改,对应的视图介面会自动的进行更新。
原理
vue.js是MVVM的架构,如图:
从图中可以看出视图层和模型层的相互传递,通过用户操作来绑定一些DOM事件来重新渲染到视图层。具体的内部架构如下图:
开始
一、 数据绑定:
实现方式:数据绑定即是视图层和模型层的双向绑定。即数据的改变驱动了视图的自动更新。
通过ViewModel控制,修改数据,从而控制View的展示,实现MVVM的思想。
里面的两个属性getter和setter,在这两个函数内部实现依赖的收集和触发,而且完美支持嵌套的对象结构。对于数组,则通过包裹数组的可变方法(比如push)来监听数组的变化。这使得操作Vue.js的数据和操作原生对象几乎没有差别。
- Obejct.defineProperty 【提供getter 和 setter】
- Observer 【提供getter 和 setter】—— 订阅者模式,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知,用来实时事件处理系统。
- watcher 【提供getter 和 setter】 —— 模板和
Observer
对象结合在一起的纽带 - Dep 【负责收集watcher】
- Directive 【处理Vue模板指令】
observe -> 触发setter -> watcher -> 触发update -> Directive -> 触发update -> 指令(如上图流程所示)
<span>Hello, this is {{name}}</span><script>var app = new Vue({ el : '#app', data : { name: 'i3yuan' } }) </script>
new Vue 执行时做了什么
function Vue(option) { var data = option.data this.data = data // 挂载 getter 和 setter observe(data, this) var id = option.el // 编译 模板 var dom = new Compile(document.querySelector(id), this) // 把编译好的模板挂载到 #app 上 document.querySelector(id).appendChild(dom) } //observe构造函数function observe(obj, vm) { Object.keys(obj).forEach(key => { defineReactive(vm, key, obj[key]) }) } //defineReactivefunction defineReactive(vm, key, val) { // 为每个变量分配一个 dep实例 var dep = new Dep() // 配置getter和setter并且挂载到vm上 Object.defineProperty(vm, key, { get() { if ( Dep.target ) { // JS的浏览器单线程特性, 保证整个全局变量在同一时间内, 只有一个监听器使用 dep.addSub(Dep.target) } return val }, set(newVal) { if ( newVal == val ) return; val = newVal; // 作为发布者发出通知 dep.notify() } }) } //Dep构造函数function Dep() { // 存放watcher this.subs = [] } Dep.prototype = { // 添加watcher, 也就是添加订阅 addSub(sub) { this.subs.push(sub) }, // 通知所有watcher notify() { this.subs.forEach(sub => { sub.update() }) } } function Compile(node, vm) { if(node) { this.$frag = this.nodeToFragment(node, vm) return this.$frag } } //watcher构造函数function Watcher(vm, node, name, type) {