0

诚然,我还是 Dojo 的新手,而且我的 Javascript 一直很薄弱,所以在这里原谅和草率的代码或语言。

我将 Dojo 1.7.1 与 Spring Roo 1.2.1RELEASE 一起使用。我正在通过Google的 CDM 加载 Dojo 。

我前段时间创建了一个自定义图像缩略图查看器以在我的站点上使用,我通过在 Spring Roo 的 load-scripts.tagx 中向我的 djConfig 添加一个模块来包含该模块,该模块在每个页面加载时运行。缩略图小部件不遵循 AMD 模式,因为当时我无法让它正常工作。

这是 djConfig:

  <script type="text/javascript">
    var djConfig = {
            parseOnLoad: false, 
            isDebug: false, 
            locale: '${fn:toLowerCase(userLocale)}',
            modulePaths:    {
                "message": "${message_dojo_url}",
                "img.ArtThumbnailWidget": "${artThumbnailWidget_dojo_url}",
                "img.ArtTableWidget": "${artTableWidget_dojo_url}",
            },
        };
  </script>

这是缩略图的 JS:

// img.ArtThumbnailWidget
dojo.provide("img.ArtThumbnailWidget");

dojo.require("dojo._base.declare");
dojo.require("dojo.parser");
dojo.require("dojo.ready");
dojo.require("dijit._WidgetBase");
dojo.require("dijit._TemplatedMixin");
dojo.require("dojox.image.LightboxNano");

// Create the widget
require([
         "dojo/_base/declare",
         "dojo/parser",
         "dojo/ready",
         "dijit/_WidgetBase",
         "dijit/_TemplatedMixin",
         "dojo/dom",
         "dojo/dom-construct",
         "dojo/on",
         "dojo/text!img/ArtThumbnailWidget/templates/ArtThumbnailWidget.html",
         "dojox/image/LightboxNano",
         "dojo/domReady!"
    ], function(declare, parser, ready, _WidgetBase, _TemplatedMixin, dom, domConstruct, on, template) {

    dojo.declare("img.ArtThumbnailWidget",[dijit._WidgetBase, dijit._TemplatedMixin], {
        /* Our properties will go here */

        // Art JSON object, default is null
        art: null,

        // Viewer ID (the username of the person looking at this image), which will default to null
        viewerId: null,

        // maxThumbnailSize is how large of an image to return for the thumbnail.  The back-end will resize the thumbnail accordingly
        maxThumbnailSize: 100,

        // maxImageSize is how large of an image to return for the LightboxNano.  The back-end will resize the image accordingly
        maxImageSize: 500,

        // Our template - important!
        templateString: template,

        // A class to be applied to the root node in our template
        baseClass: "artThumbnailWidget",

        // Specifies there are widgets in the template itself that need to be rendered as well
        widgetsInTemplate: true,

        // Competition-related vars
        competitionUrlBase: null,
        competitionButtonIconUrl: null,

        /* This is called once the DOM structure is ready, but before anything is shown */
        postCreate: function() {
            // Get a DOM node reference for the root of our widget
            var domNode = this.domNode;

            // Run any parent postCreate processes - can be done at any point
            this.inherited(arguments);

            if(this.art!=null && this.viewerId!=null && this.art.owner.name == this.viewerId) {     // If the view is the owner, add the toolbar
                // TODO: We need to clean this up, make it "prettier", and make the URLs more generic
                var toolbarNode = domConstruct.create("div", {}, this.containerNode);

                if(this.competitionUrlBase!=null) {
                    var url = this.competitionUrlBase;
                    if(url.indexOf('?')<0) {    // URL does not have a '?'
                        url = url+"?";
                    } else {    // URL has a '?', so we need to tack on and additional '&'
                        url = url+"&";
                    }
                    url = url+"username="+this.art.owner.name+"&artPieceId="+this.art.id;

                    var compButtonNode = domConstruct.create("a",
                            {
                                href: url,
                            },toolbarNode);
                    var compButtonImg = domConstruct.create("img",
                            {
                                src: this.competitionButtonIconUrl,
                                width: this.maxThumbnailSize/4,
                                height: this.maxThumbnailSize/4,
                            },compButtonNode);
                }
            }
        },

        /* This private method is used to re-set the node values when something changes  */
        _resetNodeValues: function() {
            if(this.art !=null) {
                // Using our thumbnailNode attach point, set its src value
                this.thumbnailNode.src = this.art.url+"?maxSize="+this.maxThumbnailSize;
                this.thumbnailNode.alt = this.art.title;
                this.thumbnailNode.width = this.maxThumbnailSize;
                this.thumbnailNode.height = this.maxThumbnailSize;

                // Now setup the link for the LightboxNano
                var lightboxNano = new dojox.image.LightboxNano({
                    href: this.art.url+"?maxSize="+this.maxImageSize,
                },this.thumbnailNode);
            }
        },

        /* This is called anytime the "art" attribute is set.  Consider is a "setter" method */
        _setArtAttr: function(av) {
            if (av != null) {
                // Save it on our widget instance - note that
                // we're using _set, to support anyone using
                // our widget's Watch functionality, to watch values change
                this._set("art", av);

                this._resetNodeValues();
            } else {
                // We could have a default here...would be an error, since we
                // shouldn't be calling this without an art object
            }
        },

        _setMaxThumbnailSizeAttr: function(ms) {
            // Save it on our widget instance - note that
            // we're using _set, to support anyone using
            // our widget's Watch functionality, to watch values change
            this._set("maxThumbnailSize", ms);

            this._resetNodeValues();
        },

        _setMaxImageSizeAttr: function(ms) {
            // Save it on our widget instance - note that
            // we're using _set, to support anyone using
            // our widget's Watch functionality, to watch values change
            this._set("maxImageSize",ms);

            this._resetNodeValues();
        }
    });     // End of the widget

});

