我有这个事件监听器,我试图找出为什么它会在浏览器URL文本框中的URI发生变化时被触发。代码中没有其他对此函数的引用。代码来自单页应用程序一书。
$(window)
.bind( 'hashchange', onHashchange )
.trigger( 'hashchange' );
这是所有的代码:除了我的问题之外,我理解所有这些代码。我相信大部分都可以忽略。我只是想让你在上下文中看到它。
spa.shell = (function () {
//---------------- BEGIN MODULE SCOPE VARIABLES --------------
var
configMap = {
anchor_schema_map : {
chat : { open : true, closed : true }
},
main_html : String()
+ '<div class="spa-shell-head">'
+ '<div class="spa-shell-head-logo"></div>'
+ '<div class="spa-shell-head-acct"></div>'
+ '<div class="spa-shell-head-search"></div>'
+ '</div>'
+ '<div class="spa-shell-main">'
+ '<div class="spa-shell-main-nav"></div>'
+ '<div class="spa-shell-main-content"></div>'
+ '</div>'
+ '<div class="spa-shell-foot"></div>'
+ '<div class="spa-shell-chat"></div>'
+ '<div class="spa-shell-modal"></div>',
chat_extend_time : 1000,
chat_retract_time : 300,
chat_extend_height : 450,
chat_retract_height : 15,
chat_extended_title : 'Click to retract',
chat_retracted_title : 'Click to extend'
},
stateMap = {
$container : null,
anchor_map : {},
is_chat_retracted : true
},
jqueryMap = {},
copyAnchorMap, setJqueryMap, toggleChat,
changeAnchorPart, onHashchange,
onClickChat, initModule;
//----------------- END MODULE SCOPE VARIABLES ---------------
//------------------- BEGIN UTILITY METHODS ------------------
// Returns copy of stored anchor map; minimizes overhead
copyAnchorMap = function () {
return $.extend( true, {}, stateMap.anchor_map );
};
//-------------------- END UTILITY METHODS -------------------
//--------------------- BEGIN DOM METHODS --------------------
// Begin DOM method /setJqueryMap/
setJqueryMap = function () {
var $container = stateMap.$container;
jqueryMap = {
$container : $container,
$chat : $container.find( '.spa-shell-chat' )
};
};
// End DOM method /setJqueryMap/
toggleChat = function ( do_extend, callback) {
var
px_chat_ht = jqueryMap.$chat.height(),
is_open = px_chat_ht === configMap.chat_extend_height,
is_closed = px_chat_ht === configMap.chat_retract_height,
is_sliding = ! is_open && ! is_closed;
// avoid race condition
if ( is_sliding ) { return false; }
// Begin extend chat slider
if ( do_extend ) {
jqueryMap.$chat.animate(
{ height : configMap.chat_extend_height },
configMap.chat_extend_time,
function () {
jqueryMap.$chat.attr(
'title', configMap.chat_extended_title
);
stateMap.is_chat_retracted = false;
if ( callback ) { callback( jqueryMap.$chat ); }
}
);
return true;
}
// End extend chat slider
// Begin retract chat slider
jqueryMap.$chat.animate(
{ height : configMap.chat_retract_height },
configMap.chat_retract_time,
function () {
jqueryMap.$chat.attr(
'title', configMap.chat_retracted_title
);
stateMap.is_chat_retracted = true;
if ( callback ) { callback( jqueryMap.$chat ); }
}
);
return true;
// End retract chat slider
};
changeAnchorPart = function ( arg_map ) {
var
anchor_map_revise = copyAnchorMap(),
bool_return = true,
key_name, key_name_dep;
// Begin merge changes into anchor map
KEYVAL:
for ( key_name in arg_map ) {
if ( arg_map.hasOwnProperty( key_name ) ) {
// skip dependent keys during iteration
if ( key_name.indexOf( '_' ) === 0 ) { continue KEYVAL; }
// update independent key value
anchor_map_revise[key_name] = arg_map[key_name];
// update matching dependent key
key_name_dep = '_' + key_name;
if ( arg_map[key_name_dep] ) {
anchor_map_revise[key_name_dep] = arg_map[key_name_dep];
}
else {
delete anchor_map_revise[key_name_dep];
delete anchor_map_revise['_s' + key_name_dep];
}
}
}
// End merge changes into anchor map
// Begin attempt to update URI; revert if not successful
try {
$.uriAnchor.setAnchor( anchor_map_revise );
}
catch ( error ) {
// replace URI with existing state
$.uriAnchor.setAnchor( stateMap.anchor_map,null,true );
bool_return = false;
}
// End attempt to update URI...
return bool_return;
};
// End DOM method /changeAnchorPart/
//--------------------- END DOM METHODS ----------------------
//------------------- BEGIN EVENT HANDLERS -------------------
// Begin Event handler /onHashchange/
// Purpose : Handles the hashchange event
// Arguments:
// * event - jQuery event object.
// Settings : none
// Returns : false
// Action :
// * Parses the URI anchor component
// * Compares proposed application state with current
// * Adjust the application only where proposed state
// differs from existing
//
onHashchange = function ( event ) {
var
anchor_map_previous = copyAnchorMap(),
anchor_map_proposed,
_s_chat_previous, _s_chat_proposed,
s_chat_proposed;
// attempt to parse anchor
try { anchor_map_proposed = $.uriAnchor.makeAnchorMap(); }
catch ( error ) {
$.uriAnchor.setAnchor( anchor_map_previous, null, true );
return false;
}
stateMap.anchor_map = anchor_map_proposed;
// convenience vars
_s_chat_previous = anchor_map_previous._s_chat;
_s_chat_proposed = anchor_map_proposed._s_chat;
// Begin adjust chat component if changed
if ( ! anchor_map_previous
|| _s_chat_previous !== _s_chat_proposed
) {
s_chat_proposed = anchor_map_proposed.chat;
switch ( s_chat_proposed ) {
case 'open' :
toggleChat( true );
break;
case 'closed' :
toggleChat( false );
break;
default :
toggleChat( false );
delete anchor_map_proposed.chat;
$.uriAnchor.setAnchor( anchor_map_proposed, null, true );
}
}
// End adjust chat component if changed
return false;
};
// End Event handler /onHashchange/
// Begin Event handler /onClickChat/
onClickChat = function ( event ) {
changeAnchorPart({
chat : ( stateMap.is_chat_retracted ? 'open' : 'closed' )
});
return false;
};
// End Event handler /onClickChat/
//-------------------- END EVENT HANDLERS --------------------
//------------------- BEGIN PUBLIC METHODS -------------------
// Begin Public method /initModule/
initModule = function ( $container ) {
// load HTML and map jQuery collections
stateMap.$container = $container;
$container.html( configMap.main_html );
setJqueryMap();
// initialize chat slider and bind click handler
stateMap.is_chat_retracted = true;
jqueryMap.$chat
.attr( 'title', configMap.chat_retracted_title )
.click( onClickChat );
// configure uriAnchor to use our schema
$.uriAnchor.configModule({
schema_map : configMap.anchor_schema_map
});
// Handle URI anchor change events.
// This is done /after/ all feature modules are configured
// and initialized, otherwise they will not be ready to handle
// the trigger event, which is used to ensure the anchor
// is considered on-load
//
$(window)
.bind( 'hashchange', onHashchange )
.trigger( 'hashchange' );
};
// End PUBLIC method /initModule/
return { initModule : initModule };
//------------------- END PUBLIC METHODS ---------------------
}());
答案 0 :(得分:0)
我几乎只读了一页Web应用程序,我已经学到了很多关于如何编写干净的独立JavaScript模块以及如何配置每个模块的知识。这本书回答了很多设计问题,这些问题一直在我脑海中浮现。
我相信您的问题的答案在第123页。此代码块的边距注释是“更新onClick事件处理程序以调用更改URI锚点然后立即退出,将hashchange事件处理程序保留在壳牌公司接受了这一变化。“
当您单击聊天滑块时,将执行此回调,然后窗口的hashchange事件会自动执行spa.shell.onHashChange。
//------------------- BEGIN EVENT HANDLERS -------------------
onClickToggle = function ( event ){
var set_chat_anchor = configMap.set_chat_anchor;
if ( stateMap.position_type === 'opened' ) {
set_chat_anchor( 'closed' );
}
else if ( stateMap.position_type === 'closed' ){
set_chat_anchor( 'opened' );
} return false;
};
//-------------------- END EVENT HANDLERS --------------------