Vue.js“超出最大调用堆栈大小”错误。将数据从父母传递给孩子失败
Posted
技术标签:
【中文标题】Vue.js“超出最大调用堆栈大小”错误。将数据从父母传递给孩子失败【英文标题】:Vue.js "Maximum call stack size exceeded" error. Passing data from parent to child failing 【发布时间】:2017-11-15 03:43:22 【问题描述】:我无法将数据从父母传递给孩子。我正在使用道具,也尝试过返回数据 - 没有运气。我有一个带有数据的面板组件(它是父组件)和 panelBody 组件(子组件)
面板如下:
<template>
<div id="panel">
<div class="panel">
<ul>
<li v-for="shelf in shelfs">
<panel-body :shelf="shelf" :selected.sync="selected"></panel-body>
</li>
</ul>
</div>
</div>
</template>
<script>
import PanelBody from '../components/PanelBody'
export default
name: 'panel-body',
components:
'panel-body': PanelBody
,
data: () => (
shelfs: [
name: 'shelf 1',
books: [
title: 'Lorem ipum'
,
title: 'Dolor sit amet'
]
,
name: 'shelf 2',
books: [
title: 'Ipsum lorem'
,
title: 'Amet sit dolor'
]
],
selected:
)
</script>
<style scoped>
a
color: #42b983;
</style>
我的 panelBody 是:
<template>
<div id="panel-body">
<a href="#" v-on:click.prevent.stop="select"> shelf.name </a>
<ul v-show="isSelected">
<li v-for="book in shelf.books"> book.title </li>
</ul>
</div>
</template>
<script>
export default
name: 'panel-body',
props: ['shelf', 'selected'],
computed:
isSelected: function ()
return this.selected === this.shelf
,
methods:
select: function ()
this.selected = this.shelf
</script>
<style scoped>
a
color: #42b983;
</style>
请帮忙!无法找出错误“vue.esm.js?65d7:3877 Uncaught RangeError: Maximum call stack size exceeded”。当我删除数据时,一切正常。
【问题讨论】:
你不应该使用带有 data 属性的=>
函数,只使用data()return...
成功了吗...??
不,我得到一个“属性或方法“架子”未在实例上定义,但在渲染期间被引用”和““数据”选项应该是一个返回每个实例的函数组件定义中的价值。”这很奇怪。
【参考方案1】:
出现错误的原因
超过最大调用堆栈大小
是因为这个
import PanelBody from '../components/PanelBody'
export default
name: 'panel-body',
components:
'panel-body': PanelBody
,
您使用name: 'panel-body'
定义了您的面板 组件。将其更改为 name: 'panel'
,您将删除循环引用。
cmets 和其他答案中提到的其他问题通常也适用。以下是您的组件的工作版本。
Panel.vue
<template>
<div id="panel">
<div class="panel">
<ul>
<li v-for="shelf in shelfs">
<panel-body :shelf="shelf" :key="shelf.name" :selected.sync="selected"></panel-body>
</li>
</ul>
</div>
selected
</div>
</template>
<script>
import PanelBody from './PanelBody.vue'
export default
name: 'panel',
components:
'panel-body': PanelBody
,
data()
return
shelfs: [
name: 'shelf 1',
books: [
title: 'Lorem ipum'
,
title: 'Dolor sit amet'
]
,
name: 'shelf 2',
books: [
title: 'Ipsum lorem'
,
title: 'Amet sit dolor'
]
],
selected:
</script>
<style scoped>
a
color: #42b983;
</style>
PanelBody.vue
<template>
<div id="panel-body">
<a href="#" v-on:click.prevent.stop="select"> shelf.name </a>
<ul v-show="isSelected">
<li v-for="book in shelf.books"> book.title </li>
</ul>
</div>
</template>
<script>
export default
name: 'panel-body',
props: ['shelf', 'selected'],
data()
return
internalSelected: null
,
computed:
isSelected: function ()
return this.internalSelected === this.shelf
,
methods:
select: function ()
this.internalSelected = this.shelf
this.$emit("update:selected", this.internalSelected)
</script>
<style scoped>
a
color: #42b983;
</style>
我还想注意一件事。由于 PanelBody 中的 this 行,this.selected = this.shelf
Vue 会抛出一个警告,表明你正在直接改变一个 prop。通常,您应该存储要更改的属性的本地副本。我已经更新了上面的代码来做到这一点。
【讨论】:
@TeomanKirac 不客气。目前还没有涉及一个额外的问题;此代码将产生一个错误,即您正在直接改变一个道具。我会在一分钟内发布一个修复。 @TeomanKirac 我更新了 PanelBody 代码并简要说明。 伯特先生,你太棒了。非常感谢您的解释和专业知识。非常感谢:) 另见 github.com/vuejs/vue/issues/9081 我向 Vue 报告了这一点 我的问题是我的页面名称(max-button
)与组件名称(MaxButton
,也可以用作max-button
)相同。【参考方案2】:
您所在的 Vue 的名称不应与您正在导入的组件的名称相同。
就我而言
<template>
<div>
<SingleStandard></SingleStandard>
</div>
</template>
<script>
import SingleStandard from '../components/SingleStandard';
export default
name: 'SingleStandard',
components: SingleStandard ,
;
</script>
上面的代码导致了同样的问题,但是当我更改导出组件的名称时它起作用了。
<template>
<div>
<SingleStandard></SingleStandard>
</div>
</template>
<script>
import SingleStandard from '../components/SingleStandard';
export default
name: 'SingleStandardView', <-------------
components: SingleStandard ,
;
</script>
请为所有未来的人检查您的命名约定:)
【讨论】:
是的,我也是这种情况,但我的方法与映射操作同名。【参考方案3】:vue2 中的同步发生了变化。
https://vuejs.org/v2/guide/components.html#sync-Modifier
你应该这样使用它
<panel-body :shelf="shelf" :selected="selected" @update:selected="val => selected = val"></panel-body>
和孩子
this.$emit('update:selected', shelf)
或 你可以这样做
<panel-body :shelf="shelf" :selected="shelf == selected" @select="selected = shelf"></panel-body>
和孩子
this.$emit("select")
【讨论】:
你是对的,但并不完全正确。您可以在问题中使用prop.sync="parentProp"
,它自动扩展为道具事件声明。唯一应该在问题代码中更改:而不是手动改变道具this.selected = this.shelf
,应该是this.$emit('update:selected', this.shelf)
。示例:jsfiddle.net/wostex/63t082p2/72
已经尝试了 John 和 Wostex 建议的所有变体,但没有成功。现在的错误是“属性或方法“架子”未在实例上定义,但在渲染期间被引用。”但是这个错误只是不同的,因为数据现在不是一个函数,就像 Vamsi Krishna 建议的那样..
数据必须是函数数据:function() return bla: true 【参考方案4】:
在我的情况下,它发生在商店溢出时
const auth = function( next, store )
if(!store.getters.auth.loggedIn)
return next('/login')
return next()
export auth;
我像这样更新并修复了这个问题。希望这会对你有所帮助。
const auth = function( next, store )
if(store.getters.auth.loggedIn)
return next('/login')
return next()
export auth;
【讨论】:
【参考方案5】:尝试禁用 vue dev-tools 扩展...
我的应用程序中有几个月出现这个不稳定的错误,这让我发疯了! 我刚刚意识到,如果我禁用 vue dev-tool chrome 扩展,它就再也不会发生了。
不完美,但它可以提供帮助。
【讨论】:
以上是关于Vue.js“超出最大调用堆栈大小”错误。将数据从父母传递给孩子失败的主要内容,如果未能解决你的问题,请参考以下文章