AngularJS刷新插值值

AngularJS refresh interpolated value

本文关键字:插值 刷新 AngularJS      更新时间:2023-09-26

我想弄清楚,如何在Angular模板中更新插值值-如果值本身不改变。

我有这样的语句(例如翻译):

<div>{{ 'SOME_TAG' | lang }}</div>

启动一个过滤器

app.filter('lang', function(Locale) {
    return function(val) {
        return Locale.translate(val);
    }
});

Locale是一个具有字段lang的服务,这取决于哪些值被翻译成不同的语言。当我改变这个字段的值时,翻译的值也应该改变。

之类的
<select ng-model="lang" ng-change="changeLang()">
    <option value="de">Deutsch</option>
    <option value="en">English</option>
</select>
...
$scope.changeLang = function() {
    Locale.changeLanguage($scope.lang);
};

在较早的AngularJS版本中(例如1.1.5,不确定有多远),这个方法做得很好。如果我更新Locale。Lang值和$digest()循环运行后,插值的模板值被更新。在最新版本(1.4.6和1.3.xx)中,这不再工作了。我认为这是一些优化的一部分-值('SOME_TAG')没有改变,所以为什么要重新运行插值。

我已经看到这个http://angular-translate.github.io/它工作得很好。是否存在更新这些值的"技巧"?

谢谢。

在angular关于过滤器的文档中,有一个叫做stateful的东西。添加它是为了提高过滤器的性能。

有一篇很好的关于有状态过滤器的博客文章详细描述了它。

简而言之,'SOME_TAG'是一个字符串,永远不会改变,过滤器添加的$watch永远不会被调用。但是对于$stateful,它还将检查您的过滤器的注入依赖是否有变化。

所以你需要$stateful或者你可以传递你的语言范围变量给服务让它工作。我认为最好避免$stateful过滤器(如文档中建议的那样),因为它们比没有它运行得更频繁。所以在这里传递语言作用域会更好。

请看看下面的演示或在这个小提琴。

angular.module('demoApp', [])
	.factory('Locale', Locale)
	.filter('langStateful', LangFilterState)
	.filter('lang', LangFilter)
	.controller('MainController', MainController);
function MainController($scope, $timeout, Locale) {
	$scope.changeLang = function() {
        Locale.changeLanguage($scope.lang);
    };
}
function LangFilter(Locale) {
    function LangFilter(val, lang) {
        return Locale.translateLang(val, lang);
    }
    
    return LangFilter;
}
function LangFilterState(Locale) {
    function LangFilter(val) {
        return Locale.translate(val);
    }
    
    LangFilter.$stateful = true;
    
    return LangFilter;
}
function Locale() {
	var localeFactory = {
        language: 'de',
        changeLanguage: changeLanguage,
        translate: translate,
        translateLang: translateLang,
        tags: {
            'title': {
            	de: 'Titel',
                en: 'title'
            },
            'help': {
                de: 'Hilfe',
                en: 'help'
            }
        }
    };
    
    return localeFactory;
    
    function changeLanguage(lang) {
        this.language = lang;
    }
    
    function translate(tag) {
        return this.tags[tag][this.language];
    }
    
    function translateLang(tag, lang) {
        return this.tags[tag][lang];
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app="demoApp" ng-controller="MainController">
<select ng-model="lang" ng-change="changeLang()" ng-init="lang='de'">
    <option value="de">Deutsch</option>
    <option value="en">English</option>
</select>
    
    {{'help' | langStateful}}
    {{'title' | lang: lang}}
</div>

我对此也很感兴趣,所以我研究了角转换代码。

在他们的代码中,特别是在src/service/translate.jssrc/filter/translate.js中,你会看到他们跟踪插补id并在$translate.setLanguage()之后更新插补对象。这是你的代码和他们的代码唯一的区别。

我的猜测是,angular会在消化周期之间跟踪插值对象的变化,并重新运行改变的插值,尽管它们的上下文没有改变,但我碰巧不太了解angular的代码库,所以我可以证明这一点。这对我来说是有意义的,因为除了angular-translate的代码之外,我没有看到任何"诡计"。