Javascript modular programming

The modular programming method in JS uses requireJS, which implements AMD specification, as an example.

  • Add and introduce require. In html JS code

my. In HTML, data main is followed by my entry JS, which is equivalent to main in other languages

 

<!DOCTYPE html>
<html>

<head>

</head>

<body>
    <h3>title1: </h3>
    <p id="idempty"></p>
    <h3>title2: </h3>
    <p id="idmymath"></p>
    <h3>title3: </h3>
    <p id="idmyson"></p>
    <h3>title4: </h3>
    <p id=idgirl></p>
    <script src="require.js" defer async="true" data-main="src/my.js">
    </script>

</body>

</html>

info.js

define(function () {
    var age = function (x) {
        return "Age:" + x;
    }

    return {
        age: age
    };
});

girl.js

//The info module is used
define(["info"],function (info) {
    var show = function (x) {
        return "girl.show  " + info.age(x);
    };

    return {
        show: show
    };
});

myson.js

define(function () {
    var show = function (x) {
        return "name + " + x;
    };
    return {
        show: show
    };
});

mymath.js

define(function(){
    var add = function(x,y){
        return x+y;
    };

    return{add:add};
});

my.js

//Empty module dependency
require([], function () {
    document.getElementById("idempty").innerHTML = "require Test direct loading";
});

//Dependency under the same directory
require(["mymath"], function (mymath) {
    document.getElementById("idmymath").innerHTML = " mymath = " + mymath.add(83, 3);
});


//Direct paths location module
require.config({
    baseUrl: "src",
    paths: {
        "girl": "neighbor/girl",
        "myson": "children/myson",
        "info": "util/info"

    }
});

require(["girl", "myson"], function (girl, myson) {
    document.getElementById("idgirl").innerHTML = "g " + girl.show(83);

    document.getElementById("idmyson").innerHTML = "son " + myson.show("sssson");

})



Click my View the execution result in HTML browser

 

  • 1. Module writing

reference resources: http://www.ruanyifeng.com/blog/2012/10/javascript_module.html

Javascript modular programming has become an urgent need. Ideally, developers only need to implement the core business logic, and others can load modules already written by others.

However, Javascript is not a modular programming language and does not support“ class "(class), let alone" module "(under development) ECMAScript standard The sixth edition will officially support "class" and "module", but it will take a long time to put into practice.)

The Javascript community has made a lot of efforts to achieve the effect of "module" in the existing running environment. This paper summarizes the current best practices of "Javascript modular programming" and explains how to put it into practice. Although this is not a preliminary tutorial, you can understand it as long as you have a little understanding of the basic syntax of Javascript.

1, Original writing

A module is a set of methods to realize a specific function.

As long as different functions (and variables recording state) are simply put together, it can be regarded as a module.

  function m1(){
    //...
  }

  function m2(){
    //...
  }

The above functions m1() and m2() form a module. When using, just call it directly.

The disadvantages of this approach are obvious: "pollute" the global variables, and there is no guarantee that there will be no variable name conflict with other modules, and there is no direct relationship between module members.

2, Object writing

In order to solve the above shortcomings, the module can be written as an object, and all module members can be placed in this object.

  var module1 = new Object({

    _count : 0,

    m1 : function (){
      //...
    },

    m2 : function (){
      //...
    }

  });

The above functions m1() and m2() are encapsulated in the module1 object. When used, it is to call the properties of this object.

module1.m1();

However, such writing will expose all module members, and the internal state can be rewritten externally. For example, the external code can directly change the value of the internal counter.

 module1._count = 5;

3, Immediate function writing

Use“ Execute function now (immediately invoked function expression, IIFE) can achieve the purpose of not exposing private members.

  var module1 = (function(){

    var _count = 0;

    var m1 = function(){
      //...
    };

    var m2 = function(){
      //...
    };

    return {
      m1 : m1,
      m2 : m2
    };

  })();

Using the above writing method, the external code cannot read the internal code_ count variable.

 console.info(module1._count); //undefined

module1 is the basic way to write Javascript modules. Next, process this writing method.

4, Zoom in mode

If a module is large and must be divided into several parts, or one module needs to inherit another module, it is necessary to adopt "amplification mode".

  var module1 = (function (mod){

    mod.m3 = function () {
      //...
    };

    return mod;

  })(module1);

The above code adds a new method m3() to the module1 module, and then returns the new module1 module.

5, Wide amplification mode

In the browser environment, each part of the module is usually obtained from the Internet. Sometimes it is impossible to know which part will be loaded first. If the writing method in the previous section is adopted, the first execution part may load an empty object that does not exist. At this time, the "wide zoom in mode" should be adopted.

  var module1 = ( function (mod){

    //...

    return mod;

  })(window.module1 || {});

Compared with "zoom in mode", the "wide zoom in mode" is "execute function immediately", and the parameter can be an empty object.

6, Enter global variables

Independence is an important feature of the module. It is better not to interact directly with other parts of the program inside the module.

In order to call global variables within a module, other variables must be explicitly entered into the module.

  var module1 = (function ($, YAHOO) {

    //...

  })(jQuery, YAHOO);

The module1 module above needs to use the jQuery library and the YUI library. These two libraries (actually two modules) are used as parameters to input module1. This not only ensures the independence of modules, but also makes the dependency between modules obvious. For more discussion on this aspect, please refer to Ben Cherry's famous article <JavaScript Module Pattern: In-Depth>.

The second part of this series will discuss how to organize and manage dependencies between different modules in the browser environment.

(end)

  • 2.AMD specification

http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html

Think about it first. Why are modules important?

Because with modules, we can more easily use other people's code and load whatever modules we want.

However, there is a premise for doing so, that is, we must write modules in the same way, otherwise you have your writing method and I have my writing method. Isn't it a mess! This is even more important considering that there is no official specification for Javascript modules.

At present, there are two common Javascript module specifications: CommonJS and AMD . I mainly introduce AMD, but I want to start with CommonJS.

8, CommonJS

In 2009, American programmer Ryan Dahl created node.js Project, using javascript language for server-side programming.

This marks the official birth of "Javascript modular programming". Because to be honest, in the browser environment, no module is not a particularly big problem. After all, the complexity of Web programs is limited; However, on the server side, there must be modules to interact with the operating system and other applications, otherwise there is no programming at all.

node.js Modular system , is the reference CommonJS Standard implementation. In CommonJS, there is a global method, require(), for loading modules. Suppose there is a math module math JS, you can load it like this.

var math = require('math');

Then, you can call the methods provided by the module:

  var math = require('math');

  math.add(2,3); // 5

Because this series is mainly aimed at browser programming and does not involve node JS, so I won't introduce CommonJS more. All we need to know here is that require() is used to load modules.

9, Browser environment

With the server-side module, naturally, we want the client-side module. And it is best that the two can be compatible. A module does not need to be modified and can run in both server and browser.

However, due to a major limitation, the CommonJS specification is not suitable for browser environment. The code in the previous section will have a big problem if it is run in the browser. Can you see it?

  var math = require('math');

  math.add(2, 3);

The second line math Add (2, 3), run after the first line of require('math '), so you must wait for math JS loading completed. In other words, if the loading time is long, the whole application will stop there and wait.

This is not a problem for the server side, because all modules are stored in the local hard disk and can be loaded synchronously. The waiting time is the reading time of the hard disk. However, for the browser, this is a big problem, because the modules are placed on the server side, and the waiting time depends on the speed of the network. It may take a long time, and the browser is in the "fake death" state.

Therefore, modules on the browser side cannot be loaded synchronously, but can only be loaded asynchronous ly. This is the background of AMD specification.

10, AMD

AMD It is the abbreviation of "Asynchronous Module Definition", which means "Asynchronous Module Definition". It loads modules asynchronously, and the loading of modules does not affect the operation of subsequent statements. All statements that depend on this module are defined in a callback function. The callback function will not run until the loading is completed.

AMD also uses the require() statement to load modules, but unlike CommonJS, it requires two parameters

require([module], callback);

The first parameter [module] is an array whose members are the modules to be loaded; The second parameter callback is the callback function after loading successfully. If the previous code is rewritten into AMD form, it is as follows:

  require(['math'], function (math) {

    math.add(2, 3);

  });

math.add() is not synchronized with math module loading, and the browser will not fake death. So obviously, AMD is more suitable for browser environment.

At present, there are mainly two Javascript libraries that implement AMD specification: require.js and curl.js . The third part of this series will introduce require JS to further explain the usage of AMD and how to put modular programming into practice.

(end)

  • 3.require.js usage

1, Why use require js?

In the earliest days, all Javascript code was written in one file, which was enough to load. Later, there were more and more codes. One file was not enough. It had to be divided into multiple files and loaded in turn. The following web page code, I believe many people have seen.

  <script src="1.js"></script>
  <script src="2.js"></script>
  <script src="3.js"></script>
  <script src="4.js"></script>
  <script src="5.js"></script>
  <script src="6.js"></script>

This code loads multiple js files in turn.

This way of writing has great disadvantages. First of all, when loading, the browser will stop web page rendering. The more files are loaded, the longer the web page will lose response; Secondly, due to the dependency between JS files, the loading order must be strictly guaranteed (for example, 1.js in the above example should be in front of 2.js). The modules with the greatest dependency must be loaded at the end. When the dependency is very complex, the coding and maintenance of the code will become difficult.

require.js was born to solve these two problems:

(1) realize the asynchronous loading of js files to avoid the loss of response of web pages;

(2) manage the dependencies between modules to facilitate code writing and maintenance.

2, Require JS loading

Use require The first step of JS is to go to the official website first download Latest version.

After downloading, suppose you put it under the js subdirectory, you can load it.

  <script src="js/require.js"></script>

One might think that loading this file may also cause the web page to lose response. There are two solutions. One is to load it at the bottom of the web page, and the other is to write it as follows:

 <script src="js/require.js" defer async="true" ></script>

The async attribute indicates that the file needs to be loaded asynchronously to prevent the web page from losing response. IE does not support this attribute, only supports defer, so write defer as well.

Load require js, the next step is to load our own code. Suppose our own code file is main js, also under the js directory. Then, just write it as follows:

<script src="js/require.js" data-main="js/main"></script>

The data main attribute is used to specify the main module of the web program. In the above example, it is main under the js directory js, this file will be required first js load. Due to require js the default file suffix is js, so you can put main js is abbreviated as main.

3, Writing method of main module

Main in the previous section JS, I call it "main module", which means the entry code of the whole web page. It's a bit like the main() function of C language. All the code starts from here.

Let's see how to write main js.

If our code does not depend on any other module, we can write javascript code directly.

  // main.js

  alert("Loading succeeded!");

But in this case, there is no need to use require JS. The real common situation is that the main module depends on other modules. At this time, the require() function defined by AMD specification should be used.

  // main.js

  require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){

    // some code here

  });

The require() function takes two arguments. The first parameter is an array, which indicates the modules it depends on. The above example is ['modulea ',' moduleb ',' modulec '], that is, the main module depends on these three modules; The second parameter is a callback function, which will be called when the previously specified modules are loaded successfully. The loaded modules will be passed into the function in the form of parameters, so that these modules can be used inside the callback function.

require() asynchronously loads moduleA, moduleB and moduleC, and the browser will not lose response; The callback function specified by it will run only after the previous modules are loaded successfully, which solves the problem of dependency.

Next, let's look at a practical example.

It is assumed that the main module relies on three modules: jquery, underscore and backbone JS can be written as follows:

  require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){

    // some code here

  });

require.js will load jQuery, underscore and backbone first, and then run the callback function. The code of the main module is written in the callback function.

4, Module loading

In the last example in the previous section, the dependent modules of the main module are ['jquery ',' underscore ',' backbone ']. By default, require JS assumes that these three modules are related to main JS are in the same directory, and the file names are jQuery js,underscore.js and backbone JS, and then automatically load.

Use require Config () method, we can customize the loading behavior of the module. require.config() is written in the header of the main module (main.js). Parameter is an object whose paths attribute specifies the loading path of each module.

  require.config({

    paths: {

      "jquery": "jquery.min",
      "underscore": "underscore.min",
      "backbone": "backbone.min"

    }

  });

The above code gives the file names of the three modules, and the default path is main js is in the same directory (js subdirectory). If these modules are in other directories, such as js/lib directory, there are two ways to write them. One is to specify paths one by one.

  require.config({

    paths: {

      "jquery": "lib/jquery.min",
      "underscore": "lib/underscore.min",
      "backbone": "lib/backbone.min"

    }

  });

The other is to directly change the base directory (baseUrl).

  require.config({

    baseUrl: "js/lib",

    paths: {

      "jquery": "jquery.min",
      "underscore": "underscore.min",
      "backbone": "backbone.min"

    }

  });

If a module is on another host, you can also directly specify its web address, for example:

  require.config({

    paths: {

      "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"

    }

  });

require.js requires that each module be a separate js file. In this way, if multiple modules are loaded, multiple HTTP requests will be issued, which will affect the loading speed of the web page. Therefore, require js provides a Optimization tools , after the modules are deployed, you can use this tool to merge multiple modules into one file to reduce the number of HTTP requests.

5, AMD module writing

require.js loaded module adopts amd specification. In other words, the module must be written according to AMD regulations.

Specifically, the module must be defined with a specific define() function. If a module does not depend on other modules, it can be defined directly in the define () function.

Suppose there is a math JS file, which defines a math module. So, math JS should be written like this:

  // math.js

  define(function (){

    var add = function (x,y){

      return x+y;

    };

    return {

      add: add
    };

  });

The loading method is as follows:

  // main.js

  require(['math'], function (math){

    alert(math.add(1,1));

  });

If this module also depends on other modules, the first parameter of the define() function must be an array indicating the dependency of the module.

  define(['myLib'], function(myLib){

    function foo(){

      myLib.doSomething();

    }

    return {

      foo : foo

    };

  });

When the require() function loads the above module, it will first load mylib JS file.

6, Load nonstandard modules

In theory, require JS must be a module defined by the define() function according to AMD specification. However, in fact, although some popular function libraries (such as jQuery) comply with AMD specifications, more libraries do not. So, require Can JS load non-standard modules?

The answer is yes.

Such modules need to use require. Before loading with require() Config () method to define some of their characteristics.

For example, the two libraries, underscore and backbone, are not written in AMD specification. If you want to load them, you must first define their characteristics.

  require.config({

    shim: {

      'underscore':{
        exports: '_'
      },

      'backbone': {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      }

    }

  });

require.config() accepts a configuration object. In addition to the paths attribute mentioned above, this object also has a shim attribute, which is specially used to configure incompatible modules. Specifically, each module should define (1) exports value (output variable name), indicating the name of the external call of the module; (2) deps array, indicating the dependency of the module.

For example, the plug-in of jQuery can be defined as follows:

  shim: {

    'jquery.scroll': {

      deps: ['jquery'],

      exports: 'jQuery.fn.scroll'

    }

  }

7, Require JS plug-in

require.js also provides a series of plug-in unit , realize some specific functions.

The domready plug-in allows the callback function to run after the page DOM structure is loaded.

  require(['domready!'], function (doc){

    // called once the DOM is ready

  });

For text and image plug-ins, require is allowed JS loads text and picture files.

  define([

    'text!review.txt',

    'image!cat.jpg'

    ],

    function(review,cat){

      console.log(review);

      document.body.appendChild(cat);

    }

  );

Similar plug-ins include json and mdown, which are used to load json files and markdown files.

(end)

Tags: Front-end H5

Posted by lordfrikk on Sat, 16 Apr 2022 09:51:42 +0930