vnode.js 2.2 KB
import { set, get } from '../utils';

// 注册函数式组件ref
export function registerRef(vnode, context) {
  if (!context.data.ref || !vnode.data.hook) {
    return vnode;
  }
  // 备份vnode原有的insert周期函数
  const hackInsert = vnode.data.hook.insert;
  // 新的vnode的insert周期函数
  vnode.data.hook.insert = function(config) {
    hackInsert(config);
    // 当vnode生成实例后,通过上下文反写入父组件的refs;
    context.parent.$refs[context.data.ref] = config.componentInstance || config.elm; // ref本身就有组件实例和dom节点两种情况,优先取实例
  };
  return vnode;
}

// 简写注册ref
export function ref(name, context) {
  const vnode = context._c(name, renderContext(context));
  return registerRef(vnode, context);
}

// 清除attrs上的数组和对象,仅用props传递
function clearAttrs(attrs) {
  const newAttrs = Object.assign({}, attrs);
  Object.keys(newAttrs).forEach(key => {
    if (typeof newAttrs[key] === 'function' || typeof newAttrs[key] === 'object') {
      delete newAttrs[key];
    }
  });
  delete newAttrs.slot;
  return newAttrs;
}

// 渲染函数式组件context
export function renderContext(context) {
  const result = {
    staticClass: context.data.staticClass,
    class: context.data.class,
    staticStyle: context.data.staticStyle,
    style: context.data.style,
    attrs: clearAttrs(context.data.attrs),
    props: context.props,
    on: context.listeners,
    directives: context.data.directives,
    scopedSlots: context.scopedSlots,
    slot: context.data.slot,
    key: context.data.key,
    ref: context.data.ref,
    refInFor: true,
  };
  return result;
}

// 设置默认渲染key
export function setDefaultContextKey(context, key) {
  const defaultKey = get(context, 'data.key');
  if (!defaultKey) {
    set(context, 'data.key', key);
  }
}

// 设置默认class
export function setDefaultContextClass(context, className) {
  const defaultClass = get(context, 'data.staticClass');
  if (!defaultClass) {
    set(context, 'data.staticClass', className);
  } else {
    set(context, 'data.staticClass', `${defaultClass} ${className}`);
  }
}

export default {
  registerRef,
  ref,
  setDefaultContextKey,
  setDefaultContextClass,
};