Signal

Signal new in angular

Signal

基础使用

1
2
3
4
5
6
7
8
9
10
@Component({
template: `
<p>{{ counter() }}</p>
<p>{{ pxCounter() }}</p>
`
})
class AComponent {
counter = signal(0);
pxCounter = computed(() => this.counter() + 'px')
}

pxCounter会追踪counter的变化

更新赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component({
template: `
<p>{{ counter() }}</p>
<p>{{ pxCounter() }}</p>
`
})
class AComponent {
counter = signal(0);
pxCounter = computed(() => this.counter() + 'px')

changeCount() {
// 赋值
this.counter.set(20)
}
}

effect

1
2
3
4
5
6
7
8
9
@Component()
export class CounterComponent {
count = signal(0);

constructor() {
// Tip: 我们不应该在effect中给signal赋值,会导致循环引用
effect(() => {this.count.set(1);}, { allowSignalWrites: true});
}
}
  • 清空signal
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Component()
    export class CounterComponent {
    count = signal(0);

    constructor() {
    const effectRef = effect(() => {this.count.set(1);}, { manualCleanup: true});
    // signal会在组件卸载是自动清空, 如果需要手动清空可以调用此方法
    effectRef.destroy();
    }
    }

在组件传值中使用signal

在angular17中,使用input向子组件传值时会转换类型为signal

  • 使用@Input向子组件传值
    1
    2
    3
    4
    5
    6
    7
    8
    @Component({
    template: `
    <p>{{ val }}</p>
    `
    })
    class AComponent {
    @input() val: string
    }
  • 使用input向子组件传值
    1
    2
    3
    4
    5
    6
    7
    8
    @Component({
    template: `
    <p>{{ val() }}</p>
    `
    })
    class AComponent {
    val = input<string>('')
    }
    使用input向子组件传值会自动转成signal, 所以val的类型不是string,而是Signal<string>

使用 effect() 代替 Onchanges()

  • 使用@Input时,我们使用Onchanges() 生命周期钩子去监听父组件传值的变化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Component({
    template: `
    <p>{{ val }}</p>
    `
    })
    class AComponent implements OnChanges{
    @input() val: string
    ngOnChanges(changes: SimpleChanges): void {
    if(changes['val']){
    // dosomething..
    }
    }
    }
  • 使用 input
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Component({
    template: `
    <p>{{ val() }}</p>
    `
    })
    class AComponent {
    val = input<string>('')
    constructor() {
    effect(() => {
    console.log(`New value: ${this.value()}`);
    });
    }
    }

input的可选参数 required, alias, transform

  • required

    1
    2
    3
    4
    5
    6
    7
    8
    @Component({
    template: `
    <p>{{ val() }}</p>
    `
    })
    class AComponent {
    val = input.required<string>()
    }

    使用required时也不需要设置默认值(因为必填所以会被替换)

  • alias

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Component({ 
    selector: 'a-comp',
    template: `
    <p>{{ val() }}</p>
    `
    })
    class AComponent {
    val = input<string>('abc', { alias: 'val2'})
    }

    <!-- 父组件 -->
    <a-comp [val2]="'test'"></a-comp>

    使用alias时可以设置别名来替换父组件向子组件传递的property

  • transform

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Component({
    template: `
    <p>{{ val() }}</p>
    `
    })
    class AComponent {
    val = input<string>('abc', {
    transform: (value: number) => value + 'px'
    })
    }

    使用transform时可以设置别名来替换父组件向子组件传递的property


本文作者: 孟 虎
本文链接: https://menghu1994.github.io/blog/2024/04/Angular17/signal/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!