Angular 4 中使用 Redux 进行 UI 状态管理
介绍
尽管近几年在构建 Web 界面方面取得了许多进展,但 DOM 和应用程序用户界面 (UI) 的控制仍然高度依赖于jQuery,这是一个已有 10 年历史的库。虽然这不一定是坏事,但 jQuery 最初的构建目的与现在的用途不同。因此,现代用途开始引发问题。前端应用程序变得越来越复杂,各种不相关的组件、封装的视图和其他元素都试图相互交互。
在本指南中,我们将探索如何使用 Redux 来缓解当前控制 Angular 2 应用程序 UI 的挑战。您将学习如何在 Reducer 函数中表示一些控制 UI 布局的逻辑,并查看示例用例。
驯服你的应用程序 UI 布局
自从 Redux 问世以来,前端应用程序的状态管理经历了一场革命。我和我的团队已经使用 Angular 2 对 Redux 进行了现场测试,结果显著提高了工作效率。
Redux 不仅使我们能够更快地交付,而且通过将大多数关键逻辑封装在一个地方并提供易于测试的架构,它还提高了代码库的整体可维护性。
我们非常喜欢 Redux,以至于我们想用它来控制一切。我们最近的一个项目是构建一个非常注重 UI 的应用程序,我们决定尝试让应用程序中的 Reducer 承担更多的责任,而不仅仅是控制数据。
我们发现“简化”UI 可以带来很多好处,并且能够控制灵活性。它使以前难以实现的用例变得轻而易举。
使用 Redux 进行 UI 布局的三个主要好处
- 保持 UI 状态,例如在更改路线时保持侧边栏打开或关闭。
- 从应用程序的任何点控制 UI,而无需担心组件如何关联或如何注入特定服务。
- 将特定于 UI 布局的操作与其他事件(例如保存服务器端数据或更改路线)链接起来
设置
下面的示例将使用 ng-bootstrap 完成,因为它是 Bootstrap 4 中最流行的带有 Angular 2 组件的库之一。您还可以使用其他组件库(例如Material Design)来实现这些示例,只需遵循相同的设计原则并对代码进行微调,使其与相应库的 API 一起使用即可。
依赖项
以下是您开始工作所需安装的软件包:
雷克斯
** 引导 **
安装
为了确保顺利安装,我们将使用Angular CLI来初始化应用程序架构。在继续之前,请确保已全局安装它。
在您的终端中,写入以下命令来初始化您的 Angular 2 应用程序:
$ ng new redux-layout-tutorial-app
$ cd new redux-layout-tutorial-app
$ yarn add bootstrap@4.0.0-alpha.6
要将 Bootstrap 的资产添加到您的项目,请在应用程序根目录中打开angular-cli.json并添加以下内容:
apps: [
{
//..
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.css"
],
//...
"environments": {
//...
"scripts": [
"../node_modules/jquery/dist/jquery.js",
"../node_modules/tether/dist/js/tether.js",
"../node_modules/bootstrap/dist/js/bootstrap.js"
]
}
这将让你的angular-cli找到你的 Bootstrap 安装的 JavaScript 和 CSS 文件并将它们添加到项目构建中。
接下来,将ng-bootstrap添加到你的依赖项中:
$ yarn add @ng-bootstrap/ng-bootstrap
并将NgbModule包含在应用程序的根模块中(位于app.module.ts中):
import {NgbModule} from "@ng-bootstrap/ng-bootstrap";
@NgModule({
//..
imports: [
NgbModule.forRoot()
],
//..
})
设置应用商店和元 Reducer
接下来,我们将对 Redux 架构进行最小程度的实现,它将作为本指南后面实现的所有用例的基础。
首先添加 Redux 应用商店的核心依赖项:
$ yarn add @ngrx/core
$ yarn add @ngrx/store
对于分页和加载条等异步事件,在应用程序的布局中,需要有一个中间件:
$ yarn add @ngrx/effects
为了使状态选择快速高效,请添加reselect。我们将使用reselect的createSelector函数来创建高效的选择器,这些选择器会被记忆,并且仅在参数发生变化时重新计算。
$ yarn add reselect
为了使开发更加方便,更容易调试,添加一个store logger,它会将每个动作以及状态的新状态记录到控制台。
$ yarn add ngrx-store-logger
为了正确构造应用程序的文件,所有与 redux 相关的文件都将保留在src/app/common目录中。
$ mkdir src/app/common
创建布局状态
创建common/layout目录,其中将包含所有操作、效果和布局状态的减速器。
$ mkdir src/app/common/layout
$ cd src/app/common/layout
在目录中创建三个用于布局状态的文件:
$ touch layout.actions.ts
** 布局.动作.ts **
每次用户执行操作(关闭和打开侧边栏、打开模式等)或发生某些事件(调整窗口大小)时,都会分派布局操作。
import { Action } from "@ngrx/store";
/*
Layout actions are defined here
*/
export const LayoutActionTypes = {};
/*
The action classes will be added here once they are defined
*/
export type LayoutActions = null;
布局.reducer.ts
$ touch layout.reducer.ts
布局的 Reducer 将处理应用程序布局的所有变化,并在每次 UI 需要改变时创建一个新的状态。
import * as layout from "./layout.actions";
export interface State {
/*
The description of the different parts of the layout go here
*/
}
const initialState: State = {
/*
The initial values of the layout state will be initialized here
*/
};
/*
The reducer of the layout state. Each time an action for the layout is dispatched,
it will create a new state for the layout.
*/
export function reducer(
state = initialState,
action: layout.LayoutActions
): State {
switch (action.type) {
default:
return state;
}
}
创建元 Reducer
在 UI 状态准备就绪后,最后一步是添加元 Reducer,它最终将由@ngrx/store提供的StoreModule引导。如果您对 Redux 和元 Reducer 的作用不太熟悉,请阅读此处:
$ touch src/app/common/index.ts
/*
Import createSelector from reselect to make selection of different parts of the state fast efficient
*/
import { createSelector } from "reselect";
/*
Import the store logger to log all the actions to the console
*/
import { storeLogger } from "ngrx-store-logger";
/*
Import the layout state
*/
import * as fromLayout from "./layout/layout.reducer";
import { compose } from "@ngrx/core";
import { combineReducers } from "@ngrx/store";
export interface AppState {
reducer: {
layout: fromLayout.State;
};
}
export const reducers = {
layout: fromLayout.reducer
};
const developmentReducer: Function = compose(storeLogger(), combineReducers)(
reducers
);
export function metaReducer(state: any, action: any) {
<span class
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~