Moon系列之Moon构造函数

前言

上一篇文章对入Moon整体结构进行了分析,基本了解了Moon代码结构组成,接下来的文章会对于Moon中各个部分的细节进行分析与了解,分析的版本是Moon的v0.9.0。

具体分析

首先通过了一个实例来看看Moon的实现效果,具体代码如下:

  <div id="app">
    <p>{{msg}}</p>
  </div>
  <script src="./moon.js"></script>
  <script>
    new Moon({
      el: '#app',
      data: {
        msg: 'hello world'
      }
    });
  </script>

上面是Moon中最基本的用法,接下来就分析下Moon中具体的处理。

Moon构造函数
 function Moon(opts) {
	  // Moon构造函数传入的options,即上例中{el: '#app', data: {msg: 'hello world'}}
      this.$opts = opts || {};
      var self = this;
      // 编号,此时id=0
      this.$id = id++;
      // 实例名称,上例中不存在name属性,故此为root
      this.$name = this.$opts.name || "root";
      // data属性
      this.$data = this.$opts.data || {};
      // render函数,上例中无render,故此为noop
      this.$render = this.$opts.render || noop;
      // hooks, 就是生命周期函数需写在hooks对象中
      this.$hooks = this.$opts.hooks || {};
      // methods属性是否存在,存在就会调用initMethods(顾名思义该方法是初始化方法的)
      var methods = this.$opts.methods;
      if (methods !== undefined) {
        initMethods(self, methods);
      }
      // 新增$events、$dom(虚拟DOM)属性
      this.$events = {};
      this.$dom = {};
      // 观察对象
      this.$observer = new Observer(this);
      this.$destroyed = true;
      this.$queued = false;
      // 计算属性computed是否存在,存在就调用initComputed初始化计算属性
      var computed = this.$opts.computed;
      if (computed !== undefined) {
        initComputed(this, computed);
      }
      // 初始化
      this.init();
    }

上面实例中不存在methods以及computed,所以主要的处理是observer对象的创建以及init方法的执行

Observer:观察对象构造函数
    function Observer(instance) {
	  // Moon实例,每个Moon实例都会存在一个Observer实例
      this.instance = instance;
      // 计算属性缓存对象
      this.cache = {};
      // 计算属性的setter
      this.setters = {};
      this.clear = {};
      this.target = null;
      // 依赖map
      this.map = {};
    }
init():初始化
	Moon.prototype.init = function () {
      log("======= Moon =======");
      // 调用callhook函数
      callHook(this, 'init');
	  // 如果el属性存在,就调用mount函数
      if (this.$opts.el !== undefined) {
        this.mount(this.$opts.el);
      }
    };
callHook函数
   var callHook = function (instance, name) {
	  // 查看hook对象中是否存在指定的生命周期方法,存在就调用该方法
      var hook = instance.$hooks[name];
      if (hook !== undefined) {
        hook.call(instance);
      }
    };
mount
    Moon.prototype.mount = function (el) {
      // 获取挂载点DOM对象
      this.$el = document.querySelector(el);
      this.$destroyed = false;
      // el不存在报错
      if ("development" !== "production" && this.$el === null) {
        error("Element " + this.$opts.el + " not found");
      }
    
      // 在$el中定义私有属性__moon__代表当前Moon实例
      this.$el.__moon__ = this;
      // 不存在模板,就会获取$el的标签及其包含的内容
      // 上面的实例中不存在template属性,所以此处是<div id="app"><p>{{msg}}</p></div>
      this.$template = this.$opts.template || this.$el.outerHTML;
      // 如果render是noop函数,表示是默认render函数,就会调用Moon.compile
      if (this.$render === noop) {
        this.$render = Moon.compile(this.$template);
      }
      // build函数,就是创建虚拟DOM并
      this.build();
      // mounted生命周期函数是否存在,存在就调用mounted
      callHook(this, 'mounted');
    };
Moon.compile
 Moon.compile = function (template) {
   // 调用compile函数,将template html转换成render函数
   return compile(template);
 };
build
  Moon.prototype.build = function () {
      // 调用render函数创建dom节点
      var dom = this.render();
      var old = null;
      // 如果存在实例的$dom不存在,old表示就是挂载点的DOM节点
      if (this.$dom.meta !== undefined) {
        old = this.$dom;
      } else {
        old = this.$el;
        this.$dom = dom;
      }
      // 调用patch函数
      this.patch(old, dom, this.$el.parentNode);
    };
render
    Moon.prototype.render = function () {
      // 实际上就是调用$render函数,创建虚拟DOM节点
      // h是Moon中定义的函数
      return this.$render(h);
    };

本篇旨在Moon构造函数的过程,此时只要知道render函数的作用即可,就是创建虚拟DOM,针对上面的实例,render函数的结果是:
虚拟DOM

从上面的结果中可以看到,render函数实际上是将不同类型的node都创建成指定格式的对象,现在只需要知道这个对象的组成属性有,具体后面会专门分析:

  • children:子节点对应的virtual dom
  • meta:元信息
  • props:属性
  • type:标签名
  • val:值
patch
   // 具体该函数的功能是处理虚拟DOM,将改变更新到真实DOM中
   Moon.prototype.patch = function (old, vnode, parent) {
    };

之后会针对虚拟DOM与真实DOM之间有个详细分析,本次具体去了解。

总结

Moon构造函数创建Moon实例添加的属性主要有:

  • $opts:参数对象
  • $id:id编号
  • $name:实例名称
  • $data:数据中心
  • $render:render函数,根据html转换成虚拟DOM
  • $hooks:生命周期对象
  • $dom:虚拟DOM对象

Moon构造函数的处理流程如下:

属性添加–>初始化所有方法—> 观察对象创建—>初始化计算属性---->生命周期函数init处理---->获取el挂载点DOM---->获取template---->根据template构建render函数–>根据render函数创建Virtual DOM---->Virtual DOM与真实DOM之间的处理—>调用mounted生命周期函数

在整个Moon创建的过程中,还有几处不甚明了:

  • methods的处理
  • computed的处理
  • Observer的监听机制

在下篇文章中会对于methods以及computed等相关做具体的分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值