Javascript 使用 ng-include 时丢失范围

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11412410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:46:02  来源:igfitidea点击:

Losing scope when using ng-include

javascripthtmlangularjsangularjs-scopeangularjs-ng-include

提问by Shlomi Schwartz

I have this module routes:

我有这个模块路线:

var mainModule = angular.module('lpConnect', []).
    config(['$routeProvider', function ($routeProvider) {
    $routeProvider.
        when('/home', {template:'views/home.html', controller:HomeCtrl}).
        when('/admin', {template:'views/admin.html', controller:AdminCtrl}).
        otherwise({redirectTo:'/connect'});
}]);

Home HTML:

主页 HTML:

<div ng-include src="views.partial1"></div>

partial1HTML:

partial1HTML:

<form ng-submit="addLine()">
    <input type="text" ng-model="lineText" size="30" placeholder="Type your message here">
</form>

HomeCtrl:

HomeCtrl

function HomeCtrl($scope, $location, $window, $http, Common) {
    ...
    $scope.views = {
        partial1:"views/partial1.html"
    };

    $scope.addLine = function () {
        $scope.chat.addLine($scope.lineText);
        $scope.lines.push({text:$scope.lineText});
        $scope.lineText = "";
    };
...
}

In the addLinefunction $scope.lineTextis undefined, this can be resolved by adding ng-controller="HomeCtrl"to partial1.html, however it causes the controller to be called twice. What am I missing here?

addLine函数$scope.lineTextis 中undefined,这可以通过添加ng-controller="HomeCtrl"到来解决partial1.html,但是它会导致控制器被调用两次。我在这里缺少什么?

采纳答案by Renan Tomal Fernandes

This is because of ng-includewhich creates a new child scope, so $scope.lineTextisn't changed. I think that thisrefers to the current scope, so this.lineTextshould be set.

这是因为ng-include它创建了一个新的子作用域,所以$scope.lineText不会改变。我认为是this指当前范围,所以this.lineText应该设置。

回答by Mark Rajcok

As @Renan mentioned, ng-include creates a new child scope. This scope prototypically inherits (see dashed lines below) from the HomeCtrl scope. ng-model="lineText"actually creates a primitive scope property on the child scope, not HomeCtrl's scope. This child scope is not accessible to the parent/HomeCtrl scope:

正如@Renan 提到的,ng-include 创建了一个新的子作用域。这个范围原型从 HomeCtrl 范围继承(见下面的虚线)。 ng-model="lineText"实际上在子作用域上创建了一个原始作用域属性,而不是 HomeCtrl 的作用域。父/HomeCtrl 范围无法访问此子范围:

ng-include scope

ng-include 范围

To store what the user typed into HomeCtrl's $scope.lines array, I suggest you pass the value to the addLine function:

要将用户输入的内容存储到 HomeCtrl 的 $scope.lines 数组中,我建议您将值传递给 addLine 函数:

 <form ng-submit="addLine(lineText)">

In addition, since lineText is owned by the ngInclude scope/partial, I feel it should be responsible for clearing it:

另外,由于 lineText 归 ngInclude scope/partial 所有,我觉得它应该负责清除它:

 <form ng-submit="addLine(lineText); lineText=''">

Function addLine() would thus become:

函数 addLine() 将因此变为:

$scope.addLine = function(lineText) {
    $scope.chat.addLine(lineText);
    $scope.lines.push({
        text: lineText
    });
};

Fiddle.

小提琴

Alternatives:

备择方案:

  • define an object property on HomeCtrl's $scope, and use that in the partial: ng-model="someObj.lineText; fiddle
  • not recommended, this is more of a hack: use $parent in the partial to create/access a lineTextproperty on the HomeCtrl $scope: ?ng-model="$parent.lineText"; fiddle
  • 定义上HomeCtrl的$范围的对象属性,并使用在部分:ng-model="someObj.lineText; 小提琴
  • 不推荐,这更像是一个黑客:在部分中使用 $parent 来创建/访问lineTextHomeCtrl $scope 上的属性:?ng-model="$parent.lineText"; 小提琴

It is a bit involved to explain why the above two alternatives work, but it is fully explained here: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

解释为什么上述两种替代方法工作有点复杂,但在这里得到了充分解释:AngularJS 中范围原型/原型继承的细微差别是什么?

I don't recommend using thisin the addLine() function. It becomes much less clear which scope is being accessed/manipulated.

我不建议this在 addLine() 函数中使用。正在访问/操作哪个范围变得不太清楚。

回答by ErwinGO

Instead of using thisas the accepted answer suggests, use $parentinstead. So in your partial1.htmlyou'll have:

不要this像接受的答案建议的那样使用,$parent而是使用。所以在你的partial1.html你将拥有:

<form ng-submit="$parent.addLine()">
    <input type="text" ng-model="$parent.lineText" size="30" placeholder="Type your message here">
</form>

If you want to learn more about the scope in ng-includeor other directives, check this out: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

如果您想了解有关 inng-include或其他指令的范围的更多信息,请查看:https: //github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

回答by wascou

I've figured out how to work around this issue without mixing parent and sub scope data. Set a ng-ifon the the ng-includeelement and set it to a scope variable. For example :

我已经想出了如何在不混合父级和子级数据的情况下解决这个问题。ng-ifng-include元素上设置 a并将其设置为范围变量。例如 :

<div ng-include="{{ template }}" ng-if="show"/>

In your controller, when you have set all the data you need in your sub scope, then set show to true. The ng-includewill copy at this moment the data set in your scope and set it in your sub scope.

在您的控制器中,当您在子作用域中设置了所需的所有数据后,将 show 设置为true。此时ng-include将复制在您的范围中设置的数据并将其设置在您的子范围中。

The rule of thumb is to reduce scope data deeper the scope are, else you have this situation.

经验法则是减少范围数据更深的范围,否则你会遇到这种情况。

Max

最大限度