Vue 源码阅读

文档:

目录

  • compile - render function (parserbi ani)
  • global-api - mixin
  • instance - lifecycle event
  • observer 响应
  • vdom virtual dom
  • util web weex server 服务端渲染
    • sfc 单文件,将Vue编译成js
构建

Runtime Only(webpack vue-loader .vue.js) Runtime compiler(运行时。课上)

vue源码

入口 :core/index

响应式原理

定义: 由于一些用户交互或者是其它方面导致数据发生变化重新对页面渲染

核心函数: Object.defineProperty(obj, prop, descriptor),obj 是要在其上定义属性的对象;prop 是要定义或修改的属性的名称;descriptor 是将被定义或修改的属性描述符。有getter 和setter代表它是响应式对象 MDN

observer对象源码定义

export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that have this object as root $data
}

getter: 依赖收集 setter:派发更新

【问题2提出】:

  • Vue 修改数组模板更新
  • Vue 修改对象模板不更新的原因

getter

  • 依赖收集
  • 触发条件
  • mountComponent,

【问题1提出】:

  • 修改哪块DOM
  • 修改效率和性能
  • 数据每一次修改是否都有去操作DOM

问题:

  • Vue computed 和 watch的区别
  • Vue v-model
  • 手写eventBus

问题1 计算属性 原理 计算属性:computed watcher - watcher depend 创建watcher,不会立刻求值,先new dep 求值时机:调用的时候,computedGetter 收集computed 依赖,多次计算,重新求值不相等才会notify, computedWatcher 侦听属性 this.$watch 属性 immediate: 立即执行 new watcher 时则会进行一次求值,userWatcher定义数据变化

  • 计算属性本质computed watcher
  • 侦听属性本质是user watcher,支持deep,sync,immediate
  • 计算属性适合用在模板渲染中,某个值依赖其他响应式对象或者计算属性而来,侦听属性适合侦听某个值变化完成复杂的业务逻辑

Vue router

手写一个vue-router 如何实现一个简单的vue router
至此,一个简单的 vue-router 就出来了,全部代码是这样的:
class VueRouter {
  constructor (Vue, options) {
    this.$options = options;
    this.routeMap = {};
    this.app = new Vue({
      data: {
        current: '#/'
      }
    });

    this.init();
    this.createRouteMap(this.$options);
    this.initComponent(Vue);
  }

  // 绑定事件
  init () {
    window.addEventListener('load', this.onHashChange.bind(this), false);
    window.addEventListener('hashchange', this.onHashChange.bind(this), false);
  }

  // 路由映射表
  createRouteMap (options) {
    options.routes.forEach(item => {
      this.routeMap[item.path] = item.component;
    });
  }

  // 注册组件
  initComponent (Vue) {
    Vue.component('router-link', {
      props: {
        to: String
      },
      template: '<a :href="to"><slot></slot></a>'
    });

    const _this = this;
    Vue.component('router-view', {
      render (h) {
        var component = _this.routeMap[_this.app.current];
        return h(component);
      }
    });
  }

  // 获取当前 hash 串
  getHash () {
    return window.location.hash.slice(1) || '/';
  }

  // 设置当前路径
  onHashChange () {
    this.app.current = this.getHash();
  }
}

响应式原理

一篇写得很好的文章:Vue源码解读一:Vue数据响应式原理