Moon系列之slot以及指令相关

前言

上篇文章中分析了Moon中虚拟DOM的整个逻辑处理,它是Moon整个功能实现的核心,本篇的要说明的slot以及指令的处理都是在上篇文章分析的逻辑过程中,只是上篇文章没有突出说明具体的处理,本篇就是具体的说明Moon是如何处理slot以及指令的。

具体分析

还是通过实例来开始分析整个过程,具体实例代码如下:

  <div id="app">
    <p m-if="true">{{getToday}}</p>
    <mn-test>
      <p>{{today}}</p>
      <p slot="second">hello world</p>
    </mn-test>
  </div>
  <script src="./moon.js"></script>
  <script>
    debugger
    Moon.component('mn-test', {
      template: `<div>
        <slot></slot>
        <slot name="second"></slot>
        </div>`
    });
    new Moon({
      el: '#app',
      data: {
        today: Date.now()
      },
      computed: {
        getToday: {
          get() {
            var now = new Date(this.get('today'));
            return now.toLocaleString();
          }
        }
      }
    });
  </script>

上面的实例中涉及到了slot以及指令m-if。

  • 首先整个的过程还是如同虚拟DOM中的处理
  • 需要说明的是m-if在tokens中也是作为标签属性的存在,slot也是作为token中也是作为标签属性的存在
  • 在返回render的处理中,lex以及parse中的处理没有什么不同,主要的不同是在于generate中部分即渲染时的具体内容的替换。
generate中关于slot以及指令的处理

generate函数的逻辑处理如下:
这里写图片描述

在具体分析了generateEL函数的处理逻辑,关于slot以及指令的核心逻辑如下:

 var compiledCode = "";
 // 是否存在插槽slot
 if (vnode.type === "slot") {
    parentVNode.meta.shouldRender = true;
    parentVNode.deep = true;
    var slotNameAttr = vnode.props.attrs.name;
    compiledCode = 'instance.$slots[\'' + (slotNameAttr && slotNameAttr.value || "default") + '\']';
  } else {
    // 创建函数体
    compiledCode = createCall(vnode, parentVNode);
  }

  // 虚拟DOM是否存在指令相关的对象
  if (vnode.specialDirectivesAfter !== undefined) {
    for (var specialDirectiveAfterInfo in vnode.specialDirectivesAfter) {
    var specialDirectiveAfter = vnode.specialDirectivesAfter[specialDirectiveAfterInfo];
    compiledCode = specialDirectives[specialDirectiveAfter.name].afterGenerate(specialDirectiveAfter.value, specialDirectiveAfter.meta, compiledCode, vnode);
          }
        }

上面的代码就是generateEL中关于slot以及指令的处理。

上面就说过在lex中生成tokens,上面实例中m-if以及slot都是作为对应标签的属性的,所以就会在createCall中,slot的处理从上面可以直接看出,而对于指令的处理,就要具体分析了。

指令相关

if (vnode.specialDirectivesAfter !== undefined) {
    具体代码
}

需要判断虚拟DOM是否存在specialDirectivesAfter对象,通过具体的分析,该对象的添加是在createCall中对于属性的处理,相关处理代码如下:

var attrInfo = attrs[attr];
var specialDirective = null;
// 是否是Moon实例内置的指令
if ((specialDirective = specialDirectives[attrName]) !== undefined) {
  if (specialDirective.afterGenerate !== undefined) {
     // 添加specialDirectivesAfter对象
     if (vnode.specialDirectivesAfter === undefined) {
        vnode.specialDirectivesAfter = {};
     }
     // 指令相关赋值
     vnode.specialDirectivesAfter[attr] = attrInfo;
  }
  if (specialDirective.duringPropGenerate !== undefined) {
    generatedObject += specialDirective.duringPropGenerate(attrInfo.value, attrInfo.meta, vnode);
  }
  vnode.meta.shouldRender = true;
  delete attrs[attr];
} 

从上面的处理逻辑看出,Moon指令的具有特定的结构,下面就看看m-if的构成:

specialDirectives[Moon.config.prefix + "if"] = {
  afterGenerate: function (value, meta, code, vnode) {
    return '(' + compileTemplate(value, delimiters, escapedDelimiters, false) + ') ? ' + code + ' : h("#text", ' + generateMeta(defaultMetadata()) + ', "")';
      }
    };

具体看看compileTemplate的处理逻辑:
具体的处理

compileTemplate的处理结果是:

(true) ? h("p", {attrs: {}}, {"shouldRender": true, "eventListeners": {}}, [h("#text", {"shouldRender": true, "eventListeners": {}}, "" + instance.get("getToday") + "")]) : h("#text", {"shouldRender": false, "eventListeners": {}}, "")

compileTemplate函数还是根据不用的指令处理成不同的render的部分函数体。

对于其他指令,具体的处理我会详细注释,Moon内置的指令都是对象,对象拥有方法beforeGenerate、duringPropGenerate、afterGenerate,这些方法afterGenerate是在generate函数中处理,beforeGenerate和duringPropGenerate是在generateProps中处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值