就 Angular 是双向数据绑定而言,为什么我应该在 Angular 中使用 Redux?

Her*_*nec 4 redux ngrx angular

据我了解,Redux 主要是为了在 javascript 应用程序中启用双向数据绑定。这对于不是双向数据绑定的框架非常有用,例如 React。但是为什么要在 Angular 中使用它,它本来就已经是双向数据绑定了?

为了说明我的问题,我在本机 Angular 中使用的代码创建了一个存储,以便在两个 Angular 组件之间进行可变状态的通信:

1)商店

import { Injectable } from '@angular/core';
@Injectable({
  providedIn: 'root'
})
export class StoreService {
  customer: any;
  constructor() { }
}
Run Code Online (Sandbox Code Playgroud)

这家商店是一个原生的 Angular 服务,我只声明可变客户(是的,打字会更好,但我想尽可能地缩短它)。

2)异步API SERVIC ë

import { Injectable } from '@angular/core';
import { StoreService } from './store.service'

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  constructor( private store: StoreService ) { }

  getData() {
    setTimeout(()=> {
      this.store.customer = {
        name: 'Bob',
        age: 25
      }
    }, 2000);
  }
}
Run Code Online (Sandbox Code Playgroud)

这个 api 服务只有一种getdata()异步检索客户数据的方法。我可以使用一种http.get方法,在这种情况下,里面的代码setTimeout将是next()可观察订阅函数中的代码。请注意,我直接在以前的商店中实例化了异步进程的返回。

3) 一个使用 store 的组件

import { Component, OnInit } from '@angular/core';
import { ApiService } from '../api.service'
import { StoreService } from '../store.service'

@Component({
  selector: 'app-mycomponent',
  templateUrl: './mycomponent.component.html',
  styleUrls: ['./mycomponent.component.css']
})
export class MycomponentComponent implements OnInit {

  constructor(
    private api: ApiService,
    private store: StoreService
  ) { }

  ngOnInit() {

    this.api.getData();

  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,除了导入服务存储和 api 之外,我只使用了一行代码,即调用数据的那一行。如果其他组件或任何其他服务已经填充商店,则此行将无用(请参阅下面的第二个组件)

4)组件的HTML模板

<ul>
  <li>Name : {{store.customer?.name}}</li>
  <li>Age : {{store.customer?.age}}</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

请注意,我直接在模板中使用 store 来确保与也导入相同 store 的其他组件的双向数据绑定。请注意?.管理异步变量的 elvis 运算符的使用store.customer

5) 修改 store 的其他组件

import { Component, OnInit } from '@angular/core';
import { StoreService } from '../store.service'

@Component({
  selector: 'app-myothercomponent',
  templateUrl: './myothercomponent.component.html',
  styleUrls: ['./myothercomponent.component.css']
})
export class MyothercomponentComponent implements OnInit {   
  constructor(private store: StoreService) { }
}
Run Code Online (Sandbox Code Playgroud)

我只导入商店,不需要任何其他代码行。

6)前一个组件的HTML模板

<p>
  <input type="text" [(ngModel)]="store.customer && store.customer.name">
</p>
Run Code Online (Sandbox Code Playgroud)

请注意由于使用 ngModel 而处理异步的特殊方式。顺便想一下,以多顺序导入 FormsModule 来处理 HTML 中的输入。

现在更改第二个组件中客户名称的值,您将在第一个组件中看到它的直接和即时更改。

Angular 的这种双向数据绑定是如此强大,而且设置和使用如此简单,我真的很想知道为什么我应该使用 Redux 或 NgRx。你能解释一下我为什么要这样做吗?

感谢帮助。

Rea*_*lar 6

据我了解,Redux 主要是为了在 javascript 应用程序中启用双向数据绑定。这对于不是双向数据绑定的框架非常有用,例如 React。但是为什么要在 Angular 中使用它,它本来就已经是双向数据绑定了?

该陈述是错误的,因此其后的所有其他内容都基于对 Redux 解决的问题的错误印象。

它与数据绑定无关,但您已接近它解决的问题。

Redux 解决了let x = {y: 2}; x.y = 3;隐藏值突变的问题,并且您的 JavaScript 应用程序中的其他所有内容都很难知道何时x.y发生变化。

从历史上看,像 AngularJS 1.x 这样的框架使用观察者将模板表达式与其先前的值进行比较以查看它是否已更改,但是如果您正在引用模板x并且内部值x.y已更改,则观察者将看不到它.

React 只有单向数据绑定,但也同样的副作用。如果x作为属性传递给<MyComponent x={x}/>组件,则不会在x.y更改时呈现更新。

Angular 也有这个问题。

程序员通过克隆对象来解决这个问题,这样数据绑定就会看到变化的变化,并将变化呈现给 DOM。

例如;

let x = {y:1};
let next = {...x, y:2};
console.log(x === next); // prints false
Run Code Online (Sandbox Code Playgroud)

而不是直接突变x.y = 2上述代码创建与新的值的新的对象,和之间的比较x和所述next值的产率false,需要它应该被更新,它告诉大多数框架像角或阵营该数据已经改变,并且任何东西。

那么这和 Redux 有什么关系呢?

Redux 是一个reducer框架。它基于使用 reducer 函数来执行上述工作的想法。的变化{...x, y:2}真的很简单,但 Redux 为开发人员提供了工具,以更易于管理的方式做到这一点。例如,选择器和动作是抽象产生新变异值的工作的方法。

如果 JavaScript 可以看到x !== x何时x.y更改,那么我们就不需要 Redux。


小智 4

当然有很多方法可以实现同一件事,Redux 正在尝试解决这个问题。Redux 实际上并不意味着双向数据绑定。它的开发是为了维护整个应用程序的状态。

Redux 动机页面可能是了解为什么使用 Redux 的正确位置。

在我看来,使用 Redux/Ngrx 有以下优点

  • 代码更易于维护。
  • 可预测的代码(易于调试,由 Redux 提供的开发工具提供)。
  • 状态是不可变的,并且仅从一处(reducer)更新。