我正在关注一本关于SPA - 单页Web应用程序的书。这很有趣,但我被一段代码阻止了。到目前为止,我明白我在做什么,所以看起来很奇怪,这没有醒来。
我有一个在聊天点击时触发的事件,该点击位于页面右下角。此事件触发 URL 哈希的更改,但是..即使我用$(window).bind('hashchange', onHashchange()).trigger('hashchange');
将其绑定到窗口,也不会触发哈希更改事件
我需要手动刷新页面以查看聊天从打开到关闭的变化,但这不应该发生,因为我希望它由onhashchange
触发。你能帮我找出发生了什么吗?
看起来我错过了一些东西,但是周围的每个人都抱怨无法与其他浏览器兼容,而在这种情况下只是无法正常工作:S
任何提示都值得赞赏=)
我有以下 html 代码
<html>
<head>
<title>SPA starter</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/spa.css" type="text/css">
<link rel="stylesheet" href="css/spa.shell.css" type="text/css">
<!-- 3rd party lib -->
<script id="jquery_js" src="js/libs/jquery/jquery.js"></script>
<script id="janchor_js" src="js/libs/jquery/jquery.uriAnchor.js"></script>
<!-- my lib -->
<script id ="spajs" src="js/spa.js"></script>
<script id="spashelljs" src="js/spa.shell.js"></script>
<script id="unloader" src="js/js_unloader.js"></script>
<script id="starter">
$(function() {
spa.initModule($('#spa'));
});
</script>
</head>
<body>
<div id="spa"></div>
</body>
</html>
和 3 个脚本 + jquery 清晰。第一个脚本可以在这里找到,由本书的作者提供,另外两个如下
温泉.js
var spa = (function() {
var initModule = function($container) {
spa.shell.initModule($container);
};
return {initModule: initModule};
}());
斯帕壳.js
spa.shell = (function() {
//----------- BEGIN MODULE SCOPE VARIABLES ---------
var configMap = {
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: 250,
chat_retract_time: 300,
chat_extend_height: 450,
chat_retract_height: 15,
chat_extended_title: 'Click to retract',
chat_retracted_title: 'Click to extend',
anchor_schema_map: {
chat: {open: true, closed: true}
}
},
stateMap = {
$container: null,
is_chat_retracted: true,
anchor_map: {}
},
jqueryMap = {},
setJqueryMap, toogleChat, onClickChat,
copyAnchorMap, changeAnchorPart, onHashchange,
initModule;
//----------- END MODULE SCOPE VARIABLES ---------
//----------- BEGIN UTILITY METHODS ---------
//Return copy of stored anchro map; minimizes overhead
copyAnchorMap = function() {
return $.extend(true, {}, stateMap.anchor_map);
};
//----------- END UTILITY METHODS ---------
//----------- BEGIN DOM METHODS ---------
//Begin DOM method /changeAnchorPart/
changeAnchorPart = function(arg_map) {
console.log("change anchor part");
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)) {
//console.log("key_name:= " + key_name);
//skip dependet keys during iteration
if (key_name.indexOf('_') === 0) {
console.log("key name starts with '_'");
continue KEYVAL;
}
//update independent key value
anchor_map_revise[key_name] = arg_map[key_name];
//update matching dependent key
key_name_dep = '_' + key_name;
//console.log("key_name_dep:= " + key_name_dep);
if (arg_map[key_name_dep]) {
//console.log("if");
anchor_map_revise[key_name_dep] = arg_map[key_name_dep];
}
else {
//console.log("else");
delete anchor_map_revise[key_name_dep];
delete anchor_map_revise['_s' + key_name_dep];
}
}
}
//END merge changes into anchor map
//BEGIN ateempt to update URI; revert if not successful
try {
console.log("setting anchor");
$.uriAnchor.setAnchor(anchor_map_revise);
console.log("set");
} catch (error) {
//replace URI with existing state
$.uriAnchor.setAnchor(stateMap.anchor_map, null, true);
console.log("changeAnchorPart error :=" + error);
bool_return = false;
}
//END attemp to update URI
return bool_return;
};
//END DOM method /changeAnchorPart/
//begin DOM method /setJqueryMap/
setJqueryMap = function() {
var $container = stateMap.$container;
jqueryMap = {$container: $container,
$chat: $container.find('.spa-shell-chat')
};
};
//end DOM method /setJqueryMap/
//Begin DOM method /toogleChat/
//
toogleChat = 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) {
console.log('avoid race condition');
return false;
}
//begin 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 rectract chat slider
};
//end DOM method /toogleChat/
//----------- END DOM METHODS ---------
//
//----------- BEGIN EVENT HANDLERS ---------
onClickChat = function(event) {
// console.log(stateMap.is_chat_retracted);
changeAnchorPart({
chat: (stateMap.is_chat_retracted ? 'open' : 'closed')
});
return false;
};
//
// BEGIN event handler /onHashchange/
//
onHashchange = function(event) {
console.log("on hash change");
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) {
console.log("onHashchange error:= " + 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 of component if changed
if (!anchor_map_previous || _s_chat_previous !== _s_chat_proposed) {
s_chat_proposed = anchor_map_proposed.chat;
console.log("adjusting components, chat:= " + s_chat_proposed);
switch (s_chat_proposed) {
case 'open':
toogleChat(true);
break;
case 'closed':
toogleChat(false);
break;
default :
toogleChat(false);
delete anchor_map_proposed.chat;
$.uriAnchor.setAnchor(anchor_map_proposed, null, true);
}
}
//END of the adjustment
return false;
};
//END event handler /onHashchange/
//----------- END EVENT HANDLERS ---------
//----------- BEGIN PUBLIC METHODS ---------
//Begin Public methods /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
//
if ("onhashchange" in window) {
console.log('SUPPORTED');
}
$(window).bind('hashchange', onHashchange()).trigger('hashchange');
};
//End PUBLIC methods /initModule/
return {initModule: initModule};
//----------- END PUBLIC METHODS ---------
}());
水疗.css
*{
margin : 0;
padding : 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
h1,h2,h3,h4,h5,h6, p{ margin-bottom: 10px;}
o1,ul,dl{list-style-position: inside;}
/** end reset */
/** begin standard selectors */
body{
font: 13px 'Trebuchet MS', Verdana, Helvetica, Arial, sans-serif;
color: #444;
background-color: #888;
}
strong{
font-weight: 800;
color:#000;
}
/** end standard selectors */
/** begin spa namespace selectors */
#spa{
position: absolute;
top:8px;
left:8px;
bottom:8px;
right:8px;
min-height: 500px;
min-width: 500px;
overflow: hidden;
border-radius: 0 8px 0 8px;
background-color: #fff;
}
/** end spa namespace selectors */
/** begin utility selectors */
.spa-x-select{}
.spa-x-clearfloat{
height: 0 !important;
float: none !important;
visibility: hidden !important;
clear: both !important;
}
/** */
斯帕壳.css
.spa-shell-head, .spa-shell-head-logo, .spa-shell-head-acct, .spa-shell-head-search,
.spa-shell-main, .spa-shell-main-content, .spa-shell-main-nav, .spa-shell-foot,
.spa-shell-chat, .spa-shell-modal {
position: absolute;
}
.spa-shell-head{
top:0;
left:0;
right:0;
height: 40px;
background-color: red;
}
.spa-shell-head-logo{
top: 4px;
left: 4px;
height: 32px;
width: 128px;
background: orange;
}
.spa-shell-head-acct{
top:4px;
right:0;
width: 64px;
height: 32px;
background: green;
}
.spa-shell-head-search{
top:4px;
right:64px;
width: 248px;
height: 32px;
background: blue;
}
.spa-shell-main{
top:40px;
left:0;
bottom:40px;
right:0;
background-color: #993300;
}
.spa-shell-main-content, .spa-shell-main-nav{
top:0;
bottom:0;
}
.spa-shell-main-nav{
width:250px;
background: #eee;
}
.spa-x-closed, .spa-shell-main-nav{
width:0;
}
.spa-shell-main-content{
left:250px;
right:0;
background: #ddd;
}
.spa-x-closed .spa-shell-main-content{
left:0;
}
.spa-shell-foot{
bottom:0;
left:0;
right:0;
height:40px;
background-color: #99ffff;
}
.spa-shell-chat{
bottom:0;
right:0;
width: 300px;
height: 15px;
background: burlywood;
z-index: 1;
cursor:pointer;
border-radius: 5px 0 0 0;
}
.spa-shell-modal{
margin-top:-200px;
margin-left:-200px;
top:50%;
left:50%;
width:400px;
height:400px;
background: #fff;
border-radius: 3px;
z-index: 2;
}
弄错了,请纠正我,但您正在绑定中执行该函数。你想要这样:
$(window).bind('hashchange', onHashchange).trigger('hashchange');
后面没有"()"。
请记住,在某些浏览器中对此的支持是有限的。
摘自:jQuery - hashchange event
if (("onhashchange" in window) && !($.browser.msie)) {
window.onhashchange = function () {
alert(window.location.hash);
}
// Or $(window).bind( 'hashchange',function(e) {
// alert(window.location.hash);
// });
}
else {
var prevHash = window.location.hash;
window.setInterval(function () {
if (window.location.hash != prevHash) {
prevHash = window.location.hash;
alert(window.location.hash);
}
}, 100);
}
根据您的需求进行调整。