学习Redux第二天(基于angular的toDoList)

本文分享了一个基于Angular和Redux的简易demo,演示了如何利用Redux进行组件间的数据通讯,包括toDoList的增删改操作,通过实例代码详细解析了Redux在实际项目中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

学习Redux第一天(基于angular的简易的小demo-实现组件间通讯)


一、toDoList

代码下载地址:https://github.com/fairyLiu-153/angular-redux
先看组件分布,最外层组件父组件(红框),add-to-do组件(蓝框), doing组件(黑框),done组件(紫框),
这次我还是先写redux部分,然后就开始分析:

  • state:要分析结构的哈,首先我页面渲染需要什么数据,数据的结构,做啥事?比如吃饭睡觉,那就需要一个text属性,完成了吗?完成了就在done表显示,没完成就在doing表显示,就需要一个completed属性。那最基本的就定下来了。
  • action: 然后我就想action需要有几个type,得有增加add,切换toggle,删除delete,最最基本的是这仨。
  • reducer: 接着我又想,若想实现add,toggle,delete功能,我分别需要什么数据,比如add,那我就需要add的内容text,toggle我得需要toggle的哪一条,那条item,删除也是,我删除哪一条,要么我得知道这一条是哪一条,要么我得知道它的索引来把它删掉,这样,参数就基本定下来了

    在这里插入图片描述

在这里插入图片描述

以上,我终于想完了,不啰嗦了,那我开始写吧。下面附上完整代码:

二、代码

  1. 目录结构(看to-do-list相关即可)
    在这里插入图片描述
  2. 代码展示
    1.to-do-list.action.ts
import { Action, ActionCreator } from 'redux';
import { ITodoItem } from '../reducers/to-do-list.reducer';

export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO';
export const DELETE_TODO = 'DELETE_TODO';

// add todo
export interface AddToDoAction extends Action {
    text: string;
}

export const addTodo: ActionCreator<AddToDoAction> = (text: string) => ({
    type: ADD_TODO,
    text
});

// toggle todo
export interface ToggleToDoAction extends Action {
    todoItem: ITodoItem;

}

export const toggleToDo: ActionCreator<ToggleToDoAction> = (todoItem: ITodoItem) => ({
    type: TOGGLE_TODO,
    todoItem
});

// delete todo
export interface DeleteToDoAction extends Action {
    todoItem: ITodoItem;
}

export const deleteToDo: ActionCreator<ToggleToDoAction> = (todoItem: ITodoItem) => ({
    type: DELETE_TODO,
    todoItem
});

2.actions目录下index.ts

import * as LoginActions from './login.action';
import * as TodoListActions from './to-do-list.action';

export {
    LoginActions,
    TodoListActions
}

3.to-do-list.reducer.ts

import { Action } from 'redux';
import * as _ from 'lodash';
import { AddToDoAction, ToggleToDoAction, DeleteToDoAction } from '../actions/to-do-list.action';
export interface ITodoItem {
    text: string;
    completed: boolean;
}

export interface ToDosState {
    todos: ITodoItem[];

}
export const initialState: ToDosState = {
    todos: []
};

export const ToDosReducer = function (state: ToDosState = initialState, action: Action) {
    let todoList: ITodoItem[];
    let todoItem: ITodoItem = {
        text: '',
        completed: false
    };
    switch (action.type) {
        case 'ADD_TODO':
            todoList = state.todos;
            todoItem.text = (action as AddToDoAction).text;
            todoItem.completed = false;
            return Object.assign({todos: [...todoList, todoItem]});

        case 'TOGGLE_TODO': {
            todoList = state.todos;
            todoItem = (action as ToggleToDoAction).todoItem;
            todoItem.completed = !todoItem.completed;
            return Object.assign({todos: [...todoList]});
        }
        case 'DELETE_TODO': {
            todoList = state.todos;
            todoItem = (action as DeleteToDoAction).todoItem;
            return Object.assign({}, state, {
                todos: _.reject(todoList, todo => todo === todoItem)
            });
        }
        default:
            return state;
    }

};

4.reducers目录下index.ts

import { Reducer, combineReducers } from 'redux';
import { LoginState, LoginReducer } from './login.reducer';
export * from './login.reducer';
import { ToDosState, ToDosReducer } from './to-do-list.reducer';
export * from './to-do-list.reducer';




export interface AppState {
    login: LoginState;
    toDoList: ToDosState;

}

export const rootReducer: Reducer<AppState> = combineReducers<AppState>({
    login: LoginReducer,
    toDoList: ToDosReducer
});

5.redux.service.ts

import { Injectable } from '@angular/core';
import { createStore, Store, Unsubscribe } from 'redux';
import { AppState, rootReducer} from './reducers';
import { LoginState } from './reducers/login.reducer';
import { ITodoItem, ToDosState } from './reducers/to-do-list.reducer';
import { TodoListActions, LoginActions } from './actions';


