使用value和ngValue的区别:SELECT --> OPTION

7
我最近发现在SELECT的OPTION部分有一个ngValue的替代品,用于value属性。关于这个问题,文档中真的缺乏相关说明(我只找到了一个链接:https://angular.io/docs/ts/latest/api/forms/index/NgSelectOption-directive.html)。不管怎样,当您使用对象来处理ngModel时,可以使用ngValue并且会很好地工作。否则,只有例如ID会被更新。如果我们只是使用字符串数组,则value就足够了。以下是示例:
{{myModel | json}}
<select [(ngModel)]="myModel">
  <option *ngFor="let i of items" [ngValue]="i">{{i.value}}</option>
</select>

<br /><br />

{{mySimpleModel}}
<select [(ngModel)]="mySimpleModel">
  <option *ngFor="let i of simpleItems" [value]="i">{{i}}</option>
</select>

虽然这个功能可以正常工作,但是两者之间存在明显的区别:如果使用 ngValue ,预定义的值不会在下拉列表中被选中,而对于原始类型来说,在加载时该值会被选中。例如:

items: any[] = [{id: 1, value: 'item1'}, {id: 2, value: 'item2'}, {id: 3, value: 'item3'}];
myModel: any = {id: this.items[1].id , value: this.items[1].value};

simpleItems: string[] = ['item1', 'item2', 'item3'];
mySimpleModel: string = this.simpleItems[1];  

点击此处查看示例:https://plnkr.co/edit/JBrtmx7QkPZztBjaqYkS?p=preview 那么,为什么Angular会为字符串设置默认值,而不是对象?最优雅的解决方法是什么?


1
我知道这超出了范围,但你说的很有趣。我一直认为变量类型的输入是一件好事,例如:items: {id: number, value: string}[] = [{id: 1, value: 'item1'}, {id: 2, value: 'item2'}, {id: 3, value: 'item3'}];但你说这是非常错误的。你有什么来源或者可以让我阅读更多相关信息的地方吗?我很好奇! - uglycode
基本上当它不会丢失类型信息时,键入变量是可以的,但在有初始化程序时没有必要。如果类型注释为 any ,则始终严格更差。作为证据,如果您使用 IDE(如 VS Code),请尝试在构造函数或方法中声明和未声明注释的情况下,从 this.myModel 上按 . 键。结果将说明一切。 - Aluan Haddad
例如,如果您编写myModel: any = {id: this.items[1].id , value: this.items[1].value};,则在访问idvalue时将不会获得任何完成,并且编译器不会验证它们是否存在,因为您已经告诉编译器“我知道得更好!”。它还将允许您编写this.myModel.foobar(),TypeScript不会抱怨,因为您覆盖了类型推断。然后,您的程序将在运行时崩溃。如果您删除类型注释,则TypeScript将推断类型为“具有类型为number的id属性和类型为string的value属性的对象”。 - Aluan Haddad
1
如果你想了解源代码,可以观看 TypeScript 的创造者 Anders Hejlsberg 在其首次发布时的介绍视频。https://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript 这一直是该语言的一部分。 - Aluan Haddad
1
根据情况而定。any 是主要问题,但即使有更好的类型,有时推断类型更准确。例如,一个函数在不同的控制流路径上返回 "a""b",会被推断为返回联合类型 "a" | "b"。但我们可能会用更差的 string 进行注释。当类型被重复使用或无法推断时,接口非常好用。此外,注释独立函数和方法的参数是一个好习惯(不要使用 any),但不要注释直接作为回调传递的函数值的参数。 - Aluan Haddad
显示剩余7条评论
2个回答

5
您不需要为此寻找"变通方法"。当您执行此操作时,不需要使用任何特殊技巧或方法。
myModel = {id: this.items[1].id , value: this.items[1].value};

您正在创建一个新对象,该对象具有与 this.items[1] 相同的值,但它并不是相同的对象,而是全新的对象。

const items = [{id: 1, value: 'item1'}, {id: 2, value: 'item2'}, {id: 3, value: 'item3'}]

const myModel = {id: 2, value: 'item2'};

console.log(items[1] === myModel);

那就是你的选择框在

1
谢谢,这解决了我的疑惑。您能否通过删除注释来修复此答案的类型安全性呢?感谢!已点赞! - Aluan Haddad
谢谢,我知道我做错了什么。在使用Angular时,这些对现有对象的引用非常重要,因为我已经有几次经验了。 - uglycode
@uglycode 如果答案对您有帮助,请记得点赞。 - Aluan Haddad
值得一提的是comparewith函数。 - Royi Namir

4
为了使用 [ngValue] 获取默认选中的选项,您可以使用 [compareWith]。 只需在 compareObj 方法中更改正确的比较对象属性即可。
<select [compareWith]="compareObj"  [(ngModel)]="selectedObject">
   <option *ngFor="let object of objects" [ngValue]="object">
      {{object.name}}
   </option>
</select>

compareObj(o1: Object, o2: Object) {
   return o1.id === o2.id;
}

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