现在我正在尝试添加另一个自定义组件,即上述缩略图的表格。新代码需要引用这个旧的 Widget,但我似乎无法让它工作。

新的表格小部件(到目前为止):

// in "img/ArtTableWidget"
define([
        "dojo/_base/declare", "dojo/parser", 
        "dijit/_WidgetBase", "dijit/_TemplatedMixin", 
        "dojo/dom", "dojo/dom-construct","img/ArtThumbnailWidget",
        "dojo/text!./ArtTableWidget/templates/ArtTableWidget.html"], 
    function(declare,parser,_WidgetBase,_TemplatedMixin, dom, domConstruct, ArtThumbnailWidget, template) {
        return declare("img.ArtTableWidget",[dijit._WidgetBase,dijit._TemplatedMixin], {
            // Default values for the ArtTable

            // The base URL to use for downloading the photos
            artUrlBase: null,

            // The base URL used for submitting competitions and the button URL
            newCompetitionUrlBase: null,
            newCompetitionButtonIconUrl: null,

            // Indicates what params on the URL are used to control page 
            // and size.  These will be appended to the URL as needed.
            pageNumberParameterName: "page",
            pageSizeNumberParameterName: "size",

            // Holds the page and size
            page: 1,
            size: 15,
            totalPages: 0,

            columns: 3,

            // Holds the current list of "art"
            artList: [],

            // The userid currently viewing
            viewerId: null,

            // Our HTML template
            templateString: template,

            baseClass: "artTableWidget",

            // Specifies there are widgets in the template itself that need to be rendered as well
            widgetsInTemplate: true,

            // Functions //

            postCreate: function() {
                this._load(this.page);
            },

            // Loads the given page
            _load: function(pageToLoad) {
                if(pageToLoad==null) {
                    pageToLoad=1;
                }

                // Generate the URL
                genUrl = this.artUrlBase.indexOf("?")>=0 ? this.artUrlBase+"&page="+pageToLoad+"&size="+this.size : this.artUrlBase+"?page="+pageToLoad+"&size="+this.size;

                // Make the call to the backend
                dojo.xhrGet({
                    url: genUrl,
                    handleAs: "json",
                    tableWidget: this,
                    load: function(data,ioArgs) {
                        this.tableWidget.page = data.page;
                        this.tableWidget.totalPages = data.totalPages;
                        this.tableWidget.artList = data.data;

                        this.tableWidget._updateTable();
                    }
                });
            },

            _updateTable: function() {
                // Fix the buttons at the bottom

                // Clear the artTable
                domConstruct.empty(this.artTable);

                // Loop through the art and build the rows
                tableRow = tableRow = domConstruct.create("tr",{},this.artTable);
                dojo.forEach(this.artList,function(art,index) {
                    if(index % columns == 0) {
                        tableRow = domConstruct.create("tr",{},this.artTable);
                    }
                    tableColumn = domConstruct.create("td",{style: { marginLeft: "auto", marginRight: "auto" }},tableRow);
                    var tnNode = new ArtThumbnailWidget({
                        art: art,
                        viewerId: this.viewerId,
                        competitionUrlBase: this.newCompetitionUrlBase,
                        competitionButtonIconUrl: this.newCompetitionButtonIconUrl,
                    });
                    tnNode.placeAt(tableColumn);
                });
            }
        });
});

但是,当我在 Chrome 中运行新组件时,我在 dojo.js.uncompressed.js 行 1716 中收到一个通用错误。错误消息是“multipleDefine”,并且附加的对象看起来是我的 ArtTableWidget。我在挖掘这个对象时注意到“deps”成员,它似乎是在顶部定义()中定义的所有依赖项的数组,其中包括 img/ArtThumbnailWidget,但“pack”成员是未定义的. 我猜它只是没有加载我的模块或其他东西。

