Angular 进阶之五: Signals到底用不用?

Angular 在V16的时候推出了Signals,在17正式作为主打功能之一强烈推荐,看过了各种博主的各种科普文章也没说明白,到底这东西值不值得用?毕竟项目大了,重构代码也不是闹着玩儿的。各种科普文章主要在说两点:

1. 用了性能提高

2. 用了方便,你改一个,使用的地方自动就获得通知。(听起来和Rxjs的Observer一样)

在Angular项目日常开发过程中主要的矛盾其实就两个。

1. Object的成员改了,不会触发子组件(component)的ngOnChange。需要手动调用detectChanges。

2. 性能,其中之一就是html template里头不能用function,不然会不停的调用。

这也是Signals可能可以解决的两个问题。我们用下面一个简单的例子来说明。

import { Component, signal, computed } from '@angular/core';

interface Member {
    id: number;
    name: string;
    value: number;
}

@Component({
    template: `<div>
        <p>{{targetsSignal()[0].name}} has {{targetsSignal()[0].value}}</p>
        <button (click)="increase()">Increase</button>
        
        <button (click)="decrease()" [disabled]="canDecrease()">Decrease</button>
        <p>Name starts with M</p>
        <div *ngFor="let member of computedNames()">{{member.id}} - {{member.name}}</div>
        
        <div style="height: 300px; width: 300px; background-color: #2f487e;" (mousemove)="onMousemove()"></div>
        <test-signal-sub [members]="targetsSignal()"></test-signal-sub>
    </div>`,
    selector: 'test-signal',
})

export class SignalComponent {
    counter = 0;
    counter1 = 0;

    targets: Member[] = [{name: 'Maria', id: 1, value: 1}, {name: 'Michel', id: 2, value: 1}, {name: 'Jack', id: 3, value: 1}, {name: 'John', id: 4, value: 1}, 
                {name: 'Sam', id: 5, value: 1}, {name: 'Mila', id: 6, value: 1}];
    readonly targetsSignal = signal<Member[]>(this.targets);
    
    computedNames = computed(() => {
        this.counter++
        console.log("namesFiltered() called! " + this.counter + " times!");
        return this.targetsSignal().filter(item => item.name.startsWith('M'));
    })

    constructor() {

    }

    onMousemove() {
        // console.log('Mouse moved');
    }

    increase() {
        const newTargets = [].concat(this.targetsSignal());
        newTargets[0].value += 1;
        this.targetsSignal.set(newTargets);
    }

    decrease() {
        this.targetsSignal.update(val => { 
            val[0].value -= 1;
            return val;
        });
    }

    canDecrease() {
        this.counter1++;
        console.log("canDecrease() called! " + this.counter1 + " times!");
        return this.targetsSignal()[0].value <= 0;
    }
}
import { Component, OnChanges, SimpleChanges, Input } from '@angular/core';

@Component({
    template: `<div>
        <p>Sub signal component below:</p>
        <p>{{name}} preferred {{color}}</p>
        <p>{{members[0].name}} has value {{members[0].value}}</p>
    </div>`,
    selector: 'test-signal-sub',
})

export class SignalSubComponent implements OnChanges {
    @Input() members: any;
    color = '';
    name = '';
    readonly preferedColor = [{name: 'Maria', color: 'red'}, {name: 'Michel', color: 'blue'}, {name: 'Jack', color: 'yellow'}, {name: 'John', color: 'green'}, 
    {name: 'Sam', color: 'black'}, {name: 'Mila', color: 'white'}];
    constructor() {

    }

    ngOnChanges(changes: SimpleChanges): void {
        if (changes.members?.previousValue !== changes.members?.currentValue) {
            const index = changes.members?.currentValue[0].value % changes.members?.currentValue.length ?? 0;
            this.color = this.preferedColor[index].color;
            this.name = this.preferedColor[index].name;
        }
    }
}

两个组件,父组件的html template里绑定了computedNames,和canDecrease,从外表也看不出来区别,但是如果使用鼠标在蓝色区域晃动,控制台就会打印canDecrease被不停调用,computedNames没事,这个例子说明了Signal可以被用在html template里,解决的主要场景之一就是button的状态,现实中不都是理想情况,button属于form,一个valid状态就解决了button是不是disable。很多情况button的[disabled]后面跟了一串判断,"a || b || !c || d"等等,现在有了signal就直接一个signal就好了。但是重构时需要把涉及到的a,b,c,d这些成员都改成signal。这就可能需要一次重构一整个component。

