仅当页面的某个部分发生更改时才运行角度编译

Posted

技术标签:

【中文标题】仅当页面的某个部分发生更改时才运行角度编译【英文标题】:run angular compile only when a certian section of a page has changed 【发布时间】:2015-03-13 06:44:39 【问题描述】:

所以我正在开发一个应用程序,该应用程序有许多通过 jquery ajax 加载的部分,一些在它启动时,一些在响应其他部分,有些甚至是嵌套的。我不能做的是说“哦,mainContainer 中的内容改变了?”好吧,去编译那部分的代码。

原因是我希望能够将ui-sref's 放入我们不想弄乱的部分代码中。我想出了一个解决方案,但它并没有像我想象的那样工作,我在自定义指令中添加了$watch,但它触发了无数次。这是代码。

希望有人可以解释如何仅在 X <div> 中的内容通过发生的许多 ajax 调用之一更改时才运行一次,这样我就不需要立即将所有旧的将代码转换为 angular,并可以链接到使用 angular 的新代码。

app.directive('ngMainContainer', function ($compile, $timeout) 
    console.log("main container directive");
    return function (scope, elem, attrs) 
        scope.$watch(function () 
            return elem;
        , function (val) 
            console.log("Something changed. " + val);
            $timeout(function () 
                $compile(val)(scope);
            , 0);
        );
    ;
);

再次,我认为对传递给指令的元素进行监视是答案,但是即使我移动鼠标并单击通过 jquery ajax 加载的容器外部某处的页面,它也会运行。

【问题讨论】:

您是否尝试过将作用域变量设置为elem.html() 并在其上设置$watch 我收到此错误“错误:[jqLit​​e:nosel] jqLit​​e 不支持通过选择器查找元素!请参阅:docs.angularjs.org/api/angular.elementerrors.angularjs.org/1.3.5/jqLite/nosel - 这看起来应该不难,显然我错过了一些东西。 请看我的回答和我回答的下编辑部分。我试图解决两种方法来解决这个问题,其中一种包括不依赖于“注入”方面的角度的代码 【参考方案1】:

这是一个可能对您有用的解决方案。我将指令 ngMainContainer 放在我们想要观察其 html 内容的元素上。

在我们的控制器中,我添加<p> content </p>,我首先添加$compile,然后更新范围var,如$scope.html = angular.element(myDiv).html()。这是我们的指令$watch 触发的地方。

这是完整的工作示例。 <button> 正在附加 html,但这应该模拟 ajax 调用请求的解析完成。

JSFiddle Link

app.directive('ngMainContainer', [function () 
    return 
        restrict: 'A',
        link: function (scope, elem, attrs) 

            scope.$watch('html', function(n, o) 
                if(n !== o) 
                    console.log(elem.contents())
                    // html has changed, do something!
                
            );
        
    
]);

app.controller('ctrl', ['$scope', '$compile', function($scope, $compile) 

    $scope.content = "scope content";

    var myDiv = document.getElementById('main');

    $scope.appendContent = function()  // Replicate Ajax Callback

        var dynamic = $compile('<p ng-cloak> content </p>')($scope); // Compile content        
        angular.element(myDiv).append(dynamic);
        $scope.html = angular.element(myDiv).html()
    
]);

编辑

这是一种在将内容附加到 &lt;div&gt; 时执行此操作的方法,在执行附加的代码上没有角度的概念

Updated JSFiddle

<button id="noAngular" onclick="noAngularAppend()">Append Content - No Angular</button>

function noAngularAppend() 
    angular.element(document.getElementById('main')).scope().externallyAppend('<p ng-cloak> content </p>');

指令函数(注入$compile

scope.externallyAppend = function(element) 
    var node = $compile(element)(scope);
    elem.append(node);
    scope.$apply(scope.html = elem.contents());

【讨论】:

【参考方案2】:

Sal,我对你的答案投了赞成票,因为它最终确实帮助我解决了这个问题,但最终这并不是我想要的。

这就是我最终的结果。在主应用程序的控制器中,有一个函数,其中只有两行。

 $scope.doReshing = function (element) 
    $compile(angular.element(element))($scope);
    $scope.$apply();

然后,在 document.ready() 顶部包含 ng 指令的任何部分中,我放置了以下内容。

 var removeableContentContainer = $('#removableContentContainer');
 angular.element(removeableContentContainer).scope().doReshing(removeableContentContainer);

这正是我想要的。它让我对现有应用程序的工作方式几乎没有任何改变,让我在“旧”代码中添加 ui-srefs,而不必担心它如何或何时加载、何时加载、document.ready()触发,它会告诉 Angular 它需要编译。这是我的目标,您可以在任何时间点提取一些代码,并让它们本质上就像它们是带有控制器的页面的一部分一样。

【讨论】:

以上是关于仅当页面的某个部分发生更改时才运行角度编译的主要内容,如果未能解决你的问题,请参考以下文章

仅当用户向下滚动时才加载部分页面的简单方法?

仅当 Rails 中的属性发生更改时才运行回调

仅当两个依赖项都更改时才运行效果挂钩

浏览器渲染页面/reflow repaint

在路线更改和新组件加载不起作用后以角度滚动到顶部

仅当 pr 目标为 master 时才运行 GitHub 操作