"$attrs 是只读的","$listeners 是只读的","避免直接改变一个 prop"
Posted
技术标签:
【中文标题】"$attrs 是只读的","$listeners 是只读的","避免直接改变一个 prop"【英文标题】:"$attrs is readonly","$listeners is readonly","Avoid mutating a prop directly" 【发布时间】:2018-09-10 04:03:37 【问题描述】:我是 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'" 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"
提前致谢
【问题讨论】:
【参考方案1】:首先,这些错误仅在非生产版本中出现,但它们表明应该在生产发布之前解决问题。
如果加载了多个 Vue 实例,则会显示 $attrs、$listeners 和其他警告。据我了解,这通常是由于以下原因之一:
它正在通过 webpack 加载/打包到包中,并且也在外部加载(不是通过 webpack) 它被你包含的东西加载(例如vuetify,vue-test-utils,vue-cli-electron-builder)一种方式和你的webpack配置另一种方式(例如绝对路径与相对路径,common.js与esm.js vue文件, runtime-only vue vs compiler+runtime vue)如果您单击该行(在上面的输出中是 app.js:19302)并在消息发出的位置放置一个断点,您可以在堆栈回溯中查看模块列表以查看是否有超过列出了 Vue 的一条路径。例如,看下面的前三个模块有不同的路径(但都是 Vue 的一部分): 如果您看到 Vue 以两种或多种不同的方式出现,则表明加载了多个 Vue 实例。 Vue 只支持单个实例,如果加载多个实例,就会产生这些错误消息。
上面包含几个问题的链接,Vuetify 问题是我提交的问题。在那种情况下,Vuetify 需要 Vue 并且加载它的方式与我不同。通常修复方法是检查指定(或未指定)Vue 的 webpack 配置,并尝试使其与包含其他副本的方式相匹配(例如,绝对路径与相对路径,或打包与外部)。
【讨论】:
你也可以运行yarn why vue
(如果使用yarn)来查看哪些包可能在复制vue。
这是刚刚添加的付费课程的新部分,但我会包含链接以防有人订阅。另外,值得注意的是,本课的主题是 $attrs 在 Vue 3 中已经完全改变。请参阅新文档和本课程关于从 2 迁移到 3,特别是本课,称为 The New $attrs:@987654325 @
对我来说,问题正是你所说的,我从 index.html 文件中删除了额外的导入,错误消失了,它创建了 2 个实例。谢谢。
也看到了这个,但想补充一下,这是因为我在一个包中进行开发,并使用yarn link
在另一个应用程序中测试该包的实现。最初的包依赖于 Vue 2.x,我的应用程序也是如此。一旦我将包真正更新/导入到我的应用程序中,这就不成问题了。【参考方案2】:
将此添加到 vue.config.js,对我有用。
const path = require('path')
module.exports =
configureWebpack:
externals:
vue: 'Vue'
【讨论】:
这告诉 webpack 你想把它从捆绑过程中排除。所以做 importVue from 'vue';
不会做任何事情。这对你有用,因为你是从其他地方获得 vue,比如你的 html 中的脚本标签。【参考方案3】:
我遇到了同样的问题。对我来说,当我使用
安装本地模块时yarn add ../somemodule --force
似乎这个命令将复制整个模块目录,包括 node_modules 子目录。这会导致相同版本的“vue”模块重复。在浏览器开发工具中,我可以看到模块的多个来源。
对我来说,解决方案是每次安装本地模块后手动删除 node_modules。
【讨论】:
这也是我使用npm install <folder>
时的问题,例如npm install ../my-local-lib
【参考方案4】:
就我而言,我是从一个不使用 VueCLI 的项目迁移而来的。在那个项目中,我从 CDN <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
导入了 vue。在我的 Vue CLI 项目中,我已将整个 index.html 文件复制并粘贴到 Public
文件夹中。 Vue CLI 有自己的导入 vue 的方式,所以它们发生了冲突。我只是删除了脚本,问题就解决了。
【讨论】:
【参考方案5】:这个错误发生在我身上,因为我在我的项目中使用了 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 文件夹
【讨论】:
【参考方案6】:我遇到了和上面一样的问题。我正在使用 git 子模块并且我使用过
yarn add ./submodule
不知何故,最终在 ./submodule 目录中出现了一个 node_modules 目录,这让一切变得混乱。
它正在加载两个 Vue 实例。
【讨论】:
【参考方案7】:这也可能发生,因为您使用 npm link
来使用未发布的 vue 包。与@walnut_salami 的解释基本一致。
解决此问题的方法是移至 this way 以包含未发布的模块。
【讨论】:
【参考方案8】:看起来好像有很多可能的答案。
我手动向节点文件夹添加了一个 npm 包,问题是缺少 npm i
命令。使用 install 命令后,一切正常。
【讨论】:
【参考方案9】:在我的例子中,这个错误是在模块联合我的组件之后出现的。 我通过将组件接收器中的 vue 共享给组件供应商来解决它。 例如
webpack.config.js
module.exports =
plugins: [
new ModuleFederationPlugin(
name: "dashboard",
remotes:
web_common: "web_common@http://localhost:8081/remoteEntry.js"
,
shared:
vue: // this solved my issue.
eager: true,
singleton: true,
requiredVersion: deps.vue
,
),
]
【讨论】:
以上是关于"$attrs 是只读的","$listeners 是只读的","避免直接改变一个 prop"的主要内容,如果未能解决你的问题,请参考以下文章
关于jquery或js的attr方法,$("#img").attr(width:"这里想用百分比");