maximum call stack size exceeded chartjs vue 3

t0ybt7op  于 2023-11-18  发布在  Chart.js
关注(0)|答案(1)|浏览(215)

长话短说,我正在使用vue3和chartjs创建一个相当简单的折线图。

Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
    at Object.get2 [as get] (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:467:23)
    at toRaw (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:920:35)
    at Proxy.instrumentations.<computed> (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:454:19)
    at Proxy.value (webpack-internal:///./node_modules/chart.js/dist/chunks/helpers.segment.js:667:26)
    at Proxy.instrumentations.<computed> (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:454:36)
    at Proxy.value (webpack-internal:///./node_modules/chart.js/dist/chunks/helpers.segment.js:667:26)
    at Proxy.instrumentations.<computed> (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:454:36)
    at Proxy.value (webpack-internal:///./node_modules/chart.js/dist/chunks/helpers.segment.js:667:26)
    at Proxy.instrumentations.<computed> (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:454:36)
    at Proxy.value (webpack-internal:///./node_modules/chart.js/dist/chunks/helpers.segment.js:667:26)

字符串
我已经看过thisthisthis,和this类似的问题,但他们没有帮助。
这里是组件。注意我也尝试了vue-chartjs,但没有帮助

<template>
    <canvas id="passwordStrengthProgressChart" ref="passwordStrengthProgressChart">
    </canvas>
    <!-- <Line :data="data" :options="options">

    </Line> -->
</template>
<script lang="ts">
import useEncryptedDataStore, { EncryptedDataStore } from '@/Objects/Stores/EncryptedDataStore';
import { ComputedRef, Ref, ShallowRef, computed, defineComponent, onMounted, readonly, ref, shallowReactive, shallowRef, watch } from 'vue';
import { PasswordsColor, ValuesColor } from '@/Types/Colors';
import { Chart, ChartData, LineController, LineElement, PointElement, LinearScale, Title, CategoryScale } from "chart.js"
import { Line } from "vue-chartjs"
import createTestData from '@/Utilities/TestUtility';

Chart.register(LineController, LineElement, PointElement, LinearScale, Title, CategoryScale)

export default defineComponent({
  name: 'PasswordStrengthProgressChart',
  components: {
    // Line
  },
  setup() {
    const encryptedDataStore: EncryptedDataStore = useEncryptedDataStore()

    const passwordColor: string = PasswordsColor.primaryColor
    const valuesColor: string = ValuesColor.primaryColor

    const safePasswordCounts: number[] =
      encryptedDataStore.currentAndSafePasswords.safe
    const safeValueCounts: number[] =
      encryptedDataStore.currentAndSafeValues.safe

    const passwordStrengthProgressChart: Ref<HTMLElement | null> = ref(null)

    const options: any = {
      responsive: true,
      elements: {
        point: {
          radius: 1
        }
      }
    }

    const data: Ref<any> = ref({
      labels: encryptedDataStore.currentAndSafePasswords.current,
      datasets: [
        {
          label: 'Secure Passwords',
          data: [...safePasswordCounts],
          borderColor: passwordColor,
          cubicInterpolationMode: 'monotone',
          tension: 0.4
        },
        {
          label: 'Secure Values',
          data: [...safeValueCounts],
          borderColor: valuesColor,
          cubicInterpolationMode: 'monotone'
        }
      ]
    })

    onMounted(() => {
      new Chart(
        document.getElementById(
          'passwordStrengthProgressChart'
        ) as HTMLCanvasElement,
        {
          type: 'line',
          data: {
            labels: encryptedDataStore.currentAndSafePasswords.current,
            datasets: [
              {
                label: 'Secure Passwords',
                data: safePasswordCounts,
                borderColor: passwordColor,
                cubicInterpolationMode: 'monotone',
                tension: 0.4
              },
              {
                label: 'Secure Values',
                data: [1, 2],
                borderColor: valuesColor,
                cubicInterpolationMode: 'monotone'
              }
            ]
          },
          options: {
            responsive: false,
            elements: {
              point: {
                radius: 0
              }
            }
          }
        }
      )

      // test updating the chart data. Causes the error
      const interval = setInterval(() => {
        createTestData()
        clearInterval(interval)
      }, 5000)
    })

    return {
      options,
      data
    }
  },
  data() {
    return {
      chart: null
    }
  }
})
</script>

的数据
我猜这是因为vue和chartjs都在跟踪dom的变化,而且只是返回和第四次。我希望我能让vue停止跟踪更新,但我找不到任何方法。任何帮助都将不胜感激。

更新:这是只使用vue-chartjs的代码,但问题相同。

<template>
    <!-- <canvas id="passwordStrengthProgressChart" ref="passwordStrengthProgressChart">
    </canvas> -->
    <Line :data="data" :options="options">

    </Line>
</template>

<script lang="ts">
import useEncryptedDataStore, { EncryptedDataStore } from '@/Objects/Stores/EncryptedDataStore';
import { ComputedRef, Ref, ShallowRef, computed, defineComponent, onMounted, readonly, ref, shallowReactive, shallowRef, watch } from 'vue';
import { PasswordsColor, ValuesColor } from '@/Types/Colors';
import { Chart, ChartData, LineController, LineElement, PointElement, LinearScale, Title, CategoryScale } from "chart.js"
import { Line } from "vue-chartjs"
import createTestData from '@/Utilities/TestUtility';

Chart.register(LineController, LineElement, PointElement, LinearScale, Title, CategoryScale)

export default defineComponent({
    name: "PasswordStrengthProgressChart",
    components:
    {
        Line
    },
    data()
    {
        return {
            chart: null
        }
    },
    setup()
    {
        const encryptedDataStore: EncryptedDataStore = useEncryptedDataStore();

        const passwordColor: string = PasswordsColor.primaryColor;
        const valuesColor: string = ValuesColor.primaryColor;

        const safePasswordCounts: Ref<number[]> = ref(encryptedDataStore.currentAndSafePasswords.safe);
        const safeValueCounts: Ref<number[]> = ref(encryptedDataStore.currentAndSafeValues.safe);

        const passwordStrengthProgressChart: Ref<HTMLElement | null> = ref(null);

        const options: any = {
            responsive: true,
            elements:
            {
                point:
                {
                    radius: 1
                }
            }
        };

        const data: Ref<any> = ref({
            labels: encryptedDataStore.currentAndSafePasswords.current,
            datasets: [
                {
                    label: 'Secure Passwords',
                    data: safePasswordCounts,
                    borderColor: passwordColor,
                    cubicInterpolationMode: 'monotone',
                    tension: 0.4
                },
                {
                    label: 'Secure Values',
                    data: safeValueCounts,
                    borderColor: valuesColor,
                    cubicInterpolationMode: 'monotone',
                }
            ]
        });

        onMounted(() => 
        {
            // new Chart(document.getElementById('passwordStrengthProgressChart') as HTMLCanvasElement,
            //     {
            //         type: 'line',
            //         data: {
            //             labels: encryptedDataStore.currentAndSafePasswords.current,
            //             datasets: [
            //                 {
            //                     label: 'Secure Passwords',
            //                     data: safePasswordCounts,
            //                     borderColor: passwordColor,
            //                     cubicInterpolationMode: 'monotone',
            //                     tension: 0.4
            //                 },
            //                 {
            //                     label: 'Secure Values',
            //                     data: [1, 2],
            //                     borderColor: valuesColor,
            //                     cubicInterpolationMode: 'monotone',
            //                 }
            //             ]
            //         },
            //         options:
            //         {
            //             responsive: false,
            //             elements:
            //             {
            //                 point:
            //                 {
            //                     radius: 0
            //                 }
            //             }
            //         }
            //     });

            // test updating the chart data
            const interval = setInterval(() => 
            {
                createTestData();
                clearInterval(interval);
            }, 5000);
        });

        return {
            options,
            data
        }
    }
})
</script>

<style></style>


这只是在使用encryptedDataStore与chartjs时的问题,而不是其他任何地方。

2w2cym1i

2w2cym1i1#

我设法解决了这个问题,将React数据解构成一个新的ref,观察原始数据结构的变化,然后更新解构的值,并强制vue重新渲染组件。
下面是最终代码

<template>
    <div id="passwordStrenghtProgressContainer" :key="key">
        <h2>Password Strength Over Time</h2>
        <Line :data="data" :options="options">
        </Line>
    </div>
</template>

<script lang="ts">
import useEncryptedDataStore, { EncryptedDataStore } from '@/Objects/Stores/EncryptedDataStore';
import { Ref, defineComponent, ref, watch } from 'vue';
import { PasswordsColor, ValuesColor } from '@/Types/Colors';
import { Chart, ChartData, LineController, LineElement, PointElement, LinearScale, Title, CategoryScale } from "chart.js"
import { Line } from "vue-chartjs"

Chart.register(LineController, LineElement, PointElement, LinearScale, Title, CategoryScale)

export default defineComponent({
    name: "PasswordStrengthProgressChart",
    components:
    {
        Line
    },
    setup()
    {
        const key: Ref<string> = ref('');
        const encryptedDataStore: EncryptedDataStore = useEncryptedDataStore();

        const passwordColor: string = PasswordsColor.primaryColor;
        const valuesColor: string = ValuesColor.primaryColor;

        let lableArray: Ref<number[]> = ref([...encryptedDataStore.currentAndSafePasswords.current]);
        let chartOneArray: number[] = [...encryptedDataStore.currentAndSafePasswords.safe];
        let chartTwoArray: Ref<number[]> = ref([...encryptedDataStore.currentAndSafeValues.safe]);

        function updateKey()
        {
            key.value = Date.now().toString();
        }

        watch(() => encryptedDataStore.currentAndSafePasswords.current.length, (newValue) =>
        {
            lableArray.value = [...encryptedDataStore.currentAndSafePasswords.current];
            updateKey();
        });

        watch(() => encryptedDataStore.currentAndSafePasswords.safe.length, (newValue) =>
        {
            chartOneArray = [...encryptedDataStore.currentAndSafePasswords.safe];
            updateKey();
        });

        watch(() => encryptedDataStore.currentAndSafeValues.safe.length, (newValue) =>
        {
            chartTwoArray.value = [...encryptedDataStore.currentAndSafeValues.safe];
            updateKey();
        });

        const options: any = {
            responsive: true,
            elements:
            {
                point:
                {
                    radius: 0
                }
            }
        };

        const data: Ref<ChartData> = ref({
            labels: lableArray.value,
            datasets: [
                {
                    label: 'Secure Passwords',
                    data: chartOneArray,
                    borderColor: passwordColor,
                    cubicInterpolationMode: 'monotone',
                    tension: 0.4
                },
                {
                    label: 'Secure Values',
                    data: chartTwoArray,
                    borderColor: valuesColor,
                    cubicInterpolationMode: 'monotone',
                }
            ]
        });

        return {
            key,
            options,
            data
        }
    }
})
</script>

字符串

相关问题