@Injectable({
  providedIn: 'root'
})
export class ReduxService {
  private store: Store<AppState>;
  private unsubscribe: Unsubscribe;
  constructor() {
    // 创建redux store 来存放应用的状态
    this.store = createStore(
      rootReducer
    );
  }

  // 读取状态
  getIsLogin(): boolean {
    const state: LoginState = this.store.getState().login;
    return state.login;

  }

  // 改变内部state -> dispatch一个action
  setIsLogin(login: boolean) {
    this.store.dispatch(LoginActions.setIsLogin(login));
  }

  // 订阅更新
  subscribeStore(readStateFun: () => void) {
    this.unsubscribe = this.store.subscribe(readStateFun);
  }

  getTodoList() {
    const todoState: ToDosState = this.store.getState().toDoList;
    return todoState;
  }

  addTodo(text: string) {
    this.store.dispatch((TodoListActions.addTodo(text)));
  }

  deleteTodo(todoItem: ITodoItem) {
    this.store.dispatch(TodoListActions.deleteToDo(todoItem));
  }

  toggleTodo(todoItem: ITodoItem) {
    this.store.dispatch(TodoListActions.toggleToDo(todoItem));
  }
}

6.to-do-list.component.html

<app-add-todo></app-add-todo>
<h6>doing:</h6>
<hr>
<app-doing></app-doing>
<br>
<br>
<h6>done:</h6>
<hr>
<app-done></app-done>

7.add-todo.component.html

<form [formGroup]="myForm">
<input type="text" placeholder="to do" formControlName="todo">
<button (click)="addTodo()">add</button>
</form>

8.add-todo.component.ts

import { Component, OnInit } from '@angular/core';
import { ReduxService } from 'src/app/redux/redux.service';
import { AstMemoryEfficientTransformer } from '@angular/compiler';
import { FormGroup, FormBuilder } from '@angular/forms';

@Component({
  selector: 'app-add-todo',
  templateUrl: './add-todo.component.html',
  styleUrls: ['./add-todo.component.scss']
})
export class AddTodoComponent implements OnInit {

  myForm: FormGroup;

  constructor(
    private reduxService: ReduxService,
    private fb: FormBuilder
  ) {
    this.myForm = this.fb.group({
      todo: ['']
    });
   }

  ngOnInit(): void {
  }

  addTodo() {
    const text = this.myForm.controls.todo.value;
    this.reduxService.addTodo(text);
    this.myForm.controls.todo.setValue('');
  }

}

9.doing.component.html

<ul>
  <li *ngFor="let item of list" style="display: flex; justify-content: space-between;">
    <span>* {{item.text}}</span>
    <div>
      <button (click)="toggle(item)">toggle</button>
      <button (click)="delete(item)">delete</button>
    </div>
  </li>
</ul>

9.doing.component.ts

import { Component, OnInit } from '@angular/core';
import { ReduxService } from 'src/app/redux/redux.service';
import { ITodoItem } from 'src/app/redux/reducers';
import * as _ from 'lodash';

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

  list: ITodoItem[];
  allList: ITodoItem[];


  constructor(
    private reduxService: ReduxService
  ) { }

  ngOnInit(): void {
    this.readState();
    this.reduxService.subscribeStore(() => { this.readState(); });
  }

  readState() {
    this.getTodoLists();
  }

  getTodoLists() {
    this.allList = this.reduxService.getTodoList().todos;
    this.list = _.filter(this.allList, item => item.completed === false);
  }

  delete(item: ITodoItem) {
    this.reduxService.deleteTodo(item);

  }

  toggle(item: ITodoItem) {
    this.reduxService.toggleTodo(item);

  }

}

8.done.component.html

<ul>
    <li *ngFor="let item of list" style="display: flex; justify-content: space-between;">
      <span>* {{item.text}}</span>
      <div>
        <button (click)="toggle(item)">toggle</button>
        <button (click)="delete(item)">delete</button>
      </div>
    </li>
  </ul>

9.done.component.ts

import { Component, OnInit } from '@angular/core';
import { ITodoItem } from 'src/app/redux/reducers';
import { ReduxService } from 'src/app/redux/redux.service';
import * as _ from 'lodash';


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

  list: ITodoItem[];
  allList: ITodoItem[];

  constructor(
    private reduxService: ReduxService
  ) {

   }

  ngOnInit(): void {
    this.readState();
    this.reduxService.subscribeStore(() => { this.readState(); });
  }

  readState() {
    this.getTodoLists();
  }

  getTodoLists() {
    this.allList = this.reduxService.getTodoList().todos;
    this.list = _.filter(this.allList, item => item.completed === true)
  }

  delete(item: ITodoItem) {
    this.reduxService.deleteTodo(item);

  }

  toggle(item: ITodoItem) {
    this.reduxService.toggleTodo(item);

  }

}

总结

其实,有了redux第一天的学习,做这个demo非常的简单,理清楚思路写就是了,不需要父子组件来回传参,redux可以更好的帮我们组件交互,基本上写完redux想做了功能也完成的差不多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值