是否可以转储和恢复window.angular以创建可恢复的快照

时间:2015-12-16 10:21:03

标签: angularjs

我的应用程序需要UX中的复杂步骤才能到达其中的一些状态。这使得开发/测试周期非常麻烦,因为简单的布局更改必须在各种状态下进行可视化验证。

所以,我正在考虑以这样的方式获取正在运行的应用程序的转储/快照(即window.angular,或者也许是$ rootscope)的实用性,以便我可以快速从该快照恢复,运行一个$ rootscope。$ digest()和et voila。

有关如何实现这一目标的任何建议?

我不希望恢复的快照能够正常运行,例如,它不需要有活跃的观察者或广播订阅。它只需忠实地呈现视觉检查视图。

- 编辑 -

我开始认为这无法完成。

我已经意识到,从现在开始我的所有Angular项目都将拥有一个名为VmStateService的服务,基本上,影响渲染视图的每一项VM数据都必须生效在这个单一服务中,它被注入每个控制器。这样我只有一个干净的对象(它没有任何功能),我可以转储到字符串,或保存到本地存储,然后恢复以创建我想要测试的任何视图。

我想很不幸的是,每个人都通过$ scope.foo =" bar"来学习AngularJS,然后花费其余的职业生涯来实现创造的混乱。

4 个答案:

答案 0 :(得分:1)

简单地使用JSON.Stringify的问题在于它不会正确捕获函数,也不会捕获合法的undefined值或循环引用。你可以用作起点的东西是Node JS的util.inspect()

https://github.com/nodejs/node/blob/master/lib/util.js#L87

这已经完成了一半的工作 - 读取对象,正确格式化,管理所有细微差别。还读取函数和循环引用。你必须做另外一半的工作来翻译它,但你应该能够。

(这些是Node的许可条款 - 对于Node本身的MIT许可,其他库可能稍微严格(但不是那么多)):

https://raw.githubusercontent.com/nodejs/node/master/LICENSE

答案 1 :(得分:1)

修改

首先,如果您有兴趣做的就是获取视觉检查的视图,为什么不这样做?

document.body.parentNode.innerHTML

但是,你可能想要更多,特别是如果你想捕获任何输入字段的值等,这些东西不是由DOM的静态HTML表示的。

要解决您的问题,您必须捕获所需的任何信息,以重新创建视图状态。在Angular中,这可能意味着:

  • 当前网址
  • $ rootScope
  • 上的任何值
  • 向视图层提供数据的任何服务的内部状态。

除非您针对此功能规划应用程序架构,否则很难做到这一点。无论你如何分割它,你都需要进行一些重构。您还需要一个鼓励您可以快照的状态的体系结构,以便能够保存/恢复未来的开发。

听起来你可以从FLUX架构中受益。如果您不熟悉FLUX,我建议您查看at the flux website

我已经在我的Enterprise Angular应用程序中实现了一个版本的FLUX,使用RxJS进行操作,并为商店提供服务(我只是将它们命名为<Feature>Store,并通过{{1}注入它们})。

但是,Flux的实施可能会解决您正在寻找的问题,https://github.com/rackt/redux。 Redux是围绕React构建的,因此您需要构建从应用程序状态层到视图的桥梁(可以由Angular控制)。

Redux将应用程序状态保存在单个JS对象中,并跟踪该对象的每个原子更改。理论上,您可以立即保存/加载应用程序状态。

答案 2 :(得分:0)

这是一个天真的尝试。

用法:

  • serialize($rootScope)获取根范围的字符串,序列化版本以及您将保存在文件,localStorage等中的子项

  • restore(myCopy, $rootScope)将所有内容放回$ rootScope。 myCopy是之前复制方法返回的字符串序列化版本。

仅序列化自定义属性(而非函数)。任何以美元符号开头的东西都被视为私有角,不应该被混淆。如果您碰巧拥有以$符号开头的自定义属性,则可以将该函数调整为仅忽略私有角色。

function serialize(target, source) {
  source = source || {};
  for (var key in target) {
    if (!target.hasOwnProperty(key)) { continue; }
    if (key[0] === '$' || key === 'constructor') continue;

    if (typeof target[key] !== 'function') {
      try {
        source[key] = JSON.stringify( target[key] );
      } catch(e) {}
    }
  }

  if (target.$$nextSibling) {
    source.$$nextSibling = {};
    serialize(target.$$nextSibling, source.$$nextSibling);
  }

  if (target.$$childHead) {
    source.$$childHead = {};
    serialize(target.$$childHead, source.$$childHead);
  }

  return JSON.stringify(source);
}

function restore(copy, $rootScope) {
  try {
    copy = JSON.parse(copy);
  } catch(e) {}

  for (var key in copy) {
    if (!copy.hasOwnProperty(key)) { continue; }

    try {
      $rootScope[key] = JSON.parse(copy[key]);
    } catch(e) {
      $rootScope[key] = copy[key];
    }
  }

  if (copy.$$nextSibling) {
    $rootScope.$$nextSibling = $rootScope.$$nextSibling || {};
    restore(copy.$$nextSibling, $rootScope.$$nextSibling);
  }

  if (copy.$$childHead) {
    $rootScope.$$childHead = $rootScope.$$childHead || {};
    restore(copy.$$childHead, $rootScope.$$childHead);
  }
}

// Create a $rootScope serialized copy that can be stored in local storage, etc
var copy = serialize($rootScope);

// Restore a serialized copy into $rootScope
restore(copy, $rootScope);

答案 3 :(得分:0)

我看到我的小项目可以部分满足您的要求。

https://github.com/vorachet/angular-state-manager

它还很年轻,设计目标是成为一个维护工具,以帮助Angular应用程序理解。我欢迎您研究您的详细要求,并尝试继续开发以解决您的问题。