AngularJS 1.4:如何使用bindToController和controllerAs语法创建双向绑定

4

好的,这真的很让我烦恼。我有一个带有隔离作用域的指令,使用controllerAs语法和bindToController:

function exampleDirectiveFactory() {
    var bindings = {
        foo: '=',
        bar: '@'
    }

    return {
        bindToController: true,
        controller      : 'ExampleController',
        controllerAs    : 'vm',
        scope           : bindings,
        template        : 'foo = {{ vm.foo }}<br />bar = {{ vm.bar }}'
    };
}

假设使用如下:
<example foo="FOO" bar="BAR"></example>

我期望 vm.foo 的值与 foo 属性的值双向绑定。但实际上它是 undefined

vm.bar 的值等于 HTML 元素的 bar 属性值,这一点我是期望的。

当我试图使用过滤器更改 vm.bar 的值时,没有任何更改被保留下来。

当我将经过过滤器处理后的 vm.bar 值存储到一个新变量 vm.baz 中,它能够按预期工作。

这里是一个演示

因此我的问题有两个部分:

A)为什么在使用 '=' 时 vm.foo 的值为 undefined?

B)为什么我不能在控制器的作用域内更改 vm.bar 的值,即使该更改不会传播到 HTML 元素属性(因为我使用的是 '@')?

1个回答

11

1.4 改变了 bindToController 的工作方式。虽然看起来 Angular 的文档仍然将该字段称之为 true/false。现在它可以像 scope 属性一样接受一个对象,其中属性表示您想要绑定的内容以及如何绑定它。

function exampleDirectiveFactory() {
    var bindings = {
        foo: '=',
        bar: '@'
    }

    return {
        bindToController: bindings, //<-- things that will be bound
        controller      : 'ExampleController',
        controllerAs    : 'vm',
        scope           : {}, //<-- isolated scope
        template        : 'foo = {{ vm.foo }}<br />bar = {{ vm.bar }}'
    };
}
此外,在您的代码片段中,FOO在父作用域上是未定义的,因此当它绑定时,它将把该“未定义”值传递到指令的绑定控制器作用域中。
进一步阅读: 这种新的bindToController语法允许指令不是具有隔离作用域,但仍然可以确定要绑定的内容。您实际上可以在指令上将scope设置为true,这样就会创建一个从其祖先继承的新子作用域。

感谢您的回复。我确实阅读了有关1.4版本中bindToController更改的内容,并尝试使用该语法进行实验。但根据您的答案或我的理解,这应该导致vm.foo等于MAIN.FOO,但实际上并不是这样的:http://jsfiddle.net/sscovil/r4esw0a0/ - Shaun Scovil
你正在指定你指令中的范围变量 FOO (通过元素上的 foo="FOO" 属性)。 你必须定义 FOO。http://jsfiddle.net/r4esw0a0/2/ 另外,你不应该将所有控制器都命名为 vm,这违反了使用 controllerAs 的目的。 http://jsfiddle.net/r4esw0a0/3/ - TheSharpieOne
1
我开始明白这里发生了什么。通过使用“'='”,我意味着属性的值是一个变量名,而不是一个字符串字面量...相反,当我使用“'@'”时,它绑定了属性的字符串值。但是为什么我不能改变在这个例子中绑定的vm.foo或vm.bar的值呢?http://jsfiddle.net/sscovil/960zLavt/ - Shaun Scovil
使用双向绑定时,必须要有一个可分配的变量进行绑定,使用字符串表达式是不可分配的。为了更明显地说明:你所做的类似于尝试绑定到 foo="1+1"... 当然,它等于2,这是单向绑定,但是如何才能使双向绑定将一个值返回到 foo 中呢?https://docs.angularjs.org/error/$compile/nonassign?p0=%27FOO%27&p1=example - TheSharpieOne
1
谢谢你和我一起讨论。这些评论更好地回答了我的问题...你可能想把它们复制到答案中以增加可见性。话虽如此,我会接受并非常感激你的帮助。干杯! - Shaun Scovil
我的解决方法是在使用bindToController时,在指令中标记scope:true。这允许双向绑定。 - Tarun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接