繁体   English   中英

如何使用Javascript保存和恢复整个网站?

[英]How to save and restore the whole website using Javascript?

您好我正在使用Javascript开发自己的路由器API。 它基于#FregmentIdentifiers(document.location.hash)进行路由。

api完成了almos,但我仍然在做backbuttom事件。 每当按下后退按钮并且哈希值发生变化时,之前就会看到,旧内容将被恢复。

您知道如何保存和恢复所有内容吗?

我的问题是,如果我保存并恢复document.body.innerHTML,只会恢复标记但不会恢复事件,因此例如googlemaps停止工作。 我试图克隆document.body或document.documentElement,但javascript或者告诉我该字段没有setter或者我的克隆无效。

编辑:

为了明确我正在做的事情,我决定发布我当前的代码。 问题针对标有// TODO评论的部分。

function Router(){
var that = this;
var router = this;
var executionObservers = [];
that.routes = [];
this.registerRoute = function(route){
    that.routes.push(route);
};
var history = null;
this.init = function(){
    var i;
    var identifier = document.location.hash;
    history = new History();
    history.start();
    if(identifier.length > 0){
        identifier = identifier.substring(1,identifier.length);
        for(i = 0; i< that.routes.length; i++){
            var route = that.routes[i];
            if(route.contains(identifier)){
                route.getAction(identifier)(route.getParams(identifier));
                return true;
            }
        }
    }
    return false;
};
this.executed = function (identifier){
    var i; 
    for(i=0; i<executionObservers.length; i++){
        executionObservers[i](identifier);
    }
    document.location.hash = identifier;
};

this.addExecutionObserver = function(observer){
    executionObservers.push(observer);
};

function History(){
    var history = [];
    var timeout = 200;
    var lastAddedHash = null;
    var loop = function(callback){
        var hash = window.location.hash;
        window.setTimeout(
            function(){
                if(window.location.hash!=hash){
                    hash = window.location.hash;
                    callback(hash);
                }
                loop(callback);
            },
            timeout
        );
    };
    this.add = function(hash){
        lastAddedHash  = hash;
        window.setTimeout(addCallback(hash), timeout);          
    };
    addCallback = function(hash){
        return function(){
            var i;
            var found = false;
            for(i =0; i< history.length&&!found; i++){
                if(history[i][1] == hash){
                    found = true;
                    //TODO create backup
                    //history[i][0] = 
                }
            }
            if(!found){history.push(new Array(document.documentElement.cloneNode(true),hash));}
        }
    }
    this.setTimeout = function(micoseconds){
        timeout = microseconds;
    };
    started = false;
    this.start = function(){
        if(!started){
            started = true;
            loop(function(hash){
                var i;
                if(lastAddedHash!=null&&hash!=lastAddedHash){
                    for(i =0; i<history.length; i++){
                        if(history[i][1] == hash){
                            //TODO restore from backup
                            document.location.reload();
                        }
                    }
                }
            });
        }
    };
    router.addExecutionObserver(this.add);
}
}

Router.instance = null;
Router.getInstance = function(){
    if(Router.instance === null ){
        Router.instance = new Router();
    }
    return Router.instance;
};

/**
 * @param getParams = function(identifier)
 * @param getIdentifier = function(params)
 * @param contains = function(identifier)
 */
function Route(action, getParams, getIdentifier, contains){
    var that = this;
    var router = Router.getInstance();
    this.contains = contains;
    this.getParams = getParams;
    this.getAction = function(){
        return action;
    }
    this.reExecute = function(identifier){
        action(getParams(identifier));
    };
    this.execute = function(params){
        action(params);
        this.executed(params);
    }
    this.executed = function(params){
        router.executed('#' + getIdentifier(params));
    };
    this.register = function(){
        router.registerRoute(this);
    };
}
function PrefixedRouterConfig(prefix,paramRegexes){
    this.contains = function(identifier){
        var regex = "^" + prefix;
        for(var i=0;i<paramRegexes.length;i++){
            regex+="_"+paramRegexes[i];
        }
        regex +="$";
        var match = identifier.match(regex);
        return match != null && (typeof match) == 'object' && (match[0] == identifier);
    };
    this.getIdentifier = function(params){
        ret = prefix;
        for(var i=0;i<params.length;i++){
            ret+="_"+params[i];
        }
        return ret;
    };
    this.getParams = function(identifier){
        var regex = "^" + prefix;
        for(var i=0;i<paramRegexes.length;i++){
            regex+="_("+paramRegexes[i]+")";
        }
        regex +="$";
        var matches = identifier.match(regex);
        var ret = [];
        for(var i=1;i<matches.length;i++){
            ret.push(matches[i]);
        }
        return ret;
    };
}

