DEV Community

terrierscript
terrierscript

Posted on

5 2

How to replace mixin to slot in Vue.js

Mixin is one of Vue.js feature.

https://vuejs.org/v2/guide/mixins.html

This gives options common to multiple components.

React also had a mixin in the past, but it is now deprecated.

This reason is descripted in follow documents.

Summary is here.

  • Introduce implicit dependencies
  • Cause name clashes
  • Cause snowballing complexity

There also may apply on Vue.js.

How to replace mixin? Answer: slot.

In React, we can resolve this probrem with higher order components or functional children.

In Vue.js, we can replace mixin with slot.

In this article, I use mouse event tracking example.

First: Use mixin pattern.

Mixin example is here:

// mouseMixin.js
export default {
  data() {
    return {
      x: 0,
      y: 0
    };
  },
  methods: {
    mousemove(e) {
      this.x = e.clientX;
      this.y = e.clientY;
    }
  }
}

and Components example is here:

<!-- Item -->
<template>
  <div @mousemove="mousemove">
    <div>Item with mixin</div>
    <div>x: {{ x }}</div>
    <div>y: {{ y }}</div>
  </div>
</template>

<script>
import mouseMixin from "./mouseMixin"

export default {
  mixins: [ mouseMixin ],
};
</script>

Finally, components is called those:

<!-- Parent.vue -->
<template>
  <div>
    <Item />
  </div>
</template>

<script>
export default {
  components: {
    Item,
  }
};
</script>

In this example, some properties (x, y and mousemove) is implicit. It's not to easy to find those properties.

Next: Use slot

First, write mixin usage component:

<!-- Item.vue -->
<template>
  <div>
    <div>Item with scope</div>
    <div>x: {{ x }}</div>
    <div>y: {{ y }}</div>
  </div>
</template>

<script>
export default {
  props: {
    x: Number,
    y: Number
  }
};
</script>

This is very simple because got only x and y.

Next, we create MouseEvent component.
This got x and y from mousemove and pass to <slot>

<!-- MouseEvent.vue -->
<template>
  <div @mousemove="mousemove">
    <slot :x="x" :y="y"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      x: 0,
      y: 0
    };
  },
  methods: {
    mousemove(e) {
      this.x = e.clientX;
      this.y = e.clientY;
    }
  }
};
</script>

And last, combine <MouseEvent> and <Item> with slot-scope.

<!-- Parent.vue -->
<template>
  <div>
    <MouseEvent>
      <div slot-scope="{x, y}">
        <Item :x="x" :y="y" />
      </div>
    </MouseEvent>
  </div>
</template>

<script>
export default {
  components: {
    MouseEvent,
    Item,
  },
};
</script>

Okay, It's work.

We can replace slot from mixins. You can use this pattern when avoid mixins
But Vue.js scope is so redundancy. It's a little pain point

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more