JS模块化 -- AMD

AMD usage

    define(id?, depencies?, factory);

    define('foo', ['utils'], function(utils){
        utils.add(1, 2);
        return {
            name: 'foo'
        }
    })

实现一个符合AMD 的 rj.js

  1. 可以直接配置依赖路径
    rj.confing({
        paths: {
            'jquery': '...'
        }
    })
  1. 加载模块
    // RequireJs('')
    rj(['moduleA'], function(moduleA) {})
  1. 定义模块
    rj('moduleA', [], function() {
        return 'hello world';
    })

行为

    define('a', function() {
        console.log('a load');
        return {
            run: function() { console.log('a run') }
        }
    })
    define('b', function() {
        console.log('b load');
        return {
            run: function() { console.log('b run') }
        }
    })

    require(['a', 'b'], function(a, b) {
        console.log('main run');    
        a.run();
        b.run();
    })

    // a load
    // b load
    // main load
    // a run
    // b run

rj.js 简单实现

  // 默认配置
  const defaultOptions = {
      paths: ''
  }

  const def = new Map();

  const rj = {};

  // config
  rj.config = (options) => Object.assign(defaultOptions, options);

  // from CDN
  const __import = (url) => {
      return new Promise((resolve, reject) => {
          System.import(url).then(resolve, reject);
      }) 
  }

  // normal script
  const __load = (url) => {
      return new Promise((resolve, reject) => {
          const header = document.getElementsByTagName("header")[0];
          const script = document.createElement('script');
          script.async = true;
          script.src = url;
          script.type = 'text/javascript';
          script.onload = resolve;
          script.onerror = reject;
          header.appendChild(script);
      }) 
  }

  // 获取地址
  // dep -> a -> a.js -> http:xxx/xx/xx/a.js
  const __getUrl = (dep) => {
      const p = location.pathname;
      return p.slice(0, p.lastIndexOf('/')) + '/' + dep + 'js';
  }

  // 定义模块 添加依赖
  const define = (name, deps, factory) => {
      def.set(name, {name, deps, factory});
  }

  // 触发依赖
  const require = (deps, factory) => {
      return new Promise((resolve, reject) => {
          Promise.all(deps.map(dep => {
              // 走CDN
              if(defaultOptions.paths[dep]) __import(defaultOptions.paths[dep]);

              return __load(__getUrl(dep)).then(() => {
                  const {deps, factory} = def.get(dep);
                  if(deps.length == 0) return factory(null);
                  return require(deps, factory);
              })
          })).then(resolve, reject);
      }).then(instance => factory(...instance));
  }

你可能感兴趣的:(javascript)