In the Store constructor, there is an instance construction processAfter this example is built, the options shown above are stored in Store._mudules as shown below

See the difference? The hierarchy remains the same, that is, the child remains a subset, but the options and child objects have changed

For ease of illustration, the normal module object is the options/ Child object, and the instance module is the rawModule, state, and child object. The instance Module is obtained by new Module (with a normal module argument).

That being said, let’s start with the Module constructor

var Module = function Module (rawModule, runtime) {
  this._children = Object.create(null);
  this._rawModule = rawModule;
  var rawState = rawModule.state;
  this.state = (typeof rawState === 'function' ? rawState() : rawState) || {};
};
Copy the code

Let’s look at the relationship between a normal module and an instance module first

As you can see, the relationship between the constructor module and the module is

  • The rawModule attribute is the entire normal module,
  • The value of state is the state property of the corresponding normal module,
  • In a regular module, the child modules of a Module are stored as key-value pairs in the parent’s Modules property. In an instance Module, each child module is constructed as an instance Module and stored in its parent’s Child property
  • Module also has two prototype methods related to this lesson: addChild() and getChild() by key to set and get children
Module.prototype.addChild = function addChild (key, module) {
  this._children[key] = module;
};
ModuleCollection.prototype.get = function get (path) {
  return path.reduce(function (module, key) {
    return module.getChild(key)
  }, this.root)
};
Copy the code

The above series of transformations facilitate the ModuleCollection get method and indirectly enable the following installModule method to recursively fetch the children of the deeper level (more on that next time).

Now that you know about the Module constructor, you can return to ModuleCollection

When it initializes, the input is a normal Module object

var ModuleCollection = function ModuleCollection (rawRootModule) {
  this.register([], rawRootModule, false);
};
Copy the code
ModuleCollection.prototype.register = function register (path, rawModule, runtime) { var this$1 = this; Var newModule = newModule (rawModule, Runtime); // If there is no path length, it is the first call. //this.register([], rawRootModule, false); // This $1.register(path.concat(key), rawChildModule, Runtime); if (path.length === 0) { this.root = newModule; } else { var parent = this.get(path.slice(0, -1)); parent.addChild(path[path.length - 1], newModule); } // register nested modules if (rawModule.modules) { forEachValue(rawModule.modules, function (rawChildModule, key) { this$1.register(path.concat(key), rawChildModule, runtime); }); }};Copy the code

The first time the register function is called

this.register([], options, false);
Copy the code

Options is passed as an argument. Options will create an instance of module (let’s say A) in which the length of path is 0, so this.root is the module property of A. Options. So register the second time

this$1.register(path.concat(key), rawChildModule, runtime);
Copy the code

The argument looks like this

this$1.register(['child'], child, false);
Copy the code

Since the path length is not zero, the following code needs to be executed

var newModule = new Module(rawModule, runtime);
var parent = this.get(path.slice(0, -1));
parent.addChild(path[path.length - 1], newModule);
Copy the code

The argument looks like this

var newModule = new Module(child, false);
var parent = this.get([]);
parent.addChild('child', newModule);
Copy the code

If a common module child has modules, and there is a common module(B) with a key of grandChild, the register function will be executed a third time

This $1. Register (['child', 'grandChild'], B, false);Copy the code

Path is not empty, so the following function is also executed

var newModule = new Module(B, false);
var parent = this.get(['child']);
parent.addChild('grandChild', newModule);
Copy the code

Until the normal module at this level has no modules property or no content in that property, the recursion ends and the construction of the new ModuleCollection ends

There is a get function that uses the getChild method of the Module constructor

ModuleCollection.prototype.get = function get (path) {
  return path.reduce(function (module, key) {
    return module.getChild(key)
  }, this.root)
};
Copy the code

Here is the this.get function, which takes path, for example

  • If path is [] and length is 0, reduce returns this.root directly
  • If path is [‘child’] and length is 0, reduce returns this.root and this.root.getChild(‘child’) to this.root[‘child’].
  • If path is [‘child’,’grandChild’], reduce will return this.root[‘child’] above, Get this.root[‘child’][‘grendChild’] from this.root[‘child’].getChild(‘grandChild’)
  • If path is [‘child’,’grandChild’,’ XXX ‘], return this.root[‘child’][‘grandChild’][‘ XXX ‘]
  • And so on..

The getNameSpace method is similar to the get method above

ModuleCollection.prototype.getNamespace = function getNamespace (path) {
  var module = this.root;
  return path.reduce(function (namespace, key) {
    module = module.getChild(key);
    return namespace + (module.namespaced ? key + '/' : '')
  }, '')
};
Copy the code

Let’s look at the effect of method execution

  • Can see the common module for namespaced falsy, the return value of the getNamespace make peace its parent is the same, but the return value in the module. The namespaced to falsy would not be used, so it doesn’t matter have the same
// module.namespaced is falsy, and // namespace only concatenates the namespace and '' returned by the last reduce.  // namespace+''===namespce return namespace + (module.namespaced ? key + '/' : '')Copy the code

For example, how to get child/grand2xChild/ in the figure above

This. GetNamespace ([‘child’,’grandChild’,’grandChildChild’]) path is [‘child’,’grandChild’,’grandChildChild’] Path. Reduce the first time

module = module.getChild(key); // module is this.root['child'], return namespace + (module.namespaced? Key + '/' : '')/For this module, namespaced is true, key is 'child', namespace = '+'child'+'/'('child/'), namesapce will be used in the second ReduceCopy the code

Path. Reduce the second

module = module.getChild(key); //module is this.root['child']['grandChild'], return namespace + (module.namespaced? Key + '/' : // This module's namespaced is undefined, so namespace = 'child/' + ', or 'child/', which will be used in the third ReduceCopy the code

Path. The third time the reduce

module = module.getChild(key); //module is this.root['child']['grandChild'][' grandx2Child '], return namespace + (module.namespaced? Key + '/' : // Namespace = 'child/'+' grandx2Child '+'/', ('child/ grandx2Child /')Copy the code

Ok,, finally, if you can’t understand, you can look at the reduce function to understand, and then you can’t understand that is my problem.

To sum up, ModuleCollection does the following things

  1. Use the register method to convert a common module to an instance of a Module, and create a this.root object based on the parent-child relationship of a common Module
  2. The get and getNameSpace methods are registered. (There are other methods, but they are not relevant to this article.)