Search code examples
vue.jsvuejs2vue-componentvue-render-function

Vue render function - non-scoped slot


The docs for the render function give an example of how to convert a scoped v-slot from a template

<div><child v-slot="props"><span>{{ props.text }}</span></child></div>

to a render function:

render: function (createElement) {
  return createElement('div', [
    createElement('child', {
      // pass `scopedSlots` in the data object
      // in the form of { name: props => VNode | Array<VNode> }
      scopedSlots: {
        default: function (props) {
          return createElement('span', props.text)
        }
      }
    })
  ])
}

However, what if the v-slot is not scoped? What if the template you were trying to convert was instead like

<div><child v-slot:slotName><span>...</span></child></div>

(where I've also used a non-default slot named slotName)


Solution

  • That depends on the Vue 2 version. Since 2.6.0+, Vue treats all slots the same, exposing them on scopedSlots no matter whether they are scoped or not.

    All $slots are now also exposed on $scopedSlots as functions. If you work with render functions, it is now recommended to always access slots via $scopedSlots, whether they currently use a scope or not. This will not only make future refactors to add a scope simpler, but also ease your eventual migration to Vue 3, where all slots will be functions.

    So this should work:

    render: function (createElement) {
      return createElement('div', [
        createElement('child', {
          // pass `scopedSlots` in the data object
          // in the form of { name: props => VNode | Array<VNode> }
          scopedSlots: {
            slotName: function (props) {  // or function ()
              return createElement('span', props.text)
            }
          }
        })
      ])
    }
    

    Demo