使用ng-include重用以前实例化的模板

Reusing previously instantiated templates with ng-include

本文关键字:实例化 ng-include 使用      更新时间:2024-02-24

我需要表单上的<select>来控制剩余的可用输入。通过将CCD_ 2绑定到CCD_。

问题是,每次用户更改所选值(因此更改src模板)时,angular都会从头开始编译模板并附加一个新的作用域。这具有每次擦除所有输入数据的效果。用户希望,如果他们更改回以前选择的选项,他们以前输入的所有字段数据仍将存在。

是否有任何内在的方式来实现期望的行为?理想情况下,ng-include将重复使用以前编译的模板和相关范围的选项?

一种解决方法是ng-include所有模板,并使用ng-show仅显示当前模板。虽然这看起来很重,但页面上有很多不必要的DOM元素。(特别是对于我的用例,其中将有大约20个不同的模板,并且整个<select>元素和动态模板控制可能在单个页面上重复多达40次。)

这是一个jsFiddle。所需的结果是,当将下拉列表更改为模板2并返回到1时,模板1上的计数器将保持不变。

我觉得这个问题很有趣。除了将模型放入服务中(这可能是正确的方式)之外,我不认为有一种内置的方式可以在不使用ng repeat的情况下使用ng include缓存模板,如本文所示。

<div ng-controller="Ctrl">
    <select ng-model="template" ng-options="t.name for t in templates">
     <option value="">(blank)</option>
    </select>
    url of the template: <tt>{{template.url}}</tt>
    <hr/>
    <div ng-repeat="t in templates" ng-include="t.url" ng-show="template.name == t.name">
     </div>
  </div>

正如您所指出的,这个解决方案的缺点是最终在DOM中有很多元素。

为了好玩,我写了一个ng-include版本,它缓存模板元素并重用它。在最坏的情况下,你仍然可能会创建同样多的DOM节点,但由于它们只是按需创建的,而且在任何给定的时间DOM中都只有一个,所以从角度来看,它应该保持相当高效。

这是这个指令的小提琴。

.directive('cacheInclude', function ($compile, $http, $templateCache) {
    return {
        link: function (scope, element, attrs, ctrl) {
            var cache = {};
            var currentElement = element;
            var replaceCurrent = function(cacheEntry) {
                currentElement.replaceWith(cacheEntry);
                currentElement = cacheEntry;
            };
            scope.$watch(function(){
                return scope.$eval(attrs.src);
            }, function () {
                var src = scope.$eval(attrs.src);
                if (!cache[src]) {
                    $http.get(src, {cache: $templateCache}).then(function (result) {

                        cache[src] = $compile(result.data.trim())(scope.$new());
                        replaceCurrent(cache[src]);
                    });
                } else {
                    replaceCurrent(cache[src]);
                }
            });
        }
    }
})

它不是"内置的",但我认为这是一个很好的中间解决方案。注意,该指令"仅用于示例",仍然需要错误处理等。