Angular 中的状态管理
由于之前一直用的是 Vue 和 React,对 Angular 还不是很熟悉,对于 Vue 或者 React 来说,每一个单独的组件都有它自身的状态,例如 Vue:
export defaut { data() { return { message: "hello world", } } }
它这个状态是响应式的,通过更改 message 的值,能够实时更新页面上对应的组件。
而 Angular 的组件自身是没有状态,需要额外构建一个 service ,通过依赖注入的方式将状态注入到组件中,例如构建一个 ProductService
:
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class ProductService { private cart = []; constructor() { } add(product) { this.cart.push(product); } items() { return this.cart; } clear() { this.cart = []; } pop() { this.cart.pop(); } delete(index) { this.cart.splice(index, 1); } }
将 service 注入到组件中:
import { Component, OnInit } from '@angular/core'; import {ProductService} from '../product.service'; import ProductEntity from '../product/product.entity'; @Component({ selector: 'app-cart', templateUrl: './cart.component.html', styleUrls: ['./cart.component.scss'] }) export class CartComponent implements OnInit { products = []; constructor( private productService: ProductService ) { this.products = this.productService.items(); } ngOnInit() { } addProduct() { console.log('add a product'); const product = new ProductEntity(); product.title = 'title'; product.vendor = 'vendor'; product.amount = 2; product.price = 10.34; product.image = 'https://www.wenjiangs.com/wp-content/uploads/2023/docimg21/67-zpxsgdgbh0r.jpg'; this.productService.add(product); } rmProduct() { console.log('remove a product'); this.productService.pop(); } get total() { let totalPrice = 0; this.products.forEach(product => { totalPrice += product.amount * product.price; }); return totalPrice; } }
这种方式既有好处也有坏处,首先 Angular 这种方式写起来比较繁琐,因为每个组件都要添加对应的 service (这里针对有状态组件而言),因此 Angular 不适合构建大量粒度比较细的组件,而 Vue 和 React 在这方面是强项,不过这种方式也有好处,就是状态与组件分离了,那么组件之间的消息传递就会变得十分简单,不像 Vue, 它如果需要在完全不相关的组件之间传递数据,需要引入消息总线(event bus)或者 Vuex,因为它们的组件之间的状态是独立的,而 Angular 只需要将对应的 service 通过依赖注入注入到不同组件即可。
一些注意项:
获取组件数组索引
<div class="" *ngFor="let product of products; index as i"> <app-product [product]="product" [index]="i"></app-product> </div>
获取特定组件的 event
,例如 input
框:
<div class="amount"> <input type="number" value="{{product.amount}}" (change)="changeAmount(index, $event)"> </div>
这里没有使用双向绑定是因为需要同步更新 service 中的状态。
以上代码的另外一种推荐写法:
<div class="amount"> <input type="number" value="{{product.amount}}" #amount (change)="changeAmount(index, amount.value)"> </div>
应该尽可能使用第二种写法。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论