使用requirejs从不同的文件(模块)访问变量

时间:2015-04-16 07:38:20

标签: javascript requirejs canjs

我正在尝试在canjs中创建应用程序的MVC结构。为此,我使用requireJS来分隔不同文件中的代码。

我在谷歌搜索过,我正在关注这个tutorial,但在那个tutorail我找不到访问不同模块中的模块变量。因此我遵循this方法。

但我无法做到这一点。 这是我的代码:

requirejsconfig.js文件:

  requirejs.config({
   paths :{
    enforceDefine: true,
    waitSeconds : 0,
    jquery      : "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min", 
    main        : "view/main",
    player      : "view/player",
    PlayerModel : "/models/PlayerModel",
    hbs         : "/models/view/js/handlebars",
    fixture     : "/models/view/js/can.fixture", 
    can         : "/models/view/js/can.jquery"

 }
});

main.js:

require(["player"],function(player){
    player.PlayerModel();
 });

我想在我的控制器中使用该模型方法。

player.js:

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

     function PlayerModel(){   
        var Player = PlayerModel.Player;
         Players =can.Control({ defaults :{view:view/players.hbs' }},{
            init: function(){
                this.element.html(can.view(this.options.view, {
                    players: this.options.players
                }));
            }
      $(document).ready(function(){
        $.when(Player.findAll()).then(
         function(playersResponse){
            var players = playersResponse[0];      

            new Players('.players', {
                players: players
             });
         });
    });
  }
});

PlayerModel.js:

   define(function(){

        var Player = can.Model({
            findAll: 'GET /models/players.json',
            findOne: 'GET /players.json/{id}'
        });
        return {
            Player:Player
        }
    });

正在加载每个文件(在网络tab-chrome devtools中看到)但输出中没有填充任何内容。

任何人都可以帮助我吗? 提前谢谢!

2 个答案:

答案 0 :(得分:2)

继续使用@ekuusela所说的内容,以这种格式重构Player.js中的代码:

define(['PlayerModel'],function(){
  function PlayerModel(){ ... }
  return {
    PlayerModel: PlayerModel
  }
});

发生了什么

在内部,定义模块时遵循两个约定。这些涉及:

  1. 模块的名称(标签)
  2. 此标签代表什么。
  3. 标签模块

    将文件名作为模块的名称(除非使用shim,否则就像你一样)。换句话说,define(['Module_Name'] ...),这就是我通常读取该行的方式,可以更准确地读作define(['Module_Path_Or_Shim_Symbol_Name' ...)

    这是什么'模块'反正

    模块并不神奇 - 它只是一个特殊标记的函数映射。此映射由RequireJS维护,可能与此类似:

    var ModuleMap = {
      'Player' : function (...) { ... },
      'PlayerModel' : function (...) { ... }
    };
    

    每次访问模块时,通过requiredefine调用,都会访问此地图,并找到相关的功能。但是,这还不够 - 我们想要的是在函数中定义的东西 - 模块的基本概念是它们内部的所有东西都有模块功能范围,并且不暴露在外面。因此,为了获得对这些"东西"的访问权限,RequireJS大脑完成可以对函数做的唯一事情 - 执行它。

    var playerReference = require('Player');
    

    请注意,我使用了需要模块的CommonJS表示法,这对于我们当前的目的来说更具可读性。

    因此,在您发布的代码中,模块函数已将定义并声明为PlayerModel 作为函数,但尚未公开。由于行player.PlayerModel()期望模块返回一个对象,该对象具有一个引用您的函数的名为PlayerModel的属性,因此该模块的逻辑返回值为:

    var exposedModuleReference = { PlayerModel: PlayerModel };
    return exposedModuleReference;
    

    请注意,这意味着公开函数的名称可能与函数名称本身不同。例如,以下代码将在其他任何位置无需任何更改的情况下工作:

    define(['PlayerModel'],function(){
      function PlayerModelConstructor(){ ... }
      return {
        PlayerModel: PlayerModelConstructor
      }
    });
    

    有趣的添加

    因此,执行模块函数并将该返回值分配给引用是RequireJS大脑的一部分。另一部分是,它然后更新这个地图,现在它看起来像这样:

    var ModuleMap = {
      'Player' : { PlayerModel: PlayerModelConstructor },
      'PlayerModel' : function (...) { ... }
    };
    

    这意味着用模块函数编写的代码最多只能执行一次。

答案 1 :(得分:1)

您在PlayerModel中定义函数player.js,然后需要一个名为PlayerModel的模块,但不要将所需模块分配给任何变量。您应该首先清理代码,可能重命名一些模块并移动函数。

在这里,您尝试访问模块PlayerModel中的函数player,但player.js中的模块工厂函数不返回任何内容:

require(["player"],function(player){
   player.PlayerModel();
});

为函数参数player分配的内容只是从定义模块的函数返回的内容。 (如果要将模块定义为对象,则该对象将成为参数。)