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

2.8k views Asked by At

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 ?

4

There are 4 answers

1
Andrey On BEST ANSWER

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.

1
Tachibana Shin On
$vuetify required package vuetify
0
Ninowis On

In my case the duplicated instances were caused by some Vue plugins importing the Vue instance differently than set in my project. I managed to fix it by adding the following to my Webpack config:

    externals: {
      // Stubs out `require('vue')` so it returns `global.Vue`
      vue: 'Vue',
    },

Hope it can help anyone struggling with the same issue :)

0
Carlos Rafael On

this happens when you import the vue several times inside your code. So, you need to specify the path.

if you are using vue 2.7 and vite, try to use this:

import path from 'path';

add in settings:

resolve: {
  alias: {
     vue: path.resolve(__dirname, './node_modules/vue/dist/vue.esm.js'),
  },
}