无限循环当观察父对象时,观察者不更新任何值

infinite loop when watching parent object, watcher does not update any value

本文关键字:观察者 更新 任何值 观察 对象 无限循环      更新时间:2023-09-26

我有一个生成C3js图表的指令。我有一个包含各种C3属性的对象。如果传入元素已经有一个chartOptions对象,则会使用它,但如果没有,则会添加默认对象。

scope.elementObject.chartOptions = scope.elementObject.chartOptions || chartOptions;

我正试图观察chartOptions对象上的任何更改,因为它将在指令之外与之交互,然而,简单地创建一个观察程序而不添加任何功能会导致无限循环。常规的无限循环解决方案似乎都不起作用,因为我似乎并没有在观察程序中修改对象。

scope.$watch('elementObject.chartOptions', function () {
    console.log('changed')
}, true);
//INFINITE LOOP

然而,如果我观察一个子对象,那么我不会得到一个无限循环,比如

scope.$watch('elementObject.chartOptions.data', function () {
    console.log('changed')
}, true);
//NO INFINITE LOOP

指令

app.directive('newchart', function () {
    return {
        scope: {
            data: "=",
            elementObject: "=element"
        },
        restrict: 'E',
        link: link
    };
    function link(scope, elem) {
        var el = elem[0];
        var chartOptions = {
            data: {
                columns: [['data1', 30, 200, 100, 400, 150, 250]],
                type: 'spline',
                labels: false
            },
            interaction: { enabled: true },
            grid: { x: { show: false }, y: { show: false } },
            legend: { show: true, position: 'bottom' },
            tooltip: { show: true, grouped: true }
        };
        scope.elementObject.chartOptions = scope.elementObject.chartOptions || chartOptions;
        scope.elementObject.chartOptions.bindto = el;
        var chart = c3.generate(scope.elementObject.chartOptions);
        scope.$watch('elementObject.chartOptions', function () {
            console.log('changed')
        }, true);        
    };
});

我需要能够观察chartOptions对象的任何属性的变化,而不仅仅是数据的变化,就像上面的例子一样。

我能够确定问题是由以下行引起的:

scope.elementObject.chartOptions.bindto = el;

链接函数中的CCD_ 4对象参数是正在操作的DOM元素的jquery包装器。特别是在上面放置了一个观察者,导致了无限循环。

因为我在options对象中包含了bindto属性,所以当被监视时,整个对象都返回了无限循环。

来自关于bindto:的C3js文档

如果未指定此选项,则会生成图表,但不会进行设置。相反,我们可以通过chart.element访问元素,并自行设置

因此,解决方案是在选项对象中不包含bindto属性,然后通过chart.element访问生成的svg,将其添加到指令中,例如:

function link(scope, elem) {
    ...
    var chart = c3.generate(scope.elementObject.chartOptions);
    elem.html(chart.element)
}