vue 源码解析

这几天看了一些vue 的相关源码,小结一下。

vue工作机制

在这里插入图片描述

vue 响应式的原理defineProperty

class KVue {
  constructor(options) {
    this._data = options.data;
    this.observer(this._data);
  }
  observer(value) {
    if (!value || typeof value !== "object") {
return; }
    Object.keys(value).forEach(key => {
      this.defineReactive(value, key, value[key]);
}); }
  defineReactive(obj, key, val) {
    Object.defineProperty(obj, key, {
enumerable: true /* 属性可枚举 */, configurable: true /* 属性可被修改或删除 */, get() {
        return val;
      },
      set(newVal) {
        if (newVal === val) return;
        this.cb(newVal);
} });
}
cb(val) { console.log("更新数据了", val);
} }
let o = new KVue({
  data: {
    test: "I am test."
  }
});
o._data.test = "hello,kaikeba";
	 

依赖收集与追踪

new Vue({
	template:
		`<div>
			<span>{{text1}}</span>
			<span>{{text2}}</span>
		</div>`
	data: {
		text1: 'name1'
	},
	created () {
	 	this.text1 = 'come on'
	}
})

text1 被修改,所以视图更新,但是text2视图没有用到,这里就用到了依赖收集

// 依赖收集小朋友 class Dep {
constructor () {
// 存数所有的依赖
        this.deps = []
    }
// 在deps中添加一个监听器对象 addDep (dep) {
        this.deps.push(dep)
    }
// 通知所有监听器去更新视图 notify () {
        this.deps.forEach((dep) => {
            dep.update()
}) }
}
class Watcher {
    constructor () {
// 在new一个监听器对象时将该对象赋值给Dep.target,在get中会用到
        Dep.target = this
    }
// 更新视图的方法 update () {
console.log("视图更新啦~") }
}

在这里插入图片描述
我们在增加了一个Dep类的对象,用来收集Watcher对象。数据的时候,会触发reactiveGetter函数把当前的Watcher对象存放在Dep.target中,收集到Dep类中去。
数据的时候,则会触发reactiveGetter方法,通知Dep类调用notify来触发所有watcher对象的update方法更新对应视图

constructor(options) {
  this._data = options.data
  this.observer(this._data)
// 新建一个Watcher观察者对象,这时候Dep.target会指向这个Watcher对象 new Watcher();
// 在这里模拟render的过程,为了触发test属性的get函数 console.log('模拟render,触发test的getter', this._data.test);
}
defineReactive(obj, key, val) {
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
// 将Dep.target(即当前的Watcher对象存入Dep的deps中) dep.addDep(Dep.target)
return val
    },
    set: function reactiveSetter(newVal) {
if (newVal === val) return
// 在set的时候触发dep的notify来通知所有的Watcher对象更新视图
   dep.notify()
    }
}) }

编译complie
核心逻辑 获取dom,遍历dom,获取{{}}, h- 和@开头的,设置响应式
在这里插入图片描述

  // 编译过程
  compile(el) {
    const childNodes = el.childNodes;
    Array.from(childNodes).forEach(node => {
      // 类型判断
      if (this.isElement(node)) {
        // 元素
        // console.log('编译元素'+node.nodeName);
        // 查找k-,@,:
        const nodeAttrs = node.attributes;
        Array.from(nodeAttrs).forEach(attr => {
          const attrName = attr.name; //属性名
          const exp = attr.value; // 属性值
          if (this.isDirective(attrName)) {
            // k-text
            const dir = attrName.substring(2);
            // 执行指令
            this[dir] && this[dir](node, this.$vm, exp);
          }
          if (this.isEvent(attrName)) {
            const dir = attrName.substring(1); // @click
            this.eventHandler(node, this.$vm, exp, dir);
          }
        });
      } else if (this.isInterpolation(node)) {
        // 文本
        // console.log('编译文本'+node.textContent);
        this.compileText(node);
      }

      // 递归子节点
      if (node.childNodes && node.childNodes.length > 0) {
        this.compile(node);
      }
    });
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值