You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AngularJS forEach循环内使用$compile编译HTML模板变量不更新问题

问题根因
  • 异步时序错误:$templateRequest 是异步网络请求,你在 init 中直接同步调用 generateHtml 时,模板内容还未返回,vm.itemTemplate 为 undefined,编译逻辑本身无法正常执行。
  • 作用域变量复用冲突:所有编译操作共用同一个根 $scope,循环中反复覆盖 vm.currentItem 的值。AngularJS 的数据绑定是动态引用绑定,不会保存赋值瞬间的快照,循环结束后 vm.currentItem 固定为数组最后一项,所有已编译的模板都会同步更新为最后一项的数据。
  • 代码基础缺失:原控制器中没有声明 var vm = this,直接使用 vm 会导致变量未定义报错。
修复方案
  1. 将 generateHtml 调用移到 $templateRequest 的成功回调中,保证编译时模板已经加载完成
  2. 每次循环编译时创建独立的子作用域,每个子作用域存储当前循环的单项数据,避免变量互相覆盖
  3. 调整模板绑定逻辑,直接绑定子作用域上的单项变量,不再复用全局的 currentItem,同时修正模板中误用React语法的className为HTML原生的class属性
修正后代码

控制器代码

angular.module('app').controller('PageController', ['$scope', '$sce', '$compile','$templateRequest',
    function ($scope, $sce, $compile,$templateRequest) {
        $scope.itemsHtml = '';
        // 补全vm声明
        var vm = this;
        // 动态数据数组
        vm.items = [{
            id: 1,
            name: 'abc',
        }, {
            id: 2,
            name: 'pqr',
        }, {
            id: 3,
            name: 'stu',
        }, {
            id: 4,
            name: 'xyz',
        }];
        
        let templateUrl = $sce.getTrustedResourceUrl('/views/item.html');

        $templateRequest(templateUrl).then(function(template) {
            vm.itemTemplate = template;
            // 模板加载完成后再执行编译
            vm.generateHtml();
        }, function() {});

        vm.generateHtml = function() {
            vm.items.forEach(function (item, key) {
                // 每次创建独立的子作用域,存储当前循环的item
                let childScope = $scope.$new();
                childScope.item = item;
                // 用子作用域编译模板
                let compiledElement = $compile(vm.itemTemplate)(childScope);
                // 等待脏检查执行完成后再取HTML
                childScope.$apply();
                /* 拼接编译后的动态HTML */
                $scope.itemsHtml += compiledElement.html();
                // 销毁子作用域避免内存泄漏
                childScope.$destroy();
            });
        }
    }
]);

模板代码

<script type="text/ng-template" id="item.html">
    <div class="item-wrapper">
        <div class="item-inner">
            {{ item.name }}
        </div>
        <div class="action-inner">
            <div class="btn-action"
                 role="button"
                 ng-click="pageCtrl.edit(item.id)">
                <i class="fa fa-plus"></i>
            </div>
        </div>
    </div>
</script>

注意:如果需要保留ng-click等Angular事件绑定能力,不要拼接HTML字符串,直接将编译得到的compiledElement插入到页面DOM中即可,拼接HTML会丢失所有动态绑定的事件。

内容的提问来源于stack exchange,提问作者Shailesh Daund

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:12:02