【问题标题】:"Cannot perform operations on a Metamorph that is not in the DOM" - in <= IE8 only“无法对不在 DOM 中的 Metamorph 执行操作” - 仅在 <= IE8 中
【发布时间】:2012-05-23 19:19:19
【问题描述】:

使用 Ember 0.9.7.1

当我的应用程序启动并进入第一个状态时,在 IE8 及以下版本中出现此错误。我有一个相当大的应用程序,所以我不确定我是否可以在 jsFiddle 中重现,但我会尝试在下面展示相关的部分。

我在 GitHub 上查看过这些类似的问题,但我认为两者都没有准确描述我做错了什么(一定是我……对吧?:))

https://github.com/emberjs/ember.js/issues/752
https://github.com/emberjs/ember.js/issues/447

我的应用的初始视图由状态管理器创建/加载,如下所示:

SYOS.stateManager = Em.StateManager.create({

    enableLogging: true,
    rootElement: #syos-root,
    initialState: 'noSectionSelected',

    noSectionSelected: Ember.ViewState.create({

        view: SYOS.SelectSectionView,

        chooseSection: function (manager, context) {

            manager.goToState('sectionSelected');

        }

    }),
<snip>

那个视图基本上定义为:

SYOS.SelectSectionView = Em.View.extend({

templateName: 'selectSectionView',
sectionsBinding: 'SYOS.sectionController.sections'
});

模板的精简版如下所示:

<script type="text/x-handlebars" data-template-name="selectSectionView">

<h2>Some markup</h2>

<table class="select-sect" cellspacing="0">
{{#each sections}}
    {{#view SYOS.SelectSectionRowView sectionBinding="this" tagName="tr"}}
    <td class="sect">{{section.name}}</td>
    {{/view}}
{{/each}}
</table>

</script>

如果有帮助,这个模板直接在我的 html 中定义。

当我加载页面时,控制台日志显示:

日志:STATEMANAGER:输入 noSectionSelected SCRIPT438:对象不支持此属性或方法 ember-0.9.7.1.min.js,第 10 行字符 30680 SCRIPT5022:无法对不在 DOM 中的 Metamorph 执行操作。 ember-0.9.7.1.min.js,第 13 行字符 29412 SCRIPT5022:抛出异常但未捕获 ember-0.9.7.1.min.js,第 13 行字符 16607

使用 IE 的调试器 (eww) 中断第一个错误,我可以看到错误 似乎 发生在 #each 变形标记上。它在这一行中断:

g.prototype.checkRemoved=function(){if(this.isRemoved())throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.")}

因为 this.isRemoved() 返回 true。在调试器中检查this 我看到this.start == "metamorph-6-start"。如果我在工作浏览器中搜索那个变形标记,它似乎是我模板中 #each 块的开始标记。

sectionBinding 是一个从 jQuery .ajax 调用加载的数组,所以最初它是 [],然后在我的控制器中循环 ajax 调用的结果时使用 this.get('sections').pushObject(section); 填充。

在此状态下,我不会执行任何动态视图附加或删除操作,它只需要在部分从 ajax 服务调用返回时加载视图并绑定它们。

任何人都可以在这个问题上为我指出正确的方向吗?谢谢!

编辑:更新到 Ember 0.9.8.1,现在控制台中的错误少了一个:

日志:STATEMANAGER:输入 noSectionSelected SCRIPT5022:无法对不在 DOM 中的 Metamorph 执行操作。 ember-0.9.8.1.min.js,第 14 行字符 4051 SCRIPT438:对象不支持此属性或方法 ember-0.9.8.1.min.js,第 10 行字符 31677

【问题讨论】:

    标签: ember.js


    【解决方案1】:

    跟进这件事,让任何谷歌员工知道我必须做些什么来解决这个问题。

    简而言之 - 我通过彻底修改我的视图以及它们如何添加到应用程序来解决这个问题。

    我强烈建议任何对 Ember 应用程序感到奇怪的人使用 Ember 的 Debug 版本运行他们的应用程序。控制台中提供的断言和反馈非常宝贵。

    我实际上遇到了两个问题:

    1) 在构建上表的#each 中,我与另一个#each 一起使用了绑定的车把助手(在http://codebrief.com/2012/03/eight-ember-dot-js-gotchas-with-workarounds/ 上找到并且非常非常有用)。

    由于嵌套如此之深,我不得不使用{{ boundHelper this}} 调用绑定助手,这似乎真的把事情搞砸了。 Chrome、Firefox 和 IE9 似乎并没有对此感到窒息——不知道为什么。但基本上使用带有this 的绑定助手最终将'' 传递给 normalizePath,并导致此断言失败

    function normalizePath(path) {
      Ember.assert('must pass non-empty string to normalizePath()', path && path!=='');
    

    我通过将 boundHelper 更改为对值数组或单个值起作用来解决此问题,因此我可以将其写为 {{boundHelper colors}} 并在我的助手中循环而不是使用 #each

    2) 所以,一个问题下来了,但仍然得到原来的变形错误。清除另一个错误后,我现在可以判断变形错误完全来自另一个视图。

    我有 2 个嵌套视图,它们使用 #view 帮助器在我的 HTML 中定义。不知何故,嵌套视图导致父级重新渲染。同样,Ember 的调试版本是一个很好的工具,可以在控制台中记录有关它的消息。

    我不是 100% 确定为什么会出现这样的问题,但似乎在重新渲染过程中,变形标记不存在,并且很合适。这看起来确实可能是 Ember 中的一个错误,但更有可能的是我只是没有按照“Ember 方式”做某事。与 Ember 一样好,它也很容易让你的脚离开 :)

    我最终将这些内联视图制作成 Handlebars 模板,并将视图附加到 Ember App.ready 函数中的 DOM。这清除了所有错误,IE 7 和 8 现在可以无错误地呈现应用程序。

    【讨论】:

      【解决方案2】:

      当我在 HTML cmets 中发现一些把手代码时,我刚刚解决了这个问题。有问题的代码可能刚刚被删除或包裹在把手 cmets 中,如下所示:

      {{!--
          <h1>{{myTitle}}</h1>
      --}}
      

      【讨论】:

      • 谢谢斯科特。那正是我的问题! (呼)
      • 谢谢斯科特。也一样!
      【解决方案3】:

      我遇到了这个问题,因为我们试图这样做:

      <input size="16" type="text" valueBinding="{{deadline}}">
      

      事实上它应该是:

      <input size="16" type="text" {{bindAttr valueBinding="deadline"}}>
      

      【讨论】:

      • 救了我的培根!谢谢:-)
      【解决方案4】:

      我今天刚刚遇到这个问题,希望我的经验对其他人有所帮助。我们看到了相同的错误消息,并且在删除了所有注释掉的车把代码后,将此引用更改为显式的 #each 对象名称,但没有任何效果。

      事实证明,如果您多次嵌套 #with 和 #each,视图可能会有点不稳定:

      {{#with view.content.project as project}}
          //set some project fields
          {{#each job in project.jobs}}
              {{#with job}}
                  // set job some fields
              {{#/with}}
              {{#each task in job.tasks}}
                  {{#with task}}
                      // set tasksome fields
                  {{#/with}}
              {{/each}}
          {{/each}}
      {{/with}}
      

      我们发现,如果我们在第一个 #each 之前使用 (#with view.content.project as project) 关闭项目,错误就会消失。我不确定为什么会出现问题,但是,也许这会帮助其他人解决同样的问题。

      有效的代码:

      {{#with view.content.project as project}}
          //set some project fields
      {{/with}}
      {{#each job in project.jobs}}
          {{#with job}}
              // set job some fields
          {{#/with}}
          {{#each task in job.tasks}}
              {{#with task}}
                  // set tasksome fields
              {{#/with}}
          {{/each}}
      {{/each}}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-23
        • 1970-01-01
        • 2012-10-15
        • 2015-08-03
        • 2020-07-27
        相关资源
        最近更新 更多