TreeSaver.js 的工作流程逻辑

Treesaver 是浏览器大小尺寸敏感(size-sensitive)的,会就着当前的浏览器尺寸(browser size),选用不同的分栏表格(grid)做排版。

初始化

TreeSaver.js 框架的入口源代码在后面可以看到:https://github.com/Treesaver/treesaver/blob/master/src/init.js

这里的代码用到了Google开发的JS库:Closure Library,Closure Library的一个显著特点就是支持namespacing system(命名空间)。用过.Net和Java的对这个很熟悉。

这里init.js 文件的goog.provide('treesaver'); 就是表明以后如果你想用这个文件,你只需要引用名称空间:treesaver。goog.require('treesaver.boot');则是引用名称空间。

Closure 代码 .net等同代码 java等同代码
goog.provide('treesaver'); namespace treesaver package treesaver
goog.require('treesaver.boot'); using treesaver.boot; import treesaver.boot;

初始化最核心的代码在:treesaver.ui.ArticleManager.load = function(initialHTML) {}

这个函数的调用堆栈如下,调用者在前面,被调用者在后面:

https://github.com/Treesaver/treesaver/blob/master/src/init.js
treesaver.boot.load = function() {}
treesaver.boot.loadProgress_ = function() {}
treesaver.core.load = function() {}
treesaver.ui.ArticleManager.load = function(initialHTML) {}

treesaver.ui.ArticleManager.load 传入的参数是我们页面的Html代码的Body部分。这个代码在显示上最核心的几段代码我加了中文注释。

/**
 * Initialize all content
 * @param {?string} initialHTML
 */
treesaver.ui.ArticleManager.load = function(initialHTML) {
  // Initialize state
  treesaver.ui.ArticleManager.currentArticle = null;
  treesaver.ui.ArticleManager.currentPosition = null;
  treesaver.ui.ArticleManager.currentPageIndex = -1;
  treesaver.ui.ArticleManager.currentArticleIndex = null;
  treesaver.ui.ArticleManager.currentTransitionDirection = null;
  treesaver.ui.ArticleManager.currentPageWidth = null;
  // Data store
  treesaver.ui.ArticleManager.articleOrder = [];
  treesaver.ui.ArticleManager.articleMap = {};
  treesaver.ui.ArticleManager.articles = {};
  treesaver.ui.ArticleManager.toc = [];
  /**
   * @private
   */
  treesaver.ui.ArticleManager.grids_ = treesaver.ui.ArticleManager.getGrids_();
  if (!treesaver.ui.ArticleManager.grids_) {
    treesaver.debug.error('No grids');
    return false;
  }
  // Set up the loading & error pages
  treesaver.ui.ArticleManager.initLoadingPage();
  treesaver.ui.ArticleManager.initErrorPage();
  treesaver.ui.ArticleManager.initialUrl = treesaver.network.stripHash(document.location.href);
  treesaver.ui.ArticleManager.initialHTML = initialHTML;
  // Set the display to the current article?
  if (initialHTML) {
    // ××××××  开始构造显示 ××××××××××
     var initialArticle = new treesaver.ui.Article(treesaver.ui.ArticleManager.initialUrl,
                                          document.title,
                                          treesaver.ui.ArticleManager.grids_,
                                          initialHTML);
    if (!initialArticle.error) {
      // 缓存
      treesaver.ui.ArticleManager.articles[treesaver.ui.ArticleManager.initialUrl] = initialArticle;
      treesaver.ui.ArticleManager._setArticle(initialArticle, null, 0, true);
    }
    else {
      treesaver.debug.warn('Error in initial article');
      // Unload and show plain content
      treesaver.core.unload();
    }
  }
  else {
    treesaver.debug.warn('No initial article');
    // What to do here?
  }
  // Set up event handlers
  // *********** 文章分页,下一篇文章等的事件捆绑  **********
  treesaver.ui.ArticleManager.watchedEvents.forEach(function(evt) {
    treesaver.events.addListener(document, evt, treesaver.ui.ArticleManager.handleEvent);
  });
  window['onpopstate'] = treesaver.ui.ArticleManager.onPopState;
  // Download the table of contents
  treesaver.ui.ArticleManager.generateTOC();
  return true;
};

每次调整浏览器尺寸后

上面初始化代码中我们可以看到下面的代码:

// Set up event handlers
  treesaver.ui.ArticleManager.watchedEvents.forEach(function(evt) {
    treesaver.events.addListener(document, evt, treesaver.ui.ArticleManager.handleEvent);
  });

treesaver.ui.ArticleManager.handleEvent 函数的实现如下:

/**
 * @param {Object} e
 */
treesaver.ui.ArticleManager.handleEvent = function(e) {
  if (e.type === treesaver.ui.Article.events.PAGINATIONPROGRESS) {
    // We have new pages to display
    // TODO
    // Fire event
    treesaver.events.fireEvent(document, treesaver.ui.ArticleManager.events.PAGESCHANGED);
    return;
  }
  if (e.type === treesaver.ui.Article.events.LOADED) {
    // TODO
    // If it's the current article, kick off pagination?
    // If it's the next, kick it off too?
    // Where does size come from?
    treesaver.events.fireEvent(document, treesaver.ui.ArticleManager.events.PAGESCHANGED);
    return;
  }
  if (e.type === treesaver.ui.Article.events.LOADFAILED &&
      e.article === treesaver.ui.ArticleManager.currentArticle) {
    // The current article failed to load, redirect to it
    treesaver.ui.ArticleManager._redirectToArticle(treesaver.ui.ArticleManager.currentArticle);
    return;
  }
};

TreeSaver的根控件就是 Chrome, 所以上面发出的事件会被下面代码拦截到:事件调度入口:

https://github.com/Treesaver/treesaver/blob/master/src/ui/chrome.js

这里的下面函数是所有事件的调度入口:

/**
 * Event dispatcher for all events
 * @param {Event} e
 */
treesaver.ui.Chrome.prototype['handleEvent'] = function(e) {
  switch (e.type) {
  // Both these events mean that the pages we are displaying
  // (or trying to display) may have changed. Make sure to
  // fetch them again
  // Article changed and TOC changed will affect nav indicators
  case treesaver.ui.ArticleManager.events.PAGESCHANGED:
    return this.selectPagesDelayed();
  case treesaver.ui.ArticleManager.events.TOCUPDATED:
    this.updateTOCDelayed();
    return this.selectPagesDelayed();
  case treesaver.ui.ArticleManager.events.ARTICLECHANGED:
    this.updateTOCActive(e);
    return this.updatePageURL(e);
  case 'mouseover':
    return this.mouseOver(e);
  case 'touchstart':
    return this.touchStart(e);
  case 'touchmove':
    return this.touchMove(e);
  case 'touchend':
    return this.touchEnd(e);
  case 'touchcancel':
    return this.touchCancel(e);
  case 'keydown':
    return this.keyDown(e);
  case 'click':
    return this.click(e);
  case 'mousewheel':
  case 'DOMMouseScroll':
    return this.mouseWheel(e);
  }
};
原文地址:https://www.cnblogs.com/ghj1976/p/2119729.html