AngularJS-为什么使用;控制器作为虚拟机;?

AngularJS-为什么使用;控制器作为虚拟机;?,angularjs,Angularjs,整个周末,我都很苦恼,不明白为什么父控制器的功能没有被子控制器识别 我很快意识到将我的控制器作为vm是原因: <div data-ng-controller="ParentCtrl as vm"> <div data-ng-controller="Child1 as vm"></div> <div data-ng-controller="Child2 as vm"></div> </div> 当然,现在

整个周末,我都很苦恼,不明白为什么父控制器的功能没有被子控制器识别

我很快意识到将我的控制器作为vm是原因:

 <div data-ng-controller="ParentCtrl as vm">
   <div data-ng-controller="Child1 as vm"></div>
   <div data-ng-controller="Child2 as vm"></div>
 </div>

当然,现在看来很明显,child1和child2都不会在ParentCtrl中看到函数,如果我使用之前的模式,即不使用vm,而是使用$scope,那么一切都会很好

因此,我的问题是“使用“vm”方法对任何人都有什么好处?如果它优于不使用它,那么如何调用ParentCtrl中的函数调用


谢谢你

我以前使用controller作为vm语法,但最近我已经不再使用它了。我发现,当我使用作用域隔离构建带有嵌套指令的复杂页面时,使用传统的$scope方法要容易得多

您的问题我想了一会儿。我能看到的唯一真正的价值是,当您在页面中使用嵌套控制器时,您可以获得对每个作用域的语义引用,以便您的标记更易于阅读。例如:

<div ng-controller="CustomersCtrl as customers">
    <div ng-controller="OrdersCtrl as orders">
         <p>Showing{{customers.model.length}} customers with a total of {{orders.model.length}} orders</p>
    </div>
</div>

显示{{customers.model.length}}个客户,总共有{{orders.model.length}个订单


除此之外,我没有真正看到值,如果您像我一样喜欢使用指令嵌套,那么该值很快就会被imho取消。

我认为它的一个主要优点是,它会自动确保您的绑定中有一个
。因为Angular中的经验法则是,如果您没有
I在你的束缚下,你可能会射中自己的脚

假设您有:

<input ng-model="foo" />
这将避免数据绑定无法按预期工作的潜在问题


这背后的原因在于原型继承在JavaScript中的工作方式,这里已经非常详细地描述了这一点:

您在这个示例中遇到的问题并不是由于使用了控制器作为语法;而是由于您的嵌套对象由于命名而隐藏了父对象

控制器作为选项在广泛使用编译为JavaScript的其他语言(如CoffeeScript或TypeScript)时非常有用。由于不需要$scope注入,它还允许您创建可与非角度组件交换的更轻量级控制器。它只是一种替代语法,但如果愿意,您仍然可以使用$scope


这里真正的问题是,为什么编写了控制器示例作为语法的人决定使用“as-vm”。从技术上讲,该语法旨在提供MVVM风格的编码体验,因此使用“as-vm”“也许有道理,但这暴露了你所看到的问题。父控制器是一个名为
vm
的对象,而子对象也是名为
vm
,因此子对象是从视图中隐藏父对象。相反,如果以不同的方式命名对象,则子对象在访问父对象时不会有任何问题,而且在代码中,您使用的属性来自哪个对象实际上是非常清楚的

将控制器用作语法的一个优点是,它允许您将控制器定义为一个简单的javascript构造函数,其属性和函数直接从实例化对象公开,而不是从$scope公开

例如:

function MyController() {

    var ctl = this;

    ctl.message = 'You have not clicked anything yet.';

    ctl.onClick = function() {
        ctl.message = 'You clicked something.';
    };

    return ctl;
}

...

myModule.controller('MyController', MyController);

...

<div ng-controller="MyController as vm">
    <span>{{vm.message}}</span>
    <button ng-click="vm.onClick()">Click Me</button>
</div>
函数MyController(){
var ctl=这个;
ctl.message='您尚未单击任何内容';
ctl.onClick=函数(){
ctl.message='您单击了某些内容';
};
返回ctl;
}
...
myModule.controller('MyController',MyController);
...
{{vm.message}
点击我
请注意,我们可以使用一个简单的旧javascript控制器,而不必绑定到angular。对于需要附加依赖项(如$scope或其他服务)的场景,您仍然可以轻松地将它们传递给构造函数,但这种模式会减少直接在$scope上的混乱,并且还解决了直接在作用域上设置变量时隐藏变量的问题

归根结底,这实际上是一个偏好的问题,但对我来说,我真的很喜欢不必直接在作用域上定义所有内容,并且尽可能地将我的控制器视为任何旧的javascript对象

以下是一篇关于控制器as使用的优秀文章:

据我所知,使用“控制器作为vm”语法的主要原因是angularjs中的控制器实际上充当模型(封装数据并提供行为)或视图模型(将数据暴露于html)


在大多数情况下,它工作得很好,但我遇到的一个主要问题是,很难从子控制器访问父控制器中的数据,而且可能的解决方案()并不优雅。

我以前见过“as”语法,但从未使用过它。我不希望我的视图直接/按名称访问控制器。另外,从封装的角度来看,Child1或Child2不应该知道有关父控制器的任何信息;因此,不应调用父控制器上的函数。控制器之间的通信应通过修改共享服务进行;或者使用emit作为事件调度器。因此,Reboog,如果我理解正确,您的意见是不使用“vm”,但无论如何,不要依赖$scope,并且使用emit,不管孩子们可以通过scope访问父函数,对吗?是的,这是我的观点和我一直采取的方法。可能有一些问题我还不了解,但我还没有遇到任何限制/问题。
function MyController() {

    var ctl = this;

    ctl.message = 'You have not clicked anything yet.';

    ctl.onClick = function() {
        ctl.message = 'You clicked something.';
    };

    return ctl;
}

...

myModule.controller('MyController', MyController);

...

<div ng-controller="MyController as vm">
    <span>{{vm.message}}</span>
    <button ng-click="vm.onClick()">Click Me</button>
</div>