错误(抱歉,如果复制/粘贴看起来不正确)是:

dojo.js.uncompressed.js:1716
Error
  arguments: undefined
  get stack: function getter() { [native code] }
  info: Object
  cacheId: 0
  cjs: Object
  def: function (declare,parser,_WidgetBase,_TemplatedMixin, dom, domConstruct, ArtThumbnailWidget, template) {
  deps: Array[8]
    0: Object
    1: Object
    2: Object
    3: Object
    4: Object
    5: Object
    6: Object
      cacheId: 0
      def: 0
      executed: 4
      injected: 2
      isAmd: false
      isXd: null
      mid: "img/ArtThumbnailWidget"
      pack: undefined
      pid: ""
      result: Object
      url: "/ArtSite/resources/img/ArtThumbnailWidget.js"
      __proto__: Object
    7: Object
    length: 8
    __proto__: Array[0]
    executed: 0
    injected: 2
    isAmd: false
    isXd: null
    mid: "img/ArtTableWidget"
    node: HTMLScriptElement
    pack: undefined
    pid: ""
    require: function (a1, a2, a3){
    result: Object
    url: "/ArtSite/resources/img/ArtTableWidget.js"
    __proto__: Object
  message: "multipleDefine"
  set stack: function setter() { [native code] }
  src: "dojoLoader"
  type: undefined
  __proto__: ErrorPrototype
  dojo.js.uncompressed.js:1719src: dojoLoader
  dojo.js.uncompressed.js:1719info: 
  Object
  dojo.js.uncompressed.js:1721.

我需要一些帮助才能回到正确的轨道。

编辑 1 我使用 BuffaloBuffalo 的回复中的信息更新了所有模块,除了 dojoConfig 中的“路径”,我使用了以下内容:

    <script type="text/javascript">
    var djConfig = {
            parseOnLoad: false, 
            isDebug: false, 
            locale: '${fn:toLowerCase(userLocale)}',
            packages: [
                 { name: "message", location: "${message_dojo_module_base_url}" },
                 { name: "img", location: "${img_dojo_module_base_url}" }
            ]
        };
  </script>

似乎找到了 .js 文件,但没有找到使用dojo/text加载的模板。我尝试做“./path/Template.html”和“/module/path/Template.html”,但第一个似乎试图通过CDN(上面链接的Google APIs站点)解析URL,后者似乎想要完全合格的路径。我关闭了一条完整的路径,因为这似乎是一种肮脏的方式。我还尝试像这样添加到 dojoConfig 的路径:

        paths: [
             { "message" : "${message_dojo_module_base_url}" }
        ]

但这似乎根本没有帮助,在 Chrome 的 JS 控制台中导致了一些非常讨厌的错误。

如果我在这里正确阅读,dojo/text 不使用模块吗?

4

2 回答 2

1

很难说出确切的问题是什么,但有几件事让我很震惊:

如果您使用的是 1.7,则djConfig应该命名该对象(dojoConfig 仍然有效,但不妨更新它)。dojoConfig

modulePaths属性应更新为命名path。如果img.ArtThumbnailWidget并且img.ArtTableWidget驻留在一个公共目录中,您可以使用以下内容:

var dojoConfig = {
            parseOnLoad: false, 
            isDebug: false, 
            locale: '${fn:toLowerCase(userLocale)}',
            paths:    {
                "message": "${message_dojo_url}",
                "img": "${art_module_url}"
            }
        };

第二件事是 img.ArtThumbnailWidget 中混合的 legacy/amd 加载器样式。使用 AMD 风格,您已经完成了 99% 的工作。你需要做的就是

  1. 删除 dojo.provide 和 dojo.requires
  2. 更新require([],function(){..});define([],function(){..});
  3. 更新声明中的引用以使用局部变量而不是全局变量:

    //ArtThumbnailWidget
    define('img/ArtThumbnailWidget', [
        "dojo/_base/declare",
        "dojo/parser",
        "dojo/ready",
        "dijit/_WidgetBase",
        "dijit/_TemplatedMixin",
        "dojo/dom",
        "dojo/dom-construct",
        "dojo/on",
        "dojo/text!img/ArtThumbnailWidget/templates/ArtThumbnailWidget.html",
        "dojox/image/LightboxNano",
        "dojo/domReady!"
        ], function (declare, parser, ready, _WidgetBase, _TemplatedMixin, dom, domConstruct, on, template) {
    
      return declare("img.ArtThumbnailWidget", [_WidgetBase, _TemplatedMixin], {
        /* Our properties will go here */
    
        // Art JSON object, default is null
        art: null,
    
        // Viewer ID (the username of the person looking at this image), which will default to null
        viewerId: null,
    
        // maxThumbnailSize is how large of an image to return for the thumbnail.  The back-end will resize the thumbnail accordingly
        maxThumbnailSize: 100,
    
        // maxImageSize is how large of an image to return for the LightboxNano.  The back-end will resize the image accordingly
        maxImageSize: 500,
    
        // Our template - important!
        templateString: template,
    
        // A class to be applied to the root node in our template
        baseClass: "artThumbnailWidget",
    
        // Specifies there are widgets in the template itself that need to be rendered as well
        widgetsInTemplate: true,
    
        // Competition-related vars
        competitionUrlBase: null,
        competitionButtonIconUrl: null,
    
        /* This is called once the DOM structure is ready, but before anything is shown */
        postCreate: function () {
          // Get a DOM node reference for the root of our widget
          var domNode = this.domNode;
    
          // Run any parent postCreate processes - can be done at any point
          this.inherited(arguments);
    
          if (this.art != null && this.viewerId != null && this.art.owner.name == this.viewerId) { // If the view is the owner, add the toolbar
            // TODO: We need to clean this up, make it "prettier", and make the URLs more generic
            var toolbarNode = domConstruct.create("div", {}, this.containerNode);
    
            if (this.competitionUrlBase != null) {
              var url = this.competitionUrlBase;
              if (url.indexOf('?') < 0) { // URL does not have a '?'
                url = url + "?";
              } else { // URL has a '?', so we need to tack on and additional '&'
                url = url + "&";
              }
              url = url + "username=" + this.art.owner.name + "&artPieceId=" + this.art.id;
    
              var compButtonNode = domConstruct.create("a", {
                href: url,
              }, toolbarNode);
              var compButtonImg = domConstruct.create("img", {
                src: this.competitionButtonIconUrl,
                width: this.maxThumbnailSize / 4,
                height: this.maxThumbnailSize / 4,
              }, compButtonNode);
            }
          }
        },
    
        /* This private method is used to re-set the node values when something changes  */
        _resetNodeValues: function () {
          if (this.art != null) {
            // Using our thumbnailNode attach point, set its src value
            this.thumbnailNode.src = this.art.url + "?maxSize=" + this.maxThumbnailSize;
            this.thumbnailNode.alt = this.art.title;
            this.thumbnailNode.width = this.maxThumbnailSize;
            this.thumbnailNode.height = this.maxThumbnailSize;
    
            // Now setup the link for the LightboxNano
            var lightboxNano = new LightboxNano({
              href: this.art.url + "?maxSize=" + this.maxImageSize,
            }, this.thumbnailNode);
          }
        },
    
        /* This is called anytime the "art" attribute is set.  Consider is a "setter" method */
        _setArtAttr: function (av) {
          if (av != null) {
            // Save it on our widget instance - note that
            // we're using _set, to support anyone using
            // our widget's Watch functionality, to watch values change
            this._set("art", av);
    
            this._resetNodeValues();
          } else {
            // We could have a default here...would be an error, since we
            // shouldn't be calling this without an art object
          }
        },
    
        _setMaxThumbnailSizeAttr: function (ms) {
          // Save it on our widget instance - note that
          // we're using _set, to support anyone using
          // our widget's Watch functionality, to watch values change
          this._set("maxThumbnailSize", ms);
    
          this._resetNodeValues();
        },
    
        _setMaxImageSizeAttr: function (ms) {
          // Save it on our widget instance - note that
          // we're using _set, to support anyone using
          // our widget's Watch functionality, to watch values change
          this._set("maxImageSize", ms);
    
          this._resetNodeValues();
        }
      }); // End of the widget
    });
    

我怀疑传统风格与 AMD 风格的结合ArtThumbnailWidget是令人困惑的ArtTableWidget

于 2012-05-09T14:09:04.457 回答
0

所以,是的,这里有很多可能是错误的。你能得到一个更小的例子吗?

  1. 绝对值得检查浏览器开发工具的“网络”选项卡,看看正在尝试加载什么。这通常有助于模块解析。同步运行(我认为你是这样),而不是异步模式也有助于在那里进行诊断。
  2. 您是否应该在 modulePaths 中注册 img/ArtThumbnailWidget 而不是 img.ArtThumbnailWidget?
  3. 从长远来看,您可能想要注册包而不是逐个模块...
  4. 您应该能够在您的小部件中引用 dojo/text!./templates/ArtThumbnailWidget.html 而不是 dojo/text!img/ArtThumbnailWidget/templates/ArtThumbnailWidget.html,但只有在您获得小部件加载。(您的模块的需求是相对于您的模块进行处理的。)
于 2012-05-09T16:11:23.073 回答