RouterLink attrs is readonly - javascript

I'm starting with VueRouter in Vue.js and I'm getting this errors:
[Vue warn]: $attrs is readonly.
found in
---> <RouterLink>
<SecondNav> at resources\assets\js\modules\livegame\player\SecondNav.vue
<Player> at resources\assets\js\modules\livegame\player\Player.vue
<Root>
[Vue warn]: $listeners is readonly.
found in
---> <RouterLink>
<SecondNav> at resources\assets\js\modules\livegame\player\SecondNav.vue
<Player> at resources\assets\js\modules\livegame\player\Player.vue
<Root>
I have reduced everything I could and the result is that problem is only in router. I did it according docs and I don't have any idea where is problem. Here are my components:
SecondNav.vue
<template>
<div class="row second-top-nav">
<div class="col-md-offset-1 col-md-11">
<ul class="nav">
<li>
<router-link to='/public/livegame/player/history'>
History
</router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {}
</script>
Player.vue
<template>
<div>
<second-nav></second-nav>
</div>
</template>
<script>
import SecondNav from './SecondNav';
export default {
components: {
SecondNav
},
}
</script>
router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import History from './history/History';
export default new VueRouter({
mode: 'history',
routes: [
{path: '/public/livegame/player/history', component: History, name: 'player_history'},
],
linkActiveClass: "active", // active class for non-exact links.
});
Start point player.js
window.Event = new Vue();
import Vue from 'vue';
import router from './router'
import Player from './Player.vue';
let vm = new Vue({
el: '#player',
router,
components: {
Player
},
});
window.vm = vm;
I don't know where is problem or what I'm doing wrong. Everything in application seems to work without problem but these notifications doesn't look that all is right. I'm using Vue.js version 2.5.16 and VueRouter version 3.0.1.

Having multiple Vue instances can lead to this problem...
I fixed this warning: Vue warn $attrs is readonly. found in ...
by removing line: import Vue from 'vue'
while keeping: import VueRouter from 'vue-router'
Reason why it fixed: vue was being loaded twice. Vue is imported at the top of VueRouter. There's no need to import it before VueRouter.

Having multiple Vue instances can lead to this problem. In your player.js file you do you
window.Event = new Vue();
then immediately after:
let vm = new Vue({ ... })
Try removing the first new Vue, that should help. Since you are registering the router globally by calling Vue.use(VueRouter) you have two vue instances, both with their own router. When the second instance mounts and tries to register the router, since the first instance already did so, you get the readonly error.
Also import instances are hoisted to the top of the file, so although you declare window.Event = new Vue at the top, realistically the import instances are occurring before any variable declaration and assignment.

Related

Vue 3 - "Failed to resolve component" with global components

My Vue components work fine when declared in the top level HTML file, like this
<body>
<div class='app' id='app'>
<header-bar id='headerBar'></header-bar>
<journal-page></journal-page>
</div>
<script src="js/app.js"></script>
</body>
but using a <journal-card> component inside the <journal-page> component gives me the error:
[Vue warn]: Failed to resolve component: journal-card at <JournalPage>.
How do I fix this please?
Here's my top level code that loads the Vue components, app.js:
import * as _vue from 'vue';
import _headerBar from './widgets/headerBar.vue';
import _journalCard from './widgets/journalCard.vue';
import _journalPage from './widgets/journalPage.vue';
import _store from './data/store.js';
const app = _vue.createApp
({
components:
{
'headerBar': _headerBar,
'journalCard': _journalCard,
'journalPage': _journalPage
},
data : _store,
methods: {}
});
const mountedApp = app.mount('#app');
and here's my journal-page.vue container
<template>
<ul>
<journal-card v-for="item in journal" :key="item.id" :entry=item></journal-card>
</ul>
</template>
<script lang="js">
import _store from '../data/store.js';
export default {
'data': _store
};
</script>
and journal-card.vue component
<template>
<div>
hi imma journal entry
</div>
</template>
<script lang="js">
export default {
'data': null,
'props': [ 'entry' ]
};
</script>
Registering components in the root component's components option doesn't make them global. Doing that just makes them available to the root component itself, not its children.
To register components globally, use app.component in your top-level code:
main.js
import { createApp } from 'vue';
import App from './App.vue';
import MyGlobalComponent from './components/MyGlobalComponent.vue';
const app = createApp(App);
app.component('MyGlobalComponent', MyGlobalComponent); ✅
const mountedApp = app.mount('#app');
In my scenario issue was different. I was trying to render a similar multi word Vue component in a laravel blade file.
If you're referring a Vue component in a non .Vue file (like HTML / Laravel Blade etc), you should use kebab-cased format to refer the component name. Like my-global-component
Vue documentation - https://vuejs.org/guide/essentials/component-basics.html#dom-template-parsing-caveats
Also as a side note since this page shows up when looking in search engines for some problems with "Vue 3 Failed to resolve component", there are a few things that were deprecated with Vue 3 / Quasar 2:
eg. q-side-link
that silently disappeared (previous doc here)
as per this comment:
QSideLink -- no longer required! Simply use a QItem or whatever
component you want and bind an #click="$router.push(...)" to it.
Sorry if it's not exactly on topic but it will bite some other people, so I prefer to help one person with this comment ;-)
make sure the mounting code comes at last so
app.mount('#app')
app.component('list-view', ListView2)
is wrong and it will not work but
app.component('list-view', ListView2)
app.mount('#app')
is correct.

