【问题标题】:Directive template value not updating指令模板值未更新
【发布时间】:2026-01-26 03:50:01
【问题描述】:

我正在设置这样的指令(超时功能只是作为演示):

app.directive('timeRange', function () {
    return {
        restrict: 'A',
        scope: {
            sliderId: "@sliderId",
        },
        template:   '<div id="{{sliderId}}"></div>'+
                    '<p>From: <span>{{fromVal}}</span>'+
                        '<span style="float:right;">{{toVal}}</span><span style="float:right;">To: </span>'+
                    '</p>',
        link: function (scope, elem, attrs) {

            scope.sliderId = 'NewId';
            scope.fromVal = '06:00';
            scope.toVal = '17:00';

            setTimeout(function(){
                scope.fromVal = 'Hello';
                log("Changed");
            }, 2000);
        },
    };
});

超时函数运行时,HTML 不会更新,值保持在06:00。当变量更新时,如何让模板更新?我是否需要在链接属性的scope 部分中以某种方式链接它?

【问题讨论】:

    标签: angularjs angularjs-directive angular-directive


    【解决方案1】:

    我在您的示例中看到的唯一问题是您使用的是setTimeout 而不是$timeout 服务。每当您以这种方式更改角度或范围变量时,您都必须手动调用$scope.$apply(),这就是$timeout 服务为您所做的。下面的代码效果更好:

    app.directive('timeRange', function ($timeout) {
        return {
            restrict: 'A',
            scope: {
                sliderId: "@sliderId",
            },
            template:   '<div id="{{sliderId}}"></div>'+
                        '<p>From: <span>{{fromVal}}</span>'+
                            '<span style="float:right;">{{toVal}}</span><span style="float:right;">To: </span>'+
                        '</p>',
            link: function (scope, elem, attrs) {
    
                scope.sliderId = 'NewId';
                scope.fromVal = '08:00';
                scope.toVal = '17:00';
    
                $timeout(function(){
                    scope.fromVal = 'Hello';
                    console.log("Changed");
                }, 2000);
            },
        };
    });
    

    注意$timeout的注入以及使用方式。

    在 Plunker 中查看此内容: http://plnkr.co/edit/KlRAeg6cVhehw2EhWzCK?p=preview

    修复原件...

    固定的原始代码看起来像(只是一个sn-p):

    setTimeout(function(){
        scope.fromVal = 'Hello';
        scope.$apply();
        console.log("Changed");
    }, 2000);
    

    祝你好运!

    【讨论】:

    • 谢谢,我不知道 $timeout 服务。实际代码没有使用超时,但是调用 scope.$apply 可以很好地更新变量:)。
    • @TomHart 调用scope.$apply()时要小心添加。当申请已经在进行中时,您迟早会致电scope.$apply() - 通常是因为 Angular 正在为您运行申请。为此,您可能会得到类似digest already in progress 的信息。无论如何,很高兴我能帮上忙!
    • @drew_w 那我应该用什么? scope.$apply()$timeout 更直接。两种情况下都会出现摘要错误吗?