Search code examples
typescriptvue.jsvuetify.jsnpm-link

Vue.js : $attrs is readonly, $listeners is readonly


I tried to build my own component library implementing Vuetify, by using vue-cli vue create d-components. My components are registered through an install function exported in my lib's main.ts file such as:

import Vue, { VueConstructor } from 'vue';
import Vuetify from 'vuetify';
import DBtn from "./components/DBtn.vue";

Vue.use(Vuetify)

export default {
  install(vue: VueConstructor): void {
    vue.component("d-btn", DBtn);
    ...
  }
}

And a component is defined as:

<template>
  <v-btn v-bind="$attrs" v-on="$listeners" elevation="0" small>
    ...
  </v-btn>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";

@Component({})
export default class DBtn extends Vue {}
</script>

I added this library as a git submodule in my main Vue.js application (Which is also using Vuetify), ran npm install and npm link in the submodule's root folder, then ran npm link d-components in my main Application folder.

My application is importing & calling my library's install function via:

import Vue from 'vue';
import DComponents from "d-components" // library's name

Vue.use(DComponents);

Everything seems OK so far.

But when I try to use my library's components, I get a bunch of errors:

[Vue warn]: $attrs is readonly.

[Vue warn]: $listeners is readonly.

It seems that this one comes from the fact that two instances of Vue are created in my application, I searched to see if all my Vue imports were the same, and I can only find import Vue from 'vue' in both my main application and my library.

Does anyone know how to check if I'm creating several instances of Vue ?


Solution

  • Yes, the reason is duplicate Vue instance, and I think there should be warning about that in your console.

    The reason is your npm link done in submodule - which installs submobule package globally and all its dependencies including Vue. You can check node_modules directory of your globally installed submodule, you should see Vue there.

    So you have first Vue in node_modules of your project and second Vue in node_modules of your component (globally installed).

    The resolution is to use npm link ../component (not doing npm install in component dir) from your project directory either do npm publish for component and install it as a regular dependency for your project. That will not lead to install Vue into node_modules directory of your component.