模块内的访问属性(CommonJS 样式)

Posted

技术标签:

【中文标题】模块内的访问属性(CommonJS 样式)【英文标题】:Access property within module (CommonJS style) 【发布时间】:2013-11-25 07:17:45 【问题描述】:

在 Appcelerator Titanium 中,我正在创建一个最初设置为某些文本的标签。然后我添加一个按钮,单击该按钮会调用 scanController 模块,并且该模块需要更改该文本。所以在 scanController 中,我在下面看到的 scanView 模块中调用setResultTxt() 方法。但是当它说myResultTxt 是空的!这是为什么呢?

我仍在使用 Titanium SDK 1.7.5,因为升级到较新版本时遇到问题。

这是该问题的完整工作示例:

app.js

var win = Titanium.UI.createWindow(  
    backgroundColor:'#fff',
    layout:"vertical"
);
win.open();

var module = require('scanView');

module.createScanPage(win);

scanView.js

var myResultTxt, theButton;

exports.createScanPage = function(theWindow) 
    myResultTxt = Ti.UI.createLabel(
        text: 'Some initial text',
        top:40,
    );
    theWindow.add(myResultTxt);

    theButton = Ti.UI.createButton(
        title: 'Do something',
        top:20
    );
    theButton.addEventListener('click', function() 
        alert('clicked');
        var b = require('scanController');
        b.startScanning();
    );
    theWindow.add(theButton);
;

exports.setResultText = function(str) 
    myResultTxt.text = str;
;

scanController.js

exports.startScanning = function() 
    var a = require('scanView');
    a.setResultText('My new text');
;

【问题讨论】:

我使用 Titanium SDK 3.1.4 运行您的代码,并且运行正常。问题出在代码的不同部分,或者是旧 SDK 的问题,最好弄清楚如何更新到最新版本。 【参考方案1】:

虽然循环引用应该使用 CommonJS (This thread suggests it) 我个人避免使用它们,因为你可能会得到意想不到的结果,尤其是在 Titanium 和不同平台上。

您可以使用回调或事件侦听器,在您的情况下都可以。

以下是回调解决方案的示例:

scanView.js

theButton.addEventListener('click', function() 
     var b = require('scanController');
     // You could pass an existing function as well 
     b.startScanning(function(response) 
         if(response && response.text) 
             myResultTxt.text = response.text;
         
     );
);

scanController.js

exports.startScanning = function(callback) 
    callback( text:'My new text');
;

编辑: 要使任何模块都可以使用 setText,您可以设置一个全局事件监听器。 (我知道有些人认为这是不好的做法,主要是因为可能存在内存泄漏,但如果你在背后清理它是一个有价值的功能)。

app.js

Ti.App.addEventListener('app:setScanText', module.setResultText);

scanController.js

exports.startScanning = function() 
    Ti.App.fireEvent('app:setScanText',  text: 'My new text' );
;

scanView.js

exports.setResultText = function(response) 
    if(response && response.text) 
        myResultTxt.text = response.text;
    
;

这是未经测试的。

【讨论】:

这是一个很好的建议,但它不能在我的项目中使用,因为 startScanning() 也被其他模块调用......它不仅在 scanView 模块中被调用,还创建了标签。所以我需要找到一个解决方案,如何从我的项目中的任何地方访问myResultTxt... 啊,我明白了,我已经用 eventListener 示例更新了上面的代码。 我也试过了,但是当使用setResultText() 访问时,myResultTxt 仍然未定义。我想我必须放弃使用 CommonJS 并返回将所有属性和方法附加到单个全局对象... 嗯,触发事件时是否调用了 setResultTxt 函数?您是否尝试在函数中添加警报/调试以检查响应是什么? 是的,setResultText 被调用并且参数正确地保存了传递给它的内容。但由于某种原因,myResultTxt 并不是指原始的 myResultTxt,它只是未定义。我现在很确定这是旧 SDK 中的一个错误...

以上是关于模块内的访问属性(CommonJS 样式)的主要内容,如果未能解决你的问题,请参考以下文章

node--CommonJS

requireJS

CommonJS规范

ES6中export , export default , import模块系统总结

CommonJS 规范中的 modulemodule.exports 区别

node-学习之路02 commonJS模块