我正在尝试构建一个小型Web应用程序,但我不清楚如何在页面的不同部分之间进行通信。我将使用我的特定功能来演示我的问题。
我的所有页面都使用通用工具栏。由于此工具栏用于多个页面,因此它位于自己的PHP文件中,我使用
包含该文件<?php include("../toolbar.php"); ?>
工具栏包含登录按钮。单击时,将打开模式登录对话框(在本例中为Facebook登录对话框)。当用户登录时,他或她的名字将显示在工具栏中,登录按钮将被“注销”按钮替换。由于无论用户正在查看哪个页面,此行为都是相同的,因此我创建了toolbar.js文件以显示模态中的日志并相应地更新用户名/按钮。
但是,在大多数页面上,登录或退出工具栏还需要更新主页面的内容。我无法保证每个包含toolbar.php的页面在登录状态发生变化时都必须执行任何操作,但大部分都会更改。
同样,反过来也是可能的 - 某个页面可能在工具栏外面有一个“登录”按钮。使用它时,工具栏需要更新。
处理此问题的最佳方法是什么?
目前的实施 - 这可能很糟糕......
在toolbar.js中,每当用户登录时,我基本上都会调用一个函数'userSignedIn'(和注销的等价物)。 toolbar.js,实现它本身(它需要更新它的按钮和用户名标签)。
然后,如果主页面(让我们称之为mainPage.php)需要额外的东西,我将重新使用同样的功能来“添加”其他操作。在加载该页面时,我会执行以下操作:
var originalUserSignedIn = userSignedIn;
userSignedIn = function() {
originalUserSignedIn();
customUserSignedIn();
}
customUserSignedIn是mainPage.js中的一个函数,我在其中执行其他操作。我还没有实现相反的解决方案(从mainPage.php登录需要更新toolbar.php)。
我想来自Objective-C背景,我正在尝试类似于在方法实现中调用'super'的东西。
答案 0 :(得分:1)
一种方法是在任何其他javascript之前初始化一个空数组来保存回调函数和sign函数来调用它们:
var userSignedInCallbacks = [];
var userSignedIn = function() {
for (var i = 0; i < userSignedInCallbacks.length; i++) {
userSignedInCallbacks[i]();
}
}
然后,工具栏和主页js都会将相应的回调添加到数组中:
userSignedInCallbacks.push(function() {
// ...
});
最后,工具栏或主页中的登录操作都只会调用userSignedIn()
。
答案 1 :(得分:1)
一种方法是使用publisher-subscriber模式处理页面中不同模块之间的通信,以便每个模块仅耦合在事件接口上。
我创建了一个非常简单的示例here。它不处理注销过程,但您仍然可以看到事情的结构。
HTML
<div id="toolbar">
<button class="login">Login</button>
</div>
<div id="another-section">
<button class="login">Login</button>
</div>
<div id="login-dialog">
<button class="login">Do login!</button>
</div>
JS
//in EventBus.js
var EventBus = {
subscribers: {},
publish: function (eventName) {
var args = Array.prototype.slice.call(arguments, 1),
subscribers = this.subscribers[eventName] || [],
i = 0,
len = subscribers.length,
s;
for (; i < len; i++) {
s = subscribers[i];
s.fn.apply(s.scope, args);
}
},
subscribe: function (eventName, fn, scope) {
var subs = this.subscribers[eventName] = this.subscribers[eventName] || [];
subs.push({ fn: fn, scope: scope });
}
};
//in toolbar.js
function Toolbar(el, eventBus) {
var $el = this.$el = $(el),
$loginButton = $('button.login', $el);
$loginButton.click(function () {
eventBus.publish('userWantsToLogin');
});
eventBus.subscribe('userLoggedIn', function () {
$loginButton.html('Logout');
//change button handlers to handle logout...
});
}
//in another-section.js
function AnotherSection(el, eventBus) {
var $el = this.$el = $(el),
$loginButton = $('button.login', $el);
$loginButton.click(function () {
eventBus.publish('userWantsToLogin');
});
eventBus.subscribe('userLoggedIn', function () {
$loginButton.html('Logout');
//change button handlers to handle logout...
});
}
//in main.js
$(function () {
var $loginDialog = $('#login-dialog');
$loginDialog.dialog({ autoOpen: false});
$('button.login', $loginDialog).click(function () {
EventBus.publish('userLoggedIn');
});
EventBus.subscribe('userWantsToLogin', function () {
$loginDialog.dialog('open');
});
new Toolbar('#toolbar', EventBus);
new AnotherSection('#another-section', EventBus);
});