【问题标题】:Unusual behaviour of ngForngFor 的异常行为
【发布时间】:2018-03-14 02:12:30
【问题描述】:

今天我在尝试 Angular 指令 ngFor。我面临的问题是,当我选择任何复选框(例如 0)并单击“下一个”时,如果下一个问题也与我在上一个问题中选择的选项(0)相同,那么它将自动检查,我不知识?? [如果任何两个或多个连续问题没有至少一个相同的选项,则不会出现此行为。 ]。我希望这是有道理的。这是我的plunker

模板:

    {{question}}
    <div *ngFor="let option of options">
      <input type="checkbox">{{option}}<br>
    </div>

  <button (click)="onNext()">next</button>

Component.ts

export class App implements OnInit {
    private questionPaper = {
        questions: [{
                _id: "59d1cbd4f8a709358c045696",
                question: "2 + 3",
                __v: 0,
                answers: [
                    "5"
                ],
                options: [
                    "0",
                    "1",
                    "5",
                    "3",
                    "6"
                ]
            },
            {
                _id: "59d1cbf7f8a709358c045698",
                question: "1 * 3",
                __v: 0,
                answers: [
                    "3"
                ],
                options: [
                    "1",
                    "3",
                    "0",
                    "4"
                ]
            },
            {
                _id: "59d1cc18f8a709358c045699",
                question: "3 - 3",
                __v: 0,
                answers: [
                    "0"
                ],
                options: [
                    "3",
                    "0",
                    "6",
                    "4",
                    "7"
                ]
            },
            {
                _id: "59d1cc3ef8a709358c04569a",
                question: "6 - 4",
                __v: 0,
                answers: [
                    "2"
                ],
                options: [
                    "2",
                    "3",
                    "4",
                    "0",
                    "6"
                ]
            },
            {
                _id: "59d1cc71f8a709358c04569b",
                question: "4 * 8",
                __v: 0,
                answers: [
                    "32"
                ],
                options: [
                    "4",
                    "8",
                    "12",
                    "32",
                    "23"
                ]
            },
            {
                _id: "59d1cc96f8a709358c04569c",
                question: "0 * 1",
                __v: 0,
                answers: [
                    "0"
                ],
                options: [
                    "0",
                    "1",
                    "10",
                    "-1",
                    "4"
                ]
            },
            {
                _id: "59d1cccdf8a709358c04569d",
                question: "6 + 6",
                __v: 0,
                answers: [
                    "12"
                ],
                options: [
                    "6",
                    "12",
                    "21",
                    "0"
                ]
            },
            {
                _id: "59d1fb6a253c5270115f4ced",
                question: "1 + 10",
                __v: 0,
                answers: [
                    "11"
                ],
                options: [
                    "11"
                ]
            }
        ]
    };

    private question;
    private options = [];
    private currentQuesNumber = 1;
    onInit() {}
    constructor() {
        this.question = this.questionPaper.questions[0].question;
        this.options = this.questionPaper.questions[0].options;

    }

    onNext() {

        if (this.currentQuesNumber >= this.questionPaper.questions.length) {
            this.loadQuestion(this.questions.length);

        } else {

            this.currentQuesNumber = this.currentQuesNumber + 1;
            this.loadQuestion(this.currentQuesNumber);

        }
    }



    loadQuestion(quesNumbToLoad) {
        if (quesNumbToLoad > 0 && quesNumbToLoad <= this.questionPaper.questions.length) {
            this.question = this.questionPaper.questions[quesNumbToLoad - 1].question;

            this.options = this.questionPaper.questions[quesNumbToLoad - 1].options;
        }

    }

}

【问题讨论】:

    标签: angular typescript ngfor


    【解决方案1】:

    这是缩进行为,因为 Angular 会根据值的 对象标识 重新使用其 ngForOf-directive 中的 DOM 元素以获得更好的性能。因此,在您的情况下,值是 string,这意味着 object identity 是它的值。

    因此,如果选项的值在两个问题之间相同,则 angular 正在重用 DOM 元素。因为使用了相同的 DOM 元素,所以复选框状态仍然是 checked

    如果您希望 angular 不在 ngForOf-directive 中重用 DOM 元素,您必须提供一个始终返回某种 unqiue id 的函数(例如当前日期时间)并将其应用于ngForOf 指令(短语法trackBy)的ngForTrackBy 输入。


    例如:

    组件

    public trackById(index: number, value: any) {
      return Date.now();
    }
    

    组件模板

    *ngFor="let option of options;trackBy:trackById"
    

    或:

    <ng-template ngFor let-option [ngForOf]="options"[ngForTrackBy]="trackByFn">
    </ng-template>
    

    现在 Angular 不会为此 ngForOf-directive 重用任何 DOM 元素。

    更多关于ngForOf-directive 变更传播的信息可以在docs 中找到(以及其他一些有用的东西)


    注意:这也适用于相反的方式。例如,如果您有一些不可变的数据并且您不希望在每次更改时都创建新的 DOM 元素。只需提供一个返回项目当前索引的函数。这将强制 angular 重用您的 ngForOf-directive 中的每个现有 DOM 元素,而不管 对象身份如何。

    【讨论】:

    • @cyrix 感谢您的帮助,但现在我面临另一个问题。我将 *ngFor 与 md-checkbox(角度材料)一起使用,但在应用 'trackBy' 功能后,我根本无法选择任何复选框。 :(
    猜你喜欢
    • 1970-01-01
    • 2020-02-19
    • 2020-05-02
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多