将服务器数据传递给 RequireJS 模块的首选方法是什么?

What is the preferred method for passing server data to a RequireJS module?

本文关键字:方法 是什么 模块 RequireJS 数据 服务器      更新时间:2023-09-26

有没有在 RequireJS 模块中传递服务器数据的首选方法?我们当前的实现类似于以下代码片段;使用"Page"对象来保存任何服务器/动态数据,并将其传递给主引导程序。(我们目前不想使用 ajax 来填充任何依赖项)

从服务器页面:

<script data-main="scripts/main" src="scripts/require-jquery.js"></script>
<script type="text/javascript">
  define("page", function () {
      return { guid: "<%=Guid.NewGuid() %>" };
    });
</script>

主.js

require(["jquery", "jquery.alpha", "page"], function ($, alpha, page) {
    alpha.initialize(page);
});

jquery.apha.js

define(["jquery", "page"], function ($, page) {
    return {
        initialize: function () {
            console.log(page.guid);
            //logs guid as expected
        }
    }
});

我通常会做这样的事情(在后端使用 PHP,但一切正常):

<script src="scripts/require-jquery.js"></script>
<script>
require(['scripts/main'], function(App) {
  var myApp = new App({
    param1: <?=json_encode($param1);?>,
    param2: <?=json_encode($param2);?>
  });
});
</script>

然后将我的模块定义为采用配置的东西:

define(['jquery'], function($) {
  var App = function(options) {
    this.options = options;
    //blabla
  }
  // add some stuff to App.prototype maybe
  // and finally...
  return App;
});

RequireJS没有提到如何处理服务器数据,因为它是模块化javascript的一种手段。所以在这方面没有事实上的标准,你可以将RequireJS与json,ajax,php,embedded xml等结合起来。

两种方法

通常有两种方法可以做到这一点。

  1. 对从服务器获取所需数据的"dao"或"服务"模块进行建模,并使其用户可以访问(类似于您当前的方法,请参阅下面的代码示例)
  2. 定义所有模块都有权访问的全局对象

第一种方法向函数添加参数。

第二个提供全局访问。这也需要您自己的初始化代码才能开始获取数据。

这归结为个人喜好以及您有多少这样的"道"。如果您有多个模块,则可能会变得污染,因为您需要为每个 dao 模块创建一个新参数。在这种情况下,将它们全球化似乎更干净。

您的方法有问题

但是,您当前的方法存在一个问题,您将Page模块作为定义(使用define()而不是require()),因为为每个依赖于它的对象创建了一个定义模块。这可能意味着同一页面中的多个调用。而是使用:

// in seperate file page.js:
require([], function () {
  return { guid: "<%=Guid.NewGuid() %>" };
});

通过这种方式,RequireJS 将页面识别为一个模块,因为它是一个单独的文件,并且每个页面只会转到您的服务器一次。

如果您有 JSON 对象,请按照注释中提到的@yves进行 AJAX 调用。

如果您不想这样做,还有其他选择。可以将 guid 作为数据属性放在脚本标记上。此外,您可以尝试使加载器 js 文件动态化,以便在其中设置配置。

老实说,我只是打一个AJAX电话。

我今天刚开始使用RequireJS,在此之前,我习惯于像这样调用我想在页面加载时执行的函数:

<script>
my_method(<?php echo json_encode( array('opt1'=>true, 'opt2'=>false) );?>);
</script>

作为 @ziad-saab,我发现我能做的最相似的事情就是不使用 data-main 属性,而只是定义一个内联模块:

<script src="path/to/require.js"></script>
<script>
require(['my/module'],function(module){
    module.my_method(<?php echo json_encode( array('opt1'=>true, 'opt2'=>false) );?>); 
});
</script>

data-main 属性指示RequireJS在需要时尽快执行模块.js并加载所有模块依赖项。省略它(模块)并将其定义为内联模块,我可以放入PHP变量。

这样,我就不需要处理保存我的配置的模块,并且在我的环境中过渡到 requirejs 更容易。

我发现一些答案令人困惑,所以以下是您需要遵循的确切步骤,以使其为您工作:

就我而言,我是这样做的:

索引.php

<script src="/js/crm/lib/require.js"></script>
<script>
    // this is so called "named define"
    define('dto', {
        page: JSON.parse('{{ pageDTO | json_encode }}'),
        flashMessages: JSON.parse('{{ this.flashSession.getMessages() | json_encode }}')
    });
    // note we are using relative path to public dir here
    // order is also important, we need to define our dto module before bootstraping the application
    require(['/js/crm/app.js']);
</script>

应用.js

"use strict";
require.config({
    // ...
    baseUrl: '/js/crm/lib',
    paths: { app: '../app' }
});
require(['app/bootstrap']);

某模块.js

(在这种情况下.js在应用程序/引导程序中需要布局)

"use strict";
define([
    'dto',
    'jquery',
    'lodash'
], function (dto, $, _) { 
    console.log(dto);
});

注意 使用 data-main 引导应用程序,而不显式调用 require,可能会起作用,但由于争用条件。如果由于某种原因定义 dto 需要比调用主模块脚本所需的更多时间,脚本将崩溃。我们不想依赖它,所以我们自己做所有事情:)

所以这行不通(有时):

<script data-main="/js/crm/app.js" src="/js/crm/lib/require.js"></script>
<script>
    // this is so called "named define"
    define('dto', {
        page: JSON.parse('{{ pageDTO | json_encode }}'),
        flashMessages: JSON.parse('{{ this.flashSession.getMessages() | json_encode }}')
    });
</script>

使用窗口全局变量将服务器数据传输到 js 应用程序中:

 <script type="text/javascript">
    window.server_data=parseJSON(<?php echo json_encode(array ("server_data"=>"it works!"));?>);
 </script>
 <script data-main="js/application" src="js/lib/require.js"></script>

在应用中.js:

requirejs(["app/main"],function (MyApp){
     console.dir(window.server_data); //all our application need this global variable
    var myApp=new MyApp();
    myApp.init(window.server_data); //and your application now has server data
});