How to register global Vue components in Storybook?

Is there a way to register global Vue components in Storybook so it is compatible with globally registered Vue components in Vue-CLI?
You just need to add a few lines to .storybook/preview.js file.
Vue.js 3
import {app} from '#storybook/vue3';
app.component('router-link', MockRouterLink);
Vue.js 2
import Vue from 'vue';
Vue.component('router-link', MockRouterLink);
But I haven't tested the latter one because I only use Storybook with Vue.js 3 apps.
You can just use these lines in preview.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
Vue.component('router-link', Vue.component('RouterLink'));
export const decorators = [(story) => ({
components: {story},
template: '<story />',
router: new VueRouter()
})];
My vue-router problem is solved by this

Getting undefined when trying to read vuex state

Following a simple example in VueMaster course and can't seem to read state from the store. Here's my main.js:
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
import App from './App.vue'
import router from './router'
import store from './store'
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
And here's my index.js in the /store folder:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
user: { id: 'abc123', name: 'Adam Jahr' },
},
mutations: {},
actions: {},
modules: {}
})
Then, I try and read the state object from a component:
<template>
<div>
<h1>Create an Event, {{ $store.state.user.name }}</h1>
</div>
</template>
I don't see anything in the browser for the component. Console shows an error "TypeError: Cannot read property 'name' of undefined".
Any idea why this very simple example doesn't work? Thanks.
Shouldn't your import look like this:
import store from './store/index'
since that is where you are creating your store, check the folder structure, maybe that is the problem.
I didn't see any problem with your code, it's working as expected.
Here is sandbox link - https://codesandbox.io/s/silly-poitras-sosvs?file=/src/App.vue
You need to provide the store in your component
Something in computed like
return this.$store.state.user

global definition does not work in vue.js

I have tried to import and define a library globally as below, but somehow it does not recognize the global variable.
in main.js,
import Vue from 'vue'
import App from './App'
import router from './router'
import VueJwtDecode from 'vue-jwt-decode'
Vue.config.productionTip = false
Vue.use(VueJwtDecode)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
in Signup.vue,
...
const payload = VueJwtDecode.decode(res.jwt);
...
and the error shows that VueJwtDecode is not defined.
If you are trying to use the named reference of VueJwtDecode, you need to reimport the library in your Signup.vue compoenent since Signup.vue doesn't understand what VueJwtDecode means.
import VueJwtDecode from 'vue-jwt-decode'
const payload = VueJwtDecode.decode(res.jwt);
However, since you have globally installed the library, it has been installed to the Vue instance, meaning that it is available from the this context within your component. As a result, you can also access it from the component context without reimporting:
const payload = this.$jwtDec(res.jwt);
As document, in your component, you need to use
this.$jwtDec(res.jwt)
instead of
VueJwtDecode.decode(res.jwt);

[Vue warn]: Unknown custom element

I am new to vuejs, While writing one js code inside laravel framework, I am getting error :
[Vue warn]: Unknown custom element: <app> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
App.js
import Vue from 'vue'
import Vcinfo from './Vcinfo.vue'
import router from './router'
const app = new Vue({
el: '#vcinfo',
components: { Vcinfo },
template: '<app></app>',
router
})
please suggest what to do?
This is for future reader.
I made the mistake I had to use it like this.
import Vue from 'vue'
import Vcinfo from './Vcinfo.vue'
import router from './router'
const app = new Vue({
el: '#vcinfo',
components: { Vcinfo },
template: '<vcinfo></vcinfo>',
router
})
as per this import import Vcinfo from './Vcinfo.vue'

Categories