[AngularJS] Write a simple Redux store in AngularJS app

Posted Answer1215

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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));
  }

 

以上是关于[AngularJS] Write a simple Redux store in AngularJS app的主要内容,如果未能解决你的问题,请参考以下文章

[Javascript AST] 1. Continue: Write a simple Babel plugin

[Javascript AST] 0. Introduction: Write a simple BabelJS plugin

Speeding up AngularJS apps with simple optimizations

Spring MVC 和 Angularjs

网络摄像头 getUserMedia API - AngularJS 错误?

Python 元类