在{{}}(花括号)内部使用函数调用是一种好的实践吗?

15

在{{}}(花括号)内使用函数调用是一种好的做法吗?

有没有办法在组件内完成这个操作,例如(也许使用 ngOnChanges 或其他什么...)

模板

<div class="container">
    {{ bootstrap() }}
    {{ validate() }}  
    <textarea class="form-control">{{ fullHtml }}</textarea>
    <button (click)="copy()" class="btn btn-primary">Click to Copy HTML</button>
    <textarea class="form-control">{{ validator }}</textarea>
    <button (click)="copy()" class="btn btn-warning">Click to Copy Validate</button>

    <button class="btn btn-danger" (click)="add()">Add page and input</button>
</div>

组件

class HomeComponent {
    fullHtml = "";
    validator = "";
    pages = [{
        "name": "Page 1"
    },{
        "name": "Page 2"
    }];

    inputs = [{
        "name": "input_1",
        "required": true
    },{
        "name": "input_2",
        "required": false
    }];

    public bootstrap() {
        this.fullHtml = this.pages.map((page, pageNumber) => {
            return '<div class="row">' +
                page.name +
                '</div>'
        }).join('')
    }

    public validate(){
        this.validator = this.inputs.map((input, i) => {
            return '"' + input.name + '" => [' + (input.required? 'required': 'nullable') + '],\n';
        }).join('')
    }

    public copy(){
        alert("under construction");
    }

    public add(){
        this.pages.push({
            name: "page 3"
        });
        this.inputs.push({
            "name": "input_3",
            "required": true
        });
    }
}

https://jsfiddle.net/1hk7knwq/10283/

ps. 我需要在文本区域中显示HTML内容,因此我正在组件内部进行HTML编写。


我可能会避免这样做,但如果你必须这样做,请不要忘记对其进行清理。 - arbghl
我认为JavaScript标签在这里不相关(可能是TypeScript标签)。 - Pac0
3个回答

11

对于你的问题答案是:这要看情况。

如果函数的执行时间很短,那就没问题。但是如果函数包含了许多复杂的计算需要较长时间才能完成,那么可能会影响用户体验。

以下是 Angular 团队在官方文档中提到的:

快速执行

Angular 在每个变更检测周期后执行模板表达式。变更检测周期由许多异步活动触发,例如 promise 解析、http 结果、定时器事件、按键和鼠标移动等。

表达式应该快速完成,否则用户体验可能变差,尤其是在较慢的设备上。当计算值昂贵时,请考虑缓存这些值。

参考文献:https://angular.io/guide/template-syntax#quick-execution


5

在Handlebars(双花括号)中调用函数是合法的。但是,如果您在该函数中使用console.log,则会发现它经常被调用,因此最好尽可能保持轻量级,或者如果它是一个纯函数,则对其进行记忆化处理。请参见Lodash memoize

如果该函数没有参数(或可以重写为不接受参数),则可以使用TypeScript getter代替,例如:

get something() {
  // do some code here
  // return 5
}

现在你可以在HTML模板中使用{{ something }}。值得注意的是,放置一个console.log在这里以查看是否调用次数少于函数等价物。


3
Angular有一个非常方便的功能,可以直接将数据绑定到方法调用的结果上。通过使用Angular的模板绑定语法来将属性分配给一个方法,每次变更检测周期都会重新计算结果。虽然这很方便,但也会增加这些计算结果在每个变更检测周期的成本。例如,当将绑定到一个ngFor时,这种成本有可能极大地影响应用程序的响应性。通常有两种方法来提高性能:预计算结果或将方法实现为纯管道。
当ngFor与方法调用相结合以基于每个显示条目执行计算时,最常见的情况就是这样。通常有机会根据需要计算额外的属性,而不是在每个变更检测中重新计算显示值。例如,请考虑以下代码:
<ul>
  <li *ngFor="let instractor of instractorList">
    <span>Upccoming classes {{numClasses(instractor)}}</span>
  </li>
</ul>

每次变更检测循环都会执行numClasses,将其绑定到简单的模板中,以便在instructorList的每个条目上执行

模板的后备组件类在没有预处理数据的情况下提供其数据。以下实现定义了从模板调用的方法

<ul>
  <li *ngFor="let instractor of instractorList">
    <span>Upccoming classes {{instractor.numClasses}}</span>
  </li>
</ul>

在这个例子中,只有在列表发生变化时才会重新计算对象属性。这种情况发生的频率明显比每个变更检测周期要少,甚至可能永远不会再次发生。这是处理这种情况最高效的方法,但有时可能很难实现。

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