[AngularJS] Write a simple Redux store in AngularJS app

The first things we need to do is create a reducer:

/**
 * CONSTANT
 * @type {string}
 */
export const GET_CATEGORIES = "GET_CATEGORIES";

/**
 * INIT VALUE
 */
export const initialCategories = [
  {id: 0, name: ‘Development‘},
  {id: 1, name: ‘Design‘},
  {id: 2, name: ‘Exercise‘},
  {id: 3, name: ‘Humor‘}
];

/**
 * REDUCERS
 * @type {string}
 */
export const categories = (state = initialCategories, {type, payload}) => {
  switch(type) {
    case GET_CATEGORIES:
      return payload || state;
    default:
      return state;
  }
};

It has some default initialize data. What it does is just simply return the state.

Then let‘s create a gloable store for the app, which has two methods, getState, dispatch.  Two props: reducer, state.

class Store {
  constructor(reducer, initialState) {
    this.reducer = reducer;
    this.state=  initialState;
  }

  getState() {
     return this.state
  }

  dispatch() {
     this.state = this.reducer(this.state, action);
  }

}

Once we got that, we are going to init our store:

import {categories, initialCategories} from ‘./components/categories/category.state‘;
import Store from ‘./app.store‘;
const store = new Store(categories, initialCategories);

We passed in categoreis reudcer and the initialCategories state.

To make it available to Angular APP. we need to make it injectable:

let appModule = angular.module(‘app‘, [
    CommonModule.name,
    ComponentsModule.name
  ])
    .value(‘store‘, store)

Then we can use it in our app:

class CategoriesController {
  constructor(store) {
    ‘ngInject‘;

    angular.extend(this, {
      store
    });
  }

  $onInit() {
    this.store.dispatch({type: GET_CATEGORIES});
    this.categories = this.store.getState();
  }
}


Now we are going to simply the code a little bit, we going to make a subscribe method so that we don‘t need to call getState() method everytime after we dispatch an action.

You can think that the subscribe method is a just callback function which each time we dispatch an action, it will be called. And inside the callback function, we will call this.store.getState() to get the value.

class Store {
  constructor(reducer, initialState) {
    this.reducer = reducer;
    this.state = initialState;
    this.listeners = [];
  }

  getState() {
    return this.state;
  }

  dispatch(action) {
    this.state = this.reducer(this.state, action);
    this.listeners.forEach((l) => l());
  }

  subscribe(listener) {
    this.listeners = [
      ...this.listeners,
      listener
    ];

    // return an unsubscribe function
    return () => {
      this.listeners = this.listeners.filter(l => l !== listener);
    }
  }
}

export default Store;
class CategoriesController {
  constructor($timeout, store) {
    ‘ngInject‘;

    angular.extend(this, {
      $timeout,
      store
    });
  }

  $onInit() {
    this.unsubscribe = this.store.subscribe(() => {
       this.categories = this.store.getState();
    });

    this.store.dispatch({type: GET_CATEGORIES});
  }
}


Currently inside the dispatch() metod, we pass in an object with type and payload. It would be better if we can manage those action in a single place. There is where Action creator comes in to play.

/**
 * ACTIONS CREATOR
 */
export const CategoriesActions = () => {
  const getCategoreis = (categories) => {
    return {type: GET_CATEGORIES, payload: categories}
  };

  const getCurrentCategory = (currentCategory) => {
    return {type: GET_CURRENT_CATEGORY, payload: currentCategory}
  };

  return {
    getCategoreis,
    getCurrentCategory
  };
};

To make it avaiable to Angular App, we can create a factory for this:

let appModule = angular.module(‘app‘, [
    CommonModule.name,
    ComponentsModule.name
  ])
    .value(‘store‘, store)
    .factory(‘CategoriesActions‘, CategoriesActions)
  .component(‘app‘, AppComponent)

Then we can use it inside the controller:

  constructor($timeout, store, CategoriesActions) {
    ‘ngInject‘;

    angular.extend(this, {
      $timeout,
      store,
      CategoriesActions
    });
  }
  $onInit() {
    this.unsubscribe = this.store.subscribe(() => {
       this.categories = this.store.getState();
    });

    this.store.dispatch(this.CategoriesActions.getCategoreis());
  }
  onCategorySelected(currentCategory) {
    this.currentCategory = category(this.currentCategory, this.CategoriesActions.getCurrentCategory(currentCategory));
  }
时间: 2024-11-03 05:19:50

[AngularJS] Write a simple Redux store in AngularJS app的相关文章

ASP.NET 5 and AngularJS Part 1, Configuring Grunt, Uglify, and AngularJS

ASP.NET 5 and AngularJS Part 1, Configuring Grunt, Uglify, and AngularJS This is the first part in a multiple part blog series on building ASP.NET 5 (ASP.NET vNext) apps with AngularJS. In this series of blog posts, I show how you can create a simple

[Redux] Store Methods: getState(), dispatch(), and subscribe()

console.clear(); const counter = (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } } // Create a store const {createStore} = Redux; // Store hold the state

[后端人员耍前端系列]AngularJs篇:30分钟快速掌握AngularJs

一.前言 对于前端系列,自然少不了AngularJs的介绍了.在前面文章中,我们介绍了如何使用KnockoutJs来打造一个单页面程序,后面一篇文章将介绍如何使用AngularJs的开发一个单页面应用程序.在开始使用AngularJs开发SPA之前,我觉得有必要详细介绍下AngularJs所涉及的知识点.所有也就有了这篇文章. 二.AngularJs介绍 AngularJS是Google推出的一款Web应用开发框架.它提供了一系列兼容性良好并可扩展的服务,包括数据绑定.DOM操作.MVC和依赖注

[AngularJS] Design Pattern: Simple Mediator

We're going to use rootScope emit here to send out events and then we're going to listen for them in the run block. We're going to use rootScope on down in the run block to listen for the same event that we sent out to the system. angular .module('ap

AngularJS(三)——在多个AngularJS controller之间共享数据

在MVC中,为了方便维护,针对不同业务会使用不同的controller.有时我们需要在不同的controller中共享数据,本文旨在解决这一问题. 1. 使用$rootScope直接绑定 AngularJS中有一个$rootScope对象,它是AngularJS中最接近全局作用域的对象,是所有$scope对象的最上层,可以简单理解为BOM中的window对象或Node.js中的global对象.最简单的方式是直接将要共享的数据绑定到$rootScope对象中: <!DOCTYPE html>

Redux:store

Store是一个对象.他有如下职责: 1.存放state 2.对外提供访问state的接口: getState() 3.允许state更新:dispatch(action) 4.注册监听器: subscribe(listener) 5.注销监听器,通过subscribe返回的函数 redux所在的应用只能有一个store实例,如果想将state操作分解成多个逻辑,只能将Reducer的代码分解为多个部分,以函数调用的方式提取出来处理各自的逻辑. 当我们已经有一个处理state的Reducer函数

angularjs ocLazyLoad分步加载js文件,angularjs ocLazyLoad按需加载js

用angular有一段时间了,平日里只顾着写代码,没有注意到性能优化的问题,而今有时间,于是捋了捋,讲学习过程记录于此: 问题描述:由于采用angular做了网页的单页面应用,需要一次性在主布局中将所有模块需要引用到的js都引入.对于比较小的项目,这是可行的,但是对于大的项目,一旦js文件较多,在页面首次加载时就引入所有js文件,无疑会延缓页面加载的速度,造成不良额用户体验.那么分布加载(按需加载)就显得很有必要了. <!DOCTYPE html> <html lang="en

TypeScript + React + Redux 实战简单天气APP全套完整项目

目录: 下载链接:百度网盘 从面向过程的js到面向对象的js,让web前端更加高大尚.让你的前端步步日上,紧跟技术发展的前沿.让你构建更加复杂的应用,不只是web,App照样搞定.跟后台开发人员一较高下.巅峰对决. 适用人群:js前端工程师,web前端设计师,typescript技术人员 课程简介: TypeScript是一种由微软开发的自由和开源的编程语言.它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程.安德斯·海尔斯伯格,C#的首席架构师,

archive后upload to app store时遇到app id不可用的问题

问题如下图 出现此问题的原因有两种: 1.此app id在AppStore中已经存在,也就是说你使用别人注册的app ID ,  如果是这样,你只能更换app ID 2.此app ID是自己的,突然之间出现此问题, 解决办法是重新申请安装描述文件,即可解决此问题