我的api的示例用法可能如下所示:

config = new PrefixedRouterConfig('show_map',new Array("\\d+", "-?\\d+(?:\\.\\d+)?", "-?\\d+(?:\\.\\d+)?"));
var ROUTE_SHOW_MAP = new Route(
    function(params){
        var zoom = params[0];
        var lat = params[1];
        var lng = params[2];
        MyGmapInterface.preparePage(-1);
        addTabSelectedCallback(MyGmapInterface.tabLoaded);
        addTabClosedCallback(MyGmapInterface.tabClosed);
        MyGmapInterface.tabsLoaded = true;
        MyGmapInterface.myMap = new MyMap(lat,lng,zoom,MyGmapInterface.getMapContainer(),MyGmapInterface.notCompatible);
        MyGmapInterface.addNewCamMarkers(MyGmapInterface.loadCams());
        MyGmapInterface.initListeners();
        tabSelected(TAB_LEFT);
    },
    config.getParams,
    config.getIdentifier,
    config.contains
);
ROUTE_SHOW_MAP.register();

在包含所有Javascript文件(可能注册路由)之后,我调用了Router.getInstance()。init();

当我在某处做一个存在路径的ajax请求(手动)时,我调用ROUTE_NAME.executed()来设置fregment标识符并将其注册到历史记录中。

此外,我有一个观察者,只要执行()更改位置哈希,就会更新一些用于直接翻译的链接。

这与刷新的情况相同,因此您应该重新使用该系统。

基本上,您的哈希必须包含足够的信息来重建整个页面。 当然,有时您需要保存一些用户输入来重建页面。 这就是localStorage的用途(IE的userData)

除非你通过跟踪它们的API添加了你的事件(比如jQuery;参见http://api.jquery.com/clone#true ),否则你将无法反映已添加的事件为了让它们序列化/保存。

如果你不太可能选择使用DOM用户数据,你还需要setUserData()来序列化任何DOM用户数据(或者再次,像jQuery这样的库来跟踪它)。

如何在IFRAME中拥有所有内容并镜像父级中的所有URL片段更改,然后对iframe执行操作。 这可能是跨站点脚本问题。

你正在做的事情非常困难,因为浏览器缓存 - 它决定是否从内存加载 - 而不是你。 因此,如果上述选项不是一个选项,那么您创建此选项的唯一方法是通过浏览器扩展,它会监听选项卡后退按钮事件并相应地执行操作。

你看过jQuery历史插件了吗? 我知道在另一篇文章中你提到jQuery不是一个选项,但你可能会模仿他们的方法。

我不是这方面的专家,但由于不同的浏览器实现,我相信对于开发跨浏览器来说并不是一件容易的事。

主要网站: http//tkyk.github.com/jquery-history-plugin/#

演示页面: http//www.serpere.info/jquery-history-plugin/samples/ajax/

你想要的几乎是不可能的,你可以这样做,如果你使用像jquery这样的库来构建你的页面事件,如brettz9建议,但在你的情况下,你使用谷歌地图和其他外部库,所以它不是一个选项。 这里的方法是知道你在哪个页面,并执行初始化该页面的javascript,就好像它是第一次加载页面一样。 为此,您不仅需要跟踪页面的html,还要跟踪页面加载时执行的javascripts。

我知道的唯一方法是欺骗浏览器,使其相信每个有价值的事件都是新页面。 您可以通过使用window.location加载新页面来执行此操作,或使用get(=查询字符串)提交表单。 新位置或表单数据必须包含显示正确信息所需的所有内容。 这有其缺点 - 这是我的观点:

好:

  • 后退和前进按钮工作
  • 可以为您的数据添加书签
  • 仔细使用查询字符串数据,它为您的系统提供API

坏:

  • 每个有价值的事件都必须经过页面上传
  • 不能利用ajax
  • 你必须设计一种方法来编码查询字符串形式的系统的每个状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM