vue进阶之路(vue源码解析)死磕vue源码(二)

26 篇文章 0 订阅
10 篇文章 0 订阅

咱们书接上回,先来看看画重点的地方。

initRender(src/core/instance/render.js)

在前面是怎么个流程,可以出门左转看死磕源码一。
注意看源码先不要被细节缠住

export function initRender (vm: Component) {
  // 这有个问题 vm是谁? 前面initMixin时  vm = this
  // vm 就是实例对象喽
  vm._vnode = null        // 初始化 虚拟dom树(当前子组件)
  vm._staticTrees = null  // 缓存
  const options = vm.$options // 配置项
  // 父虚拟节点
  const parentVnode = vm.$vnode = options._parentVnode 
  // 渲染时上下文
  const renderContext = parentVnode && parentVnode.context
  // 插槽相关
  vm.$slots = resolveSlots(options._renderChildren, renderContext)
  vm.$scopedSlots = emptyObject
  // 当然上面这些细节 嘻嘻    重点来了
  vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
  vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)

  
  const parentData = parentVnode && parentVnode.data
  // 前面说过了 这种判断开发模式的代码可以先或略
  if (process.env.NODE_ENV !== 'production') {
    defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => {
      !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
    }, true)
    defineReactive(vm, '$listeners', options._parentListeners || emptyObject, () => {
      !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
    }, true)
  } else {
    defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, null, true)
    defineReactive(vm, '$listeners', options._parentListeners || emptyObject, null, true)
  }
}

createElement(src/core/vdom/create-element)

上面一段代码中的重点就是createElement顾名思义制造节点。
先把一些 ts的写法干掉, 把生产模式报警告的代码干掉
最后得到这段代码(拿源码对照着撸)

export function _createElement (context, tag, data, children, normalizationType) {
  // 首先看看 data 和 data.__ob__ 都存在的话 返回一个空的 vnode
  if (isDef(data) && isDef(data.__ob__)) {
    return createEmptyVNode()
  }
  // data和data.is都存在的话 就把data.is赋值给tag
  if (isDef(data) && isDef(data.is)) {
    tag = data.is
  }
  // tag不存在返回空的vnode
  if (!tag) {
    return createEmptyVNode()
  }
  // 若children[0]是function,则认为是scope slot而不是children
  if (Array.isArray(children) && typeof children[0] === 'function') {
    data = data || {}
    data.scopedSlots = { default: children[0] }
    children.length = 0
  }
  // 这里往下挖就又挖的特别深  记住是对子节点的处理就OK了
  // 是标签节点 或者 是文本节点之类的
  if (normalizationType === ALWAYS_NORMALIZE) {
    children = normalizeChildren(children)
  } else if (normalizationType === SIMPLE_NORMALIZE) {
    children = simpleNormalizeChildren(children)
  }
  // 根据不同的情况创建不同类型的VNode实例并返回
  let vnode, ns
  if (typeof tag === 'string') {
    let Ctor
    ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
    if (config.isReservedTag(tag)) {
      vnode = new VNode(
        config.parsePlatformTagName(tag), data, children,
        undefined, undefined, context
      )
    } else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
      vnode = createComponent(Ctor, data, context, children, tag)
    } else {
      vnode = new VNode(
        tag, data, children,
        undefined, undefined, context
      )
    }
  } else {
    vnode = createComponent(tag, data, context, children)
  }
  if (Array.isArray(vnode)) {
    return vnode
  } else if (isDef(vnode)) {
    if (isDef(ns)) applyNS(vnode, ns)
    if (isDef(data)) registerDeepBindings(data)
    return vnode
  } else {
    return createEmptyVNode()
  }
}

上面一样最显眼的就是 new VNode``````normalizeChildren simpleNormalizeChildren这几个个家伙空了接着撸。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值