前言

    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) {