在上面例子中increase使用set每次用新数组更新signal,decrease使用update,每次只改原来的数组,在子组件中,会看到,increase会触发子组件的ngOnChange,但是decrease不会。这就和原来没什么区别了。还是Angular的老问题,对象引用不变,成员变,无法触发子组件的ngOnChange。

所以,Signals也没有宣传中吹的天花乱坠那么厉害,解决的问题有限,它更像是一个Rxjs的一个封装,一个别名,一个简化版本。是不是要重构代码就看大家自己的需求了。

PS:Angular在开发signal component和双向绑定的signal,都在他们的任务列表中,等这两个发布可能会带来更多的好处,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/263269.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pake协议传输文件magic-wormhole

pake协议传输文件magic-wormhole 1 magic-wormhole简介其他介绍 2 安装magic-wormhole3 使用示范发送文件指定虫洞码长度 接收文件 1 magic-wormhole简介 16.7k star 强推&#xff0c;丝滑、简洁、安全的开源工具——magic-wormhole 项目地址&#xff1a;https://github.com/…

Android应用-flutter使用Positioned将控件定位到底部中间

文章目录 场景描述示例解释 场景描述 要将Positioned定位到屏幕底部中间的位置&#xff0c;你可以使用MediaQuery来获取屏幕的高度&#xff0c;然后设置Positioned的bottom属性和left或right属性&#xff0c;一般我们left和right都会设置一个值让控制置于合适的位置&#xff0…

Bert-vits2-2.3-Final,Bert-vits2最终版一键整合包(复刻生化危机艾达王)

近日&#xff0c;Bert-vits2发布了最新的版本2.3-final&#xff0c;意为最终版&#xff0c;修复了一些已知的bug&#xff0c;添加基于 WavLM 的 Discriminator&#xff08;来源于 StyleTTS2&#xff09;&#xff0c;令人意外的是&#xff0c;因情感控制效果不佳&#xff0c;去除…

【大模型】快速体验百度智能云千帆AppBuilder搭建知识库与小助手

文章目录 前言千帆AppBuilder什么是千帆AppBuilderAppBuilder能做什么 体验千帆AppBuilderJava知识库高考作文小助手 总结 前言 前天&#xff0c;在【百度智能云智算大会】上&#xff0c;百度智能云千帆AppBuilder正式开放服务。这是一个AI原生应用开发工作台&#xff0c;可以…

计算机网络:应用层

0 本节主要内容 问题描述 解决思路 1 问题描述 不同的网络服务&#xff1a; DNS&#xff1a;用来把人们使用的机器名字&#xff08;域名&#xff09;转换为 IP 地址&#xff1b;DHCP&#xff1a;允许一台计算机加入网络和获取 IP 地址&#xff0c;而不用手工配置&#xff1…

【DWJ_1703225514】基于Sklearn航空公司服务质量分析

【Talk is cheap】 # 导入库 import warnings warnings.filterwarnings(ignore)import pandas as pd import seaborn as sns import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False %matplotlib inlinefrom skl…

华为科技:辉煌发展、问题应对与未来战略

导言 作为全球领先的科技公司之一&#xff0c;华为经历了辉煌的发展历程。本文将深入探讨华为科技的发展过程、遇到的问题及解决过程、未来的可用范围&#xff0c;以及在各国的应用和未来的研究趋势。同时&#xff0c;分析在哪些领域华为能够取胜&#xff0c;以及在哪些方面发力…

文献管理软件EndNote X9 mac功能介绍

EndNote X9 for Mac是一款文献管理软件&#xff0c;不仅可以让您免于手动收集和整理您的研究资料和格式化书目的繁琐工作&#xff0c;还可以让您在与同事协调时更加轻松自如。让你的团队专注科研&#xff0c;更高效的共享文献开展协作。 EndNote X9 for Mac功能介绍 引文报告 …

数据结构和算法-红黑树(定义 性质 查找 插入 删除)

文章目录 红黑树的定义和性质为什么要发明红黑树&#xff1f;红黑树怎么考总览红黑树的定义实例&#xff1a;一颗红黑树练习&#xff1a;是否符合红黑树的要求一种可能的出题思路补充概念&#xff1a;节点黑高 红黑树的性质 红黑树的查找红黑树的插入实例小结与黑高相关的理论 …

深入浅出:Swagger annotations (注解)在API文档中的应用

Swagger 提供的注解集是其框架中定义 API 规范和文档的重要工具。这些注解在代码里标注重要部分&#xff0c;为 Swagger 的解析工作铺路&#xff0c;进而生成详尽的 API 文档。开发者编写的注释能够被转换成直观的文档&#xff0c;并展现API端点、参数和响应等信息。这不仅提升…

创新固定资产管理方式:易点易动集成企业微信的全新解决方案

在当今竞争激烈的商业环境中&#xff0c;高效的固定资产管理对于企业的成功至关重要。然而&#xff0c;传统的资产管理方式往往繁琐、容易出错&#xff0c;并且缺乏实时性和准确性。为了解决这些挑战&#xff0c;易点易动与企业微信进行了集成合作&#xff0c;推出了一种全新的…

Enge问题解决教程

目录 解决问题的一般步骤&#xff1a; 针对"Enge问题"的具体建议&#xff1a; 以下是一些普遍适用的解决问题的方法&#xff1a; 以下是一些更深入的Enge浏览器问题和解决办法&#xff1a; 浏览器性能问题&#xff1a; 浏览器插件与网站冲突&#xff1a; 浏览…

输电线路定位:应对复杂环境,确保电力传输畅通无阻

在现代社会&#xff0c;电力作为我们生活和工业生产的重要能源&#xff0c;其安全、稳定、高效的传输显得尤为重要。而输电线路的定位与监测&#xff0c;正是保障电力传输畅通无阻的关键环节。恒峰智慧科技将详细介绍输电线路分布式故障定位及隐患监测装置HFP-GZS2000的技术原理…

RabbitMQ 常用知识点总结,纯手绘23张图带你拿下

请访问原文 Java面试必备&#xff01;RabbitMQ 常用知识点总结&#xff0c;纯手绘23张图带你拿下 - 知乎 思维导航&#xff1a; 基础 为什么使用 MQ&#xff1f;MQ缺点几种 MQ 实现总结完整架构图RabbitMQ 六种工作模式 1、Simple 简单模式2、work 工作模式3、publish/subsc…

阻塞 IO(BIO)

文章目录 阻塞 IO(BIO)模型等待队列头init_waitqueue_headDECLARE_WAIT_QUEUE_HEAD 等待队列项使用方法驱动程序应用程序模块使用参考 阻塞 IO(BIO) 模型 等待队列是内核实现阻塞和唤醒的内核机制。 等待队列以循环链表为基础结构&#xff0c;链表头和链表项分别为等待队列头和…

Notepad++:多行数据操作

1&#xff09;删除关键字之后&#xff08;或之前&#xff09;的所有字符 删除s之后&#xff08;包含s&#xff09;的所有内容&#xff1b;快捷键&#xff1a;s.*$ 替换成功 删除s之前&#xff08;包含s&#xff09;的所有内容&#xff1b;快捷键&#xff1a;^.*s 2&#xff09…

ssh远程管理服务

什么是ssh SSH是一种加密的网络协议&#xff0c;用于在不安全的网络中安全地传输数据。它允许用户通过一个安全的通道连接到远程计算机&#xff0c;并在该通道上执行各种网络服务&#xff0c;例如远程登录和文件传输。 SSH使用公钥加密技术来验证远程计算机的身份&#xff0c;并…

NXP iMX8MM 通过 TFTP和 NFS 启动示例

By Toradex秦海 1). 简介 嵌入式 Linux 设备开发调试时候为了方便部署各种配置和修改常用的一种方法就是通过网络启动&#xff0c;具体就是将 Linux Kernel&#xff08;以及 Device tree/Device Tree overlays) 从开发主机的 TFTP 服务加载&#xff0c; Linux rootfs 通过开发…

mysql SQL执行超时问题

show variables like max_execution_time 使用这个命令查看了&#xff0c;没有设置sql执行超时时间&#xff0c;那么大概率问题就出在阿里的Druid数据库连接池出了问题 尝试着socketTimeout由60000毫秒改成10000毫秒&#xff0c;果然执行了十几秒就超时报错了 socketTime…

【JS】按照a>b>c>d>e>f的优先级,将a,b,c,d,e,f元素进行筛选,选出三个不为空字符的元素进行字符拼接

设计思路&#xff1a; 1、定义一个数组&#xff0c;把元素按照优先级进行排序&#xff1b; 2、 使用 filter() 方法过滤掉空字符串元素&#xff0c;得到一个新的数组; 3、在排序函数中&#xff0c;循环数组&#xff0c;使用 indexOf() 方法获取元素 a 和 b 在数组中的索引&a…