Home » vue » Attach global to Vue instance

Attach global to Vue instance

Posted by: admin November 26, 2021 Leave a comment

Questions:

How can I attach global filters/mixins/and more to a defined Vue Instance instead of the Vue object?

Example

import Vue from 'vue.js'
import App from './app'
import demo from './mixins/demo'

Vue.mixin(demo)

const vm = new Vue({
  router,
  render: h => h(App).$mount('#app')
})

How to attach this mixin to vm instead of the Vue object in the case where I have multiple instances?

I tried vm.mixin(demo) but It doesn’t seem to work

Answers:

Your question is not that clear but I feel what you want is to have multiple Vue root instances on the page each with it’s own set of global mixins/directives/filters etc.

Unfortunately Vue 2 was not designed in a way to make this easy. Great read on this is Global API section of Vue3 migration guide (citations):

Vue 2.x has a number of global APIs and configurations that globally mutate Vue’s behavior.

While this approach is convenient, it leads to a couple of problems. Technically, Vue 2 doesn’t have a concept of an "app". What we define as an app is simply a root Vue instance created via new Vue(). Every root instance created from the same Vue constructor shares the same global configuration. As a result:

Global configuration makes it difficult to share the same copy of Vue between multiple "apps" on the same page, but with different global configurations

This is a problem mainly (but not exclusively) during the testing. To fix it, they introduced createLocalVue() method in vue-test-utils, which uses Vue.extend global API to create a "subclass" of base Vue constructor…

So I’v used the same approach to create an example below which shows 2 different Vue subclasses each with it’s own set of global mixins and components. It sort of works but has it’s quirks (for example take a look how components are registered – leaving out MyVue1.extend call breaks the code)

My take from this exercise is that it can be done with Vue 2 but it can be a bumpy road and probably best solution is to use Vue 3 where those problems were solved properly…

const MyVue1 = Vue.extend()
const MyVue2 = Vue.extend()

MyVue1.mixin({
  methods: {
    mixinMethod: function() {
      return 'MyVue1'
    }
  }
})

MyVue1.component('my-component1', MyVue1.extend({
  template: '<div> Hello from my-component1: {{ mixinMethod() }} !</div>'
}))

MyVue2.mixin({
  methods: {
    mixinMethod: function() {
      return 'MyVue2'
    }
  }
})

MyVue2.component('my-component2', MyVue2.extend({
  template: '<div> Hello from my-component2: {{ mixinMethod() }} !</div>'
}))

const vm1 = new MyVue1({
  template: '<my-component1 />',
}).$mount('#app1')

const vm2 = new MyVue2({
  template: '<my-component2 />',
}).$mount('#app2')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app1"></div>
<div id="app2"></div>

###

Did you try it?

import fooMixin from './mixins/fooMixin'
import barMixin from './mixins/barMixin'

const vm1 = new Vue({
  router,
  mixins: [fooMixin]
  render: h => h(App).$mount('#app1')
})

const vm2 = new Vue({
  router,
  mixins: [barMixin]
  render: h => h(App).$mount('#app2')
})