3

我是 ExtJS 的新手。尝试在应用程序中使用和自定义选项卡功能。

我想用Javascript Scope 的 ExtJs 范围内的参数调用一个函数。现在我可以在不传递参数的情况下调用函数而不会出现任何错误。当我通过传递参数(在代码中提到)调用相同的函数时,它给了我以下错误,因为函数没有获取任何值。

Uncaught TypeError: Cannot call method 'indexOf' of null

此功能应将新选项卡添加到选项卡面板。

当我通过从 ExtJS 范围传递参数来调用相同的函数时,它会成功添加选项卡。但不是当函数通过传递参数从javascript范围调用时。帮助我理解并解决这个问题。

Ext.onReady(function() {
var currentItem;
var tabs = Ext.widget('tabpanel', {
    launch: function() {
      _myAppGlobal = this;
    },
    renderTo: 'tabs',
    resizeTabs: true,
    enableTabScroll: true,
    width: 850,
    defaults: {
        autoScroll: true,
        bodyPadding: 10
    }], 
    plugins: Ext.create('Ext.ux.TabCloseMenu', {
        extraItemsTail: [
            '-',
            {
                text: 'Closable',
                checked: true,
                hideOnClick: true,
                handler: function (item) {
                    currentItem.tab.setClosable(item.checked);
                }
            },
            '-',
            {
                text: 'Enabled',
                checked: true,
                hideOnClick: true,
                handler: function(item) {
                    currentItem.tab.setDisabled(!item.checked);
                }
            }
        ],
        listeners: {
            aftermenu: function () {
                currentItem = null;
            },
            beforemenu: function (menu, item) {
                menu.child('[text="Closable"]').setChecked(item.closable);
                menu.child('[text="Enabled"]').setChecked(!item.tab.isDisabled());

                currentItem = item;
            }
        }
    })
  });

  function addTab_inside(closeable, tabtitle, targetUrl) {
      tabs.add({
          title: tabtitle,
          iconCls: 'tabs',
          autoLoad: {url: targetUrl, callback: this.initSearch, scope: this},
          closable: closeable,
          autoScroll: true,
          nocache: true,
          discardUrl: false
      }).show();
  }
});

function addTab_Outside(){
   addTab_inside(true, 'Test', 'test.php');
}

addTab_Outside 函数基于事件并在 xyz 元素上调用 onClick。

4

2 回答 2

2

没有 Ext 范围之类的东西。Ext 是一组 JS 对象和函数,不多不少。因此,适用于 JS 的所有内容都适用于 Ext。任何范围界定问题和复杂性都纯粹是 JavaScript 的问题,并且对于 Ext 与任何其他 JS 库或实用程序没有任何不同。

现在,让我们看看你做了什么:

  1. 您使用一些参数调用了 Ext.onReady() 函数。
  2. 您在全局范围(也称为窗口范围)中定义了一个函数 addTab_Outside()。

就这些。

现在让我们看看 addTab_Outside 函数。在此函数中,您正在调用另一个函数 addTab_inside。但是这个“内部”功能在哪里?JS应该去哪里找这个函数呢?由于您在全局范围内定义了'ouside'函数,那么JS将在同一范围内查找内部函数并且将无法找到它,因为它不是在全局范围内创建的。

那么“内部”函数是在什么范围内创建的呢?好吧,让我们回到您在这里做的第一件事:Ext.onReady() 函数调用。你调用了这个函数,传入了一个参数。该参数是一个匿名函数,具有 2 个局部变量currentItemtabs. 您还创建了一个名为“addTab_inside”的本地函数。当我说“本地”时,这意味着变量对于在其范围内创建它们的函数是本地的。在您的情况下,父函数是匿名的,因此不可寻址。当然,该函数中的任何局部变量都可以相互访问,因为它们都在同一范围内。所以只要'tabs'引用'inside'函数或者currentItem你就可以了。

您的解决方案将起作用的唯一方法是将外部函数移动到大型匿名函数块中。但我怀疑你不想这样做,因为真的没有理由这样做。

尽管对范围的讨论很重要,但我的直觉是,无论您尝试做什么,都应该采用不同的方法。如果您正在构建一个完整的应用程序,那么我建议您使用 Sencha 指南中概述的应用程序结构,使用控制器和文件夹结构来分隔您的代码。

于 2013-03-07T07:17:53.033 回答
1

addTab_inside(true, 'Test', 'test.php');将在 Ext.onReady 之前运行。所以,你的功能还不存在。将 addTab_inside 移动到 Ext.onReady 方法的底部。

更新

@dbrin 在这里解释了范围界定问题做得很好。如果你真的想让你的方法工作,你需要设置一些“命名空间”,如下所示。

//Namespace defined in Global scope
var myApp = {};

Ext.onReady(function(){ 
  //Some stuff... 

  myApp.addTab_inside = function(closeable, tabtitle, targetUrl){
    //do work
  }
});

function addTab_Outside(){
  myApp.addTab_inside(true, 'Test', 'test.php');
}

正如我之前提到的,您仍然需要确保addTab_inside在 Ext 准备好之前不打电话。

综上所述,我建议您查看@dbrin 提到的有关建议的 MVC 架构的教程。

于 2013-03-06T17:44:21.753 回答