Javascript 将pushState()和popstate添加到我的项目中

Javascript 将pushState()和popstate添加到我的项目中,javascript,jquery,html,html5-history,Javascript,Jquery,Html,Html5 History,我有一个项目,我正在工作,有一个画廊。画廊的工作方式是,用户会看到一个图像列表,每个图像都是一个“相册”,链接到给定画廊的更多图像。我目前有这样的功能,但是当用户在进入所选库后单击“上一步”按钮时,他们不会返回到相册列表。例如,如果您正在浏览主页,请单击相册页面,然后打开一个图库。单击后退按钮后,您将返回主页 所以我想,为了解决这个问题,我可以使用history api并使用pushState和popstate。我的问题是,我无法让它工作,我不确定在我给定的脚本中把函数放在哪里 如果您希望我在这

我有一个项目,我正在工作,有一个画廊。画廊的工作方式是,用户会看到一个图像列表,每个图像都是一个“相册”,链接到给定画廊的更多图像。我目前有这样的功能,但是当用户在进入所选库后单击“上一步”按钮时,他们不会返回到相册列表。例如,如果您正在浏览主页,请单击相册页面,然后打开一个图库。单击后退按钮后,您将返回主页

所以我想,为了解决这个问题,我可以使用history api并使用pushState和popstate。我的问题是,我无法让它工作,我不确定在我给定的脚本中把函数放在哪里

如果您希望我在这里工作的站点有一个实时版本:

以下是我当前的脚本:

(function(code) {
  code(window.jQuery, window, document);
}(function($, window, document) {
  $(function() {
    initialize();
  });

  function initialize() {
    $.getJSON('/assets/js/images.json', function(json) {
      $.each(json.albums, function(i, item) {
        var photos = item.photos,
            name   = item.name,
            id     = item.id;

        showAlbums(photos, name, id);
      });  
    });
  }
  function showAlbums(p, n, i) {
    var albums    = $('.albums'),
        gallery   = $('.gallery'),
        album     = $('#templates #album .thumb').clone(true),
        thumbnail = album.find('.thumbnail'),
        image     = album.find('.image'),
        caption   = album.find('.caption h4');

    thumbnail.attr('href', '#').attr('title', n).attr('data-url', i);
    image.attr('src', p[0].href).attr('alt', n);
    caption.html(n);

    albums.append(album);

    album.on('click', 'a', function(e) {
      e.preventDefault();
      albums.hide();
      gallery.empty().show();
      document.title = "Schultz | " + n;
      $.each(p, function(i, item) {
        var photo = item.href;
        showGallery(photo, n);
      });
    });
  }
  function showGallery(p, n) {
    var gallery = $('.gallery'),
        images  = $('#templates #gallery .thumb').clone(),
        link    = images.find('.thumbnail'),
        image   = images.find('.thumbnail img');

    link.attr('href', p).attr('title', n).attr('data-gallery', '');
    image.attr('src', p).attr('alt', n);

    gallery.append(images);
  }
}));

非常感谢您提供的任何帮助,谢谢您

基本上,您要做的是将相册单击处理程序重构为一个函数,该函数可以在初始化之外调用,以构建相册视图,然后在单击相册时调用该函数,并在
popstate
(后退/前进)上调用该函数

为了实现这一点,您应该存储对构建库所需的JSON数据的引用(数据本身或用于检索它的XHR)。通过这种方式,我们可以编写一个“showAlbum”函数,该函数取而代之的是一个索引或ID,我们可以使用该索引或ID访问数据中选定的相册

比如说:

// As you're doing your initialization, process the JSON array of albums
// into a hash by ID (this is one of many ways to go about this, a more
// robust solution would be to use the XHR promise to ensure the JSON is
// always there when you need it).
var albumData = {};

function initialize () {
  $.getJSON('/assets/js/images.json', function(json) {
    $.each(json.albums, function(i, item) {
      var photos = item.photos,
          name   = item.name,
          id     = item.id;

      // Same as you have now, but with this line:
      albumData[id] = item;

      showAlbums(photos, name, id);
    });  
  });
}


// Then we create a function to show an album by ID, essentially the same as
// your click handler now, but retrieving the data from the structure we
// built out of the JSON.
function showAlbumById (id) {
  e.preventDefault();
  var album = albumData[id]
    , photos = album.photos
    , name = album.name;
  albums.hide();
  gallery.empty().show();
  document.title = "Schultz | " + n;
  $.each(photos, function(i, item) {
    showGallery(item.href, name);
  });
});
然后,您将替换相册单击处理程序,以推送状态并调用该函数。这里我使用一个查询变量来表示URL中的状态,为了清晰起见,
theAlbumId
(在代码中它由
I
引用)。如果您添加了“返回相册”按钮,您将执行类似的处理程序,但按URL 没有查询变量

album.on('click', 'a', function(e) {
  e.preventDefault();
  history.pushState({}, '', '?id='+theAlbumID);
  showAlbumById(theAlbumId);
});
这应该处理pushState部分的事情,但是popstate部分的事情需要更多的工作。我们需要能够在两个州之间来回切换:显示一张专辑,或者显示专辑索引。为此,需要为popstate事件添加一个处理程序

// define `onpopstate` or add a listener for `popstate` on the window
window.onpopstate = function (state) {
  // pseudocode, you'd need to write or find a function to pull query vars
  var albumId = getQueryParameter('id');

  // if an album ID is in the query string, show it
  if (albumId) {
    showAlbumById(albumId);
  } 
  // otherwise show the index (this should probably be another function)
  else {
    albums.show();
    gallery.empty().hide();
    document.title = "Schultz";
  }
};

最后,要处理用户刷新页面或直接访问相册URL,还需要在页面加载时检查相册ID的查询字符串,并像在popstate中一样显示相册(在某些浏览器中,popstate在页面加载时运行,但不应该这样)

基本上,您要做的是将相册单击处理程序重构为一个函数,该函数可以在初始化之外调用,以构建相册视图,然后在单击相册时调用该函数,并在
popstate
(后退/前进)上调用该函数

为了实现这一点,您应该存储对构建库所需的JSON数据的引用(数据本身或用于检索它的XHR)。通过这种方式,我们可以编写一个“showAlbum”函数,该函数取而代之的是一个索引或ID,我们可以使用该索引或ID访问数据中选定的相册

比如说:

// As you're doing your initialization, process the JSON array of albums
// into a hash by ID (this is one of many ways to go about this, a more
// robust solution would be to use the XHR promise to ensure the JSON is
// always there when you need it).
var albumData = {};

function initialize () {
  $.getJSON('/assets/js/images.json', function(json) {
    $.each(json.albums, function(i, item) {
      var photos = item.photos,
          name   = item.name,
          id     = item.id;

      // Same as you have now, but with this line:
      albumData[id] = item;

      showAlbums(photos, name, id);
    });  
  });
}


// Then we create a function to show an album by ID, essentially the same as
// your click handler now, but retrieving the data from the structure we
// built out of the JSON.
function showAlbumById (id) {
  e.preventDefault();
  var album = albumData[id]
    , photos = album.photos
    , name = album.name;
  albums.hide();
  gallery.empty().show();
  document.title = "Schultz | " + n;
  $.each(photos, function(i, item) {
    showGallery(item.href, name);
  });
});
然后,您将替换相册单击处理程序,以推送状态并调用该函数。这里我使用一个查询变量来表示URL中的状态,为了清晰起见,
theAlbumId
(在代码中它由
I
引用)。如果您添加了“返回相册”按钮,您将执行类似的处理程序,但按URL 没有查询变量

album.on('click', 'a', function(e) {
  e.preventDefault();
  history.pushState({}, '', '?id='+theAlbumID);
  showAlbumById(theAlbumId);
});
这应该处理pushState部分的事情,但是popstate部分的事情需要更多的工作。我们需要能够在两个州之间来回切换:显示一张专辑,或者显示专辑索引。为此,需要为popstate事件添加一个处理程序

// define `onpopstate` or add a listener for `popstate` on the window
window.onpopstate = function (state) {
  // pseudocode, you'd need to write or find a function to pull query vars
  var albumId = getQueryParameter('id');

  // if an album ID is in the query string, show it
  if (albumId) {
    showAlbumById(albumId);
  } 
  // otherwise show the index (this should probably be another function)
  else {
    albums.show();
    gallery.empty().hide();
    document.title = "Schultz";
  }
};

最后,为了处理用户刷新页面或直接访问相册URL的问题,您还需要在页面加载时检查相册ID的查询字符串,并像在popstate中一样显示相册(popstate在某些浏览器中是在页面加载时运行的,但它不应该运行)

没有时间在这里给出完整答案,但您要做的是将相册单击处理程序重构为一个
showAlbum
函数,该函数不依赖于作用域中的局部变量,而是接受JSON数据中相册的索引或ID(您应该维护对它的引用,而不只是使用init,以便以后可以使用它)。单击相册,然后
pushState
一个新的URL可能
'?id='+id
,然后
showAlbum(id)
加载视图。然后在
window.onpopstate
中,从查询字符串中提取
id
,然后
showAlbum(id)
。当然,如果查询字符串中没有
id
,您只需隐藏
,并显示
相册(用户在库视图中单击“后退”)。在UI方面,您可能需要在页面中添加单个库中的“返回相册”按钮。一旦你开始搞乱历史记录,这类事情就显得尤为重要,例如,如果某个用户在“多媒体资料”视图中打开浏览器,他们将无法“返回”相册。谢谢你的帮助,我将尝试你的建议。一旦我确定了pushstate,我计划做的下一件事就是添加一个“返回相册”按钮。没有时间在这里给出完整的答案,但您要做的是将相册单击处理程序重构为一个
showAlbum
函数,该函数不依赖于作用域中的局部变量,在JSON数据中接受相册的索引或ID(您应该维护对它的引用,而不仅仅是使用init,以便以后可以使用它)。单击相册,然后
pushState
一个新的URL可能
'?id='+id
,然后
showAlbum(id)
加载视图。然后在
window.onpopstate
中,您可以从查询字符串中提取
id
,然后
showAlbum(id)
。当然,如果查询字符串中没有
id
,您可以