Vue插槽穿透的几种姿势

用render函数开发高阶组件时经常会向下传递插槽,reat使用的是children异常方便,和Vue的插槽(静态插槽、作用域插槽)使用类似。

插槽穿透,大概有三种方式:


// 1.在子组件访问父级插槽
console.log(this.$parent.$slots)
console.log(this.$parent.$scopedSlots)
// 2. 分别传递静态,作用域插槽
render(h) {
  console.log(this.$slots)
  return h('render-com', {
    scopedSlots: {
      // 传递作用于插槽
      default: props => h('span', props.text)
    }
  }, [...Object.keys(this.$slots).map(slotName => this.$slots[slotName])]
  )
}
// 3.同时传递静态插槽和作用域插槽
render(h) {
  const slots = Object.keys(this.$slots).map(slotName =>
    this._t(slotName, null, { slot: slotName })
  )
  return h('render-com', {
  }, slots
  )
}
复制代码

注意第三种方式中的this._t函数,大名是renderSlot,如果是普通插槽,就直接调用函数生成 vnode,如果是作用域插槽,就直接带着 props 去调用函数生成 vnode。Vue 2.6 版本后对 slot 和 slot-scope 做了一次统一的整合,让它们全部都变为函数的形式,所有的插槽都可以在 this.$scopedSlots 上直接访问。

renderSlot函数

/**
 * Runtime helper for rendering <slot>
 */
function renderSlot (
  name,
  fallback,
  props,
  bindObject
) {
  var scopedSlotFn = this.$scopedSlots[name];
  var nodes;
  if (scopedSlotFn) { // scoped slot
    props = props || {};
    if (bindObject) {
      if (process.env.NODE_ENV !== 'production' && !isObject(bindObject)) {
        warn(
          'slot v-bind without argument expects an Object',
          this
        );
      }
      props = extend(extend({}, bindObject), props);
    }
    nodes = scopedSlotFn(props) || fallback;
  } else {
    nodes = this.$slots[name] || fallback;
  }

  var target = props && props.slot;
  if (target) {
    return this.$createElement('template', { slot: target }, nodes)
  } else {
    return nodes
  }
}


复制代码

关于Vue 中 slot 和 slot-scope 的原理,参考大神文章:juejin.cn/post/684490…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享