Skip to content

Synchronous updates don't work on $slots #66

Closed
@matt-oconnell

Description

@matt-oconnell

Version

1.0.0-beta

Steps to reproduce

Create a component that uses slots:

// SlotComponent.vue
<template>
  <div>
    <slot></slot>
  </div>
</template>

Use this component in some Parent.vue:

<template>
  <SlotComponent>
    <div :class="[{ 'is-on': on }, 'inner']"></div>
  </SlotComponent>
</template>

<script>
//...
export default {
  //...
  props: {
    on: {
      default: false,
      type: Boolean
    }
  },
  // ...
}
</script>

What is expected?

Setting props should synchronously update the template, but this test fails:

const parentWrapper = mount(Parent)
const innerEl = parentWrapper.find('.inner')

expect(innerEl.hasClass('is-on')).to.equal(false)

parentWrapper.setProps({
  on: true
})

expect(innerEl.hasClass('is-on')).to.equal(true)

What is actually happening?
nextTick is still required to update slot content.

Solution
Looks like Vue's vm._update function clones existing slots and does not update them unless the parent has updated. To fix this in our test we can trigger an update on our SlotComponent.vue:

parentWrapper.setProps({
  on: true
}) // calls parentWrapper.update

childWrapper = parentWrapper.find(SlotComponent)
childWrapper.update() // no nextTick required with this

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions