是什么导致此 "maximum call stack size exceeded" 错误?
What causes this "maximum call stack size exceeded" error?
我正在开发 Vue 3 和 Bootstrap 5 应用程序。我需要一个日期选择器,我选择 Vue 3 Datepicker.
在 components\Ui\Datepicker.vue
我有:
<template>
<datepicker
@selected="handleSelect"
v-model="dateSelected"
:upper-limit="picked_to"
:lower-limit="picked_from"
class="datepicker text-center" />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const dateSelected = ref(new Date());
return {dateSelected}
},
methods: {
handleSelect() {
this.$emit('setDate')
}
}
}
</script>
在 components\Ui\Navigation.vue
我有:
从“./Datepicker”导入日期选择器
导出默认{
注入:['$apiBaseUrl'],
姓名:'Navigation',
组件: {
日期选择器,
},
数据() {
return{
// 更多代码
}
},
方法: {
设置日期() {
这个。$emit('setDate');
}
},
}
在components\Content.vue
我有:
<template>
<div class="main">
<div class="d-sm-flex>
<h1>{{ title }}</h1>
<Navigation
@setDate='setDate'
/>
</div>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>
</div>
</div>
</template>
<script>
import Navigation from './Ui/Navigation'
export default {
inject: ['$apiBaseUrl'],
name: 'Content',
components: {
Navigation,
},
props: {
title: String,
},
emits: ['setDate'],
data() {
return {
headers: {
'content-type': 'application/json',
'Accept': 'application/json'
},
from: '',
to: '',
}
},
methods: {
sendData() {
this.axios.post(`${this.$apiBaseUrl}/submit`, this.fields, {options: this.headers}).then((response) => {
if (response.data.code == 200) {
this.isReport = true;
}
}).catch((errors) => {
this.errors = errors.response.data.errors;
});
}
},
setDate() {
console.log('Date');
},
}
}
</script>
问题
虽然我从日期选择器select一个日期,setDate()
方法并没有被执行。 Chrome 控制台显示:
Maximum call stack size exceeded
我的错误在哪里?
如前所述,该错误通常发生在死循环时。
正如 Kissu 指出的那样,如果您有一个事件被发送到父组件,然后更改作为 props 传递给子组件的数据,然后触发一个事件到父组件等等,这很容易发生。
在你展示的代码中我真的找不到任何循环,它们可能在你省略的部分。
编辑:
无限循环实际上可能是由组件的命名引起的。
您在 Datepicker.vue
中使用 <datepicker ...>
,而没有在 显式 中注册 vue3-datepicker
的日期选择器。
这可能会导致 vue 递归地尝试将组件挂载到自身中,从而导致最大堆栈跟踪错误,但这只是一个猜测。
但是您的代码中仍然存在一些问题。
首发:
<template>
<datepicker
@selected="handleSelect" // <-- according to the docs there are no events that the datepicker emits
v-model="dateSelected"
:upper-limit="picked_to" // <-- where does the picked_to value come from?
:lower-limit="picked_from" // <-- where does the picked_from value come from?
class="datepicker text-center" />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const dateSelected = ref(new Date());
return {dateSelected}
},
// do not mix options & composition api
methods: {
handleSelect() {
this.$emit('setDate')
}
}
}
</script>
您正在混合选项和组合 API,这绝不是一个好主意。
还有一些看似无处不在的值,您正在收听来自日期选择器的 @selected
事件,根据 docs 不存在,因此您将必须自己观察所选日期的变化。
组合 API 中的相同组件将如下所示:
<template>
<Datepicker v-model="initialDate" class="datepicker text-center" />
</template>
<script>
import Datepicker from "vue3-datepicker";
import { ref, watch } from "vue";
export default {
components: { Datepicker },
setup(props, { emit }) {
const initialDate = ref(new Date());
watch(initialDate, (newDate) => {
emit("setDate", newDate);
});
return { initialDate };
},
};
</script>
我尝试重新创建您在 sandbox 中给出的示例,但我没有遇到任何无限循环问题。
您可能想检查一下并与您的代码进行比较,并可能首先解决所有其他问题,看看是否对您的情况有所帮助:)
我正在开发 Vue 3 和 Bootstrap 5 应用程序。我需要一个日期选择器,我选择 Vue 3 Datepicker.
在 components\Ui\Datepicker.vue
我有:
<template>
<datepicker
@selected="handleSelect"
v-model="dateSelected"
:upper-limit="picked_to"
:lower-limit="picked_from"
class="datepicker text-center" />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const dateSelected = ref(new Date());
return {dateSelected}
},
methods: {
handleSelect() {
this.$emit('setDate')
}
}
}
</script>
在 components\Ui\Navigation.vue
我有:
在components\Content.vue
我有:
<template>
<div class="main">
<div class="d-sm-flex>
<h1>{{ title }}</h1>
<Navigation
@setDate='setDate'
/>
</div>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>
</div>
</div>
</template>
<script>
import Navigation from './Ui/Navigation'
export default {
inject: ['$apiBaseUrl'],
name: 'Content',
components: {
Navigation,
},
props: {
title: String,
},
emits: ['setDate'],
data() {
return {
headers: {
'content-type': 'application/json',
'Accept': 'application/json'
},
from: '',
to: '',
}
},
methods: {
sendData() {
this.axios.post(`${this.$apiBaseUrl}/submit`, this.fields, {options: this.headers}).then((response) => {
if (response.data.code == 200) {
this.isReport = true;
}
}).catch((errors) => {
this.errors = errors.response.data.errors;
});
}
},
setDate() {
console.log('Date');
},
}
}
</script>
问题
虽然我从日期选择器select一个日期,setDate()
方法并没有被执行。 Chrome 控制台显示:
Maximum call stack size exceeded
我的错误在哪里?
如前所述,该错误通常发生在死循环时。 正如 Kissu 指出的那样,如果您有一个事件被发送到父组件,然后更改作为 props 传递给子组件的数据,然后触发一个事件到父组件等等,这很容易发生。
在你展示的代码中我真的找不到任何循环,它们可能在你省略的部分。
编辑:
无限循环实际上可能是由组件的命名引起的。
您在 Datepicker.vue
中使用 <datepicker ...>
,而没有在 显式 中注册 vue3-datepicker
的日期选择器。
这可能会导致 vue 递归地尝试将组件挂载到自身中,从而导致最大堆栈跟踪错误,但这只是一个猜测。
但是您的代码中仍然存在一些问题。
首发:
<template>
<datepicker
@selected="handleSelect" // <-- according to the docs there are no events that the datepicker emits
v-model="dateSelected"
:upper-limit="picked_to" // <-- where does the picked_to value come from?
:lower-limit="picked_from" // <-- where does the picked_from value come from?
class="datepicker text-center" />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const dateSelected = ref(new Date());
return {dateSelected}
},
// do not mix options & composition api
methods: {
handleSelect() {
this.$emit('setDate')
}
}
}
</script>
您正在混合选项和组合 API,这绝不是一个好主意。
还有一些看似无处不在的值,您正在收听来自日期选择器的 @selected
事件,根据 docs 不存在,因此您将必须自己观察所选日期的变化。
组合 API 中的相同组件将如下所示:
<template>
<Datepicker v-model="initialDate" class="datepicker text-center" />
</template>
<script>
import Datepicker from "vue3-datepicker";
import { ref, watch } from "vue";
export default {
components: { Datepicker },
setup(props, { emit }) {
const initialDate = ref(new Date());
watch(initialDate, (newDate) => {
emit("setDate", newDate);
});
return { initialDate };
},
};
</script>
我尝试重新创建您在 sandbox 中给出的示例,但我没有遇到任何无限循环问题。
您可能想检查一下并与您的代码进行比较,并可能首先解决所有其他问题,看看是否对您的情况有所帮助:)