“$ attrs是readonly”,“$ listeners是readonly”,“避免直接改变道具”

时间:2018-03-31 08:31:00

标签: javascript vuejs2 vue-component

我是Vue的新手。我正在尝试开发一个聊天应用程序,其中好友列表将显示在左侧菜单上,聊天框将显示在正文中。我正在使用ajax调用加载好友列表并根据好友ID路由到聊天框。这是代码示例。

<div class="chat-container clearfix" id="chat">
    <div class="people-list" id="people-list">
        <chatlist-component></chatlist-component>
    </div>

    <div class="chat">
       <router-view></router-view>
    </div>
</div> 

聊天列表组件将从服务器加载好友列表。这是我的app.js文件;

Vue.use(VueRouter)

const router = new VueRouter({
  routes,
  linkActiveClass: "active"
});


    import ChatComponent from './components/ChatComponent';
    const routes = [
      { path: '/chat/:id/:name', component: ChatComponent , name: 'chat'}
    ];
    Vue.component('chatlist-component', require('./components/ChatlistComponent.vue'));

    const app = new Vue({
        el: '#chat',
        router
    });

聊天列表组件模板代码

<li class="clearfix" v-for="user in users">
                <img :src="baseUrl+'/img/default_image.jpeg'" alt="avatar" class="chat-avatar rounded-circle" />
                <router-link class="about" :to="{ name: 'chat', params: { id: user.id, name:user.name }}">
                    <div class="name">{{user.name}}</div>
                    <div class="status">
                        <i class="fa fa-circle online"></i> online
                    </div>
                </router-link>

            </li>

直到我切换到另一个用户才能正常工作。当我点击聊天列表组件中的任何路由器列表时,它工作正常,但会向控制台抛出以下错误。

app.js:19302 [Vue warn]: $attrs is readonly.

found in

---> <RouterLink>
       <ChatlistComponent> at resources/assets/js/components/ChatlistComponent.vue
         <Root>

app.js:19302 [Vue warn]: $listeners is readonly.

found in

---> <RouterLink>
       <ChatlistComponent> at resources/assets/js/components/ChatlistComponent.vue
         <Root>

app.js:19302 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "to"

提前致谢

7 个答案:

答案 0 :(得分:12)

首先,这些错误仅在非生产版本中出现,但是它们指示应在生产发布之前解决的问题。

如果加载了多个Vue实例,则会显示$ attrs,$ listeners和其他警告。据我了解,这种情况通常可能由于以下原因之一发生:

  • 它是通过webpack加载/打包到捆绑软件中的,也可以从外部(不是通过webpack加载)
  • 它是通过一种包含方式(例如vuetifyvue-test-utilsvue-cli-electron-builder)加载的,而另一种是通过Webpack配置加载的(例如,绝对路径和相对路径,common.js) vs esm.js vue文件,仅运行时vue与编译器+运行时vue)

如果单击该行(在上面的输出中为app.js:19302),并在出现消息的位置放置一个断点,则可以查看堆栈回溯中的模块列表,以查看是否还有更多内容列出了通往Vue的一条路径。例如,请参见下面的前三个模块具有不同的路径(但它们都是Vue的一部分): enter image description here 如果您看到Vue以两种或多种不同的方式显示,则表明已加载多个Vue实例。 Vue仅支持一个实例,如果加载了多个实例,cab会生成这些错误消息。

上面提到的问题有多个链接,Vuetify问题是我提出的。在那种情况下,Vuetify需要Vue,并且加载它的方式与我不同。通常,解决方法是检查您指定(或未指定)Vue的Webpack配置,并尝试使其与包含其他副本的方式匹配(例如,绝对路径与相对路径,或打包路径与外部路径)。

答案 1 :(得分:1)

就我而言,我正在从一个不使用VueCLI的项目中迁移。在该项目中,我从CDN <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>导入了vue。在我的Vue CLI项目中,我已将整个index.html文件复制并粘贴到Public文件夹中。 Vue CLI具有导入vue的自有方式,因此它们相互冲突。我只是删除了脚本,问题就解决了。

答案 2 :(得分:1)

发生此错误是因为我在项目中使用Git子模块,并且拥有以下文件夹:

  • ./node_modules-这是针对主要项目的。在这些node_modules中安装了vue。
  • ./my_git_submodules/vue_design_system/node_modules-提供基本组件(也使用vue)的设计系统。 Vue也已安装在这里!

因此,因为两者:

  • ./node_modules/vue
  • ./my_git_submodules/vue_design_system/node_modules/vue

已存在,运行npm run serve(在下面的vue-cli-service build)构建了两个Vue实例。这是 一个非常讨厌的问题,因为它在某些情况下会破坏反应性 (即,您点击一个按钮,却什么也没发生-您只要 $ listeners只读错误)

快速修复:
删除子文件夹(vue_design_system)中的node_modules并运行npm run serve对我来说有效。

长期修复:
您可能需要通过在vue.config.js

中添加一条规则来使Webpack忽略嵌套的node_modules文件夹

答案 3 :(得分:1)

我遇到了和上面一样的问题。我正在使用 git 子模块,我使用了

yarn add ./submodule

不知何故,./submodule 目录中出现了一个 node_modules 目录,这让一切都变得混乱。

它正在加载两个 Vue 实例。

答案 4 :(得分:0)

将其添加到 vue.config.js 对我有用。

const path = require('path')

module.exports = {
  configureWebpack: {
    externals: {
      vue: 'Vue'
    }
  }
}

答案 5 :(得分:0)

我遇到了同样的问题。对我来说,当我使用

安装本地模块时
yarn add ../somemodule --force

似乎此命令将复制整个模块目录,包括node_modules子目录。这将导致复制相同版本的“ vue”模块。在浏览器devtool中,我可以看到该模块的多个源。

对我来说,解决方案是在每次安装本地模块后手动删除node_modules。

答案 6 :(得分:-5)

将其添加到main.js中对我有用。

Vue.config.silent = true;