Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there way to inherit templates with mixins in VueJS

Someone knows how inherit a mixin with its template? or how to inject dinamically elements or components from a mixin?

EDIT: I don't want to modify greeting component, I have two Mixins: 404Mixin that adds a method raise404() and show a 100% layer and LoaderMixin that have loading() method that shows a spinner in the corner. I can inherit their methods, but I have to duplicate the html in every component that I want to use it.

Thanks

mixin = {
  template: '<p>{{ foo }}</p>',
  data() {
    return {
      foo: 'Hello',
    };
  },
}

// This should  be <div><p>Hello</p><p>World!</p></div>
Vue.component('greeting', {
  mixins: [mixin],
  template: '<div><p>World!</p></div>'
});

var vm = new Vue({
  el: '#app'
});
<script src="https://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
<div id="app">
  <greeting></greeting>
</div>
like image 860
Ali Avatar asked Jul 09 '17 22:07

Ali


People also ask

What is the benefit of using Mixins in Vuejs?

Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component's own options.

What is $El in Vue?

The $el option in Vue provides Vue with an existing HTML element to mount the Vue instance generated using the new keyword. this. $el. querySelector is used to access HTML elements and modify the element's properties.


2 Answers

After years, I can imagine a elegant solution, and maybe it could be more elegant using classes, typescript or an annotation that create the component super in the mixin, but for now, the problem is partial solved.

GreetingMixin = {
  data() {
    return {
      greeting: 'Hello',
    };
  },
  provide() { return {child: this}},
  components: {
    super: {
      inject: ['child'],
      template: '<div class="blue">{{ child.greeting }} <strong><slot /></strong></div>',
    }
  },
}


// This should be <div class="blue">Hello <strong>World!</strong></div>
Vue.component('welcomeWorld', {
  mixins: [GreetingMixin],
  template: '<super>World!</super>',
});

// This should be <div class="blue">Hi <strong><i>ali</i></strong></div>
Vue.component('welcomeName', {
  mixins: [GreetingMixin],
  props: ["name"],
  created() { this.greeting = "Hi" },
  template: '<super><i>{{ name }}</i></super>',
});

// This should be <h1><div class="blue">Hello <strong>World</strong></div></h1>
Vue.component('welcomeH1', {
  mixins: [GreetingMixin],
  props: ["name"],
  template: '<h1><super>{{ name }}</super></h1>',
});


var vm = new Vue({
  el: '#app'
});
.blue {
color: blue
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <welcome-world></welcome-world>
  <welcome-name name="Ali"></welcome-name>
  <welcome-h1 name="Ali"></welcome-h1>
</div>
like image 149
Ali Avatar answered Oct 01 '22 17:10

Ali


You can't "inherit" mixin templates like in your example, if it were possible there would have to be a standardized way of merging the templates.

Since it seems all you really want to do is inherit the template, why not use component composition with slots?

Vue.component('not-found', {
  template: '#not-found',
  methods: {
    doSomethingSpecial() {
      alert('Hi there');
    },
  },
});

new Vue({
  el: '#app',
  data() {
    return {
      notFoundVisible: false,
    };
  },
});
.not-found {
  background-color: white;
  text-align: center;
  font-size: 30px;
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}
<script src="https://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>

<template id="not-found">
  <div class="not-found">
    <h1>404 Not Found</h1>
    <slot></slot>
  </div>
</template>

<div id="app">
  <not-found v-show="notFoundVisible" @click="notFoundVisible = false" v-ref:not-found>The resource was not found</not-found>
  <button @click="notFoundVisible = true">Click Me</button>
  <button @click="$refs.notFound.doSomethingSpecial()">Do Something Special</button>
</div>

Is there any particular reason why you need to mixin these components instead of composing them together?

like image 27
Decade Moon Avatar answered Oct 01 '22 18:10

Decade Moon