Requirejs: модуль AMD не определен

Я хочу использовать datepickk.js внутри моего модуля: даже если этот плагин поддерживает AMD, я не смог загрузить его в RequireJS: http://jsfiddle.net/numediaweb/5xbqqr0j/13/

// Config Object
requirejs.config({
    // Local Directory
    baseUrl: "/js",
    // Script Locations
    paths: {
        // Common Libraries
        "jquery": "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min",
        "datepickk": "//crsten.github.io/datepickk/dist/datepickk.min"
    }
});

// Check Dependencies
requirejs(['jquery', 'datepickk'], function ($, Datepickk) {
    var loadedMods = require.s.contexts._.defined;
    console.log(loadedMods);
    $('#message').text('Loaded modules => '+JSON.stringify(loadedMods));
    return {};
});

Если вы проверите консоль, вы увидите, что jquery определен, а модуль - нет.

Есть идеи, почему это происходит?

Я попробовал другой вариант загрузки этого модуля:

require.config({
    paths: {
        'Datepickk': '//crsten.github.io/datepickk/dist/datepickk.min'
    },

Но тогда я получаю эту ошибку:

datepickk.js:1146 Uncaught TypeError: Cannot freeze
    at Function.freeze (<anonymous>)
    at Datepickk (datepickk.js:1146)
    at Object.execCb (require.js:1693)
    at Module.check (require.js:881)
    at Module.enable (require.js:1173)
    at Module.init (require.js:786)
    at callGetModule (require.js:1200)
    at Object.completeLoad (require.js:1587)
    at HTMLScriptElement.onScriptLoad (require.js:1714)

1 ответ

Решение

Кто бы ни написал код AMD для datepickk.js Нужно прочитать о том, как писать модули AMD. Есть две проблемы:

  1. Имя модуля жестко закодировано как Datepickk поскольку define вызов define('Datepickk', Datepickk) , Первый аргумент жестко кодирует имя. Это действительно плохая вещь, поскольку в документации RequireJS ясно, что разработчики не должны жестко кодировать имена и вместо этого позволяют оптимизатору добавлять имя по мере необходимости, но здесь кто-то не обращал на это внимания.

    Это объясняет, почему ваша вторая конфигурация, Datepickk в paths работает, но ваш первый нет. Вы должны ссылаться на это как Datepickk в вашем paths конфигурации. Если вы хотите, чтобы ваш собственный код ссылался на него как datepickk Вы можете использовать map конфигурация в дополнение к paths:

    map: {
      "*": {
        datepickk: "Datepickk"
      }
    }
    
  2. Да, даже если вы исправите вышесказанное, вы все равно получите ошибку, с которой столкнулись. Глядя на документацию для Datepickk Я вижу, что вы используете это делать new Datepickk(...), Если вы сделаете это, то объект, который должен быть заморожен, должен быть новым объектом, который назначен this виртуальной машиной JavaScript, когда конструктор выполняется. Если вы посмотрите на код, который делает Datepickk доступно для другого кода, это то, что вы видите:

    if ( typeof define === 'function' && define.amd ) define('Datepickk', Datepickk);
    else if ( typeof exports === 'object' ) module.exports = Datepickk;
    else window.Datepickk = Datepickk;
    

    2-й и 3-й филиал экспортируют Datepickk конструктор мира. Все в порядке. Первая ветка, которая имеет для вас значение, требует define с Datepickk действуя как модульная фабрика. Когда RequireJS выполняет define звони, тут же звонит Datepickk построить модуль. В этой ситуации this не установлен на какое-либо конкретное значение, поэтому он устанавливается на текущий Window экземпляр (виртуальная машина JavaScript делает это) и Object.freeze выходит из строя. define звонок должен быть:

    define(function () {
        return Datepickk;
    });
    

    (Я также удалил жестко закодированное имя модуля.) Это создает модуль, который имеет значение для функции Datepickk,

Другие вопросы по тегам