Ember FastBoot SimpleDOM正文为空

时间:2017-03-19 22:22:26

标签: javascript ember.js ember-cli

我试图在FastBoot环境中的实例初始化程序中读取DOM,但document.body似乎是空的。以下代码在浏览器中有效,但在FastBoot中不返回任何内容:

const ELEMENT_NODE_TYPE = 1;

// TODO(maros): Get this working with FastBoot. For some reason the SimpleDOM
// body is empty.
const findBootstrapData = (document) => {
  for (let currentNode = document.body.firstChild; currentNode; currentNode = currentNode.nextSibling) {
    if (currentNode.nodeType !== ELEMENT_NODE_TYPE) {
      continue;
    }

    if (currentNode.getAttribute('class') === 'bootstrap-data') {
      return JSON.parse(currentNode.firstChild.nodeValue);
    }
  }
};

export function initialize(appInstance) {
  const store = appInstance.lookup('service:store');
  const document = appInstance.lookup('service:-document');

  const data = findBootstrapData(document);
  if (data) {
    store.push({ data: data.posts });
  }
}

export default {
  name: 'blog-posts',
  initialize
};

我尝试阅读的数据已使用Ember CLI插件注入{{content-for "body"}}部分。没有FastBoot,这可以很好地工作。

如何让这个实例初始化程序在FastBoot中运行?

编辑:

有关额外的上下文,请参阅我使用Ember CLI Addon填充DOM的方法:

/* eslint-env node */
'use strict';

const fs = require('fs');
const path = require('path');
const convertMarkdown = require('marked');
const parseFrontMatter = require('front-matter');

// Reads blog posts from `/posts`, compiles from markdown to HTML and stores
// as JSON in a script tag in the document. An instance initializer then picks
// it up and hydrates the store with it.
module.exports = {
  name: 'blog-posts',

  contentFor: function(type) {
    if (type !== 'body') {
      return;
    }

    const dirname = path.join(__dirname, '..', '..', 'posts');
    const data = fs.readdirSync(dirname).map((filename, index) => {
      if (!filename.endsWith('.md')) {
        return;
      }

      const fileContent = fs.readFileSync(path.join(dirname, filename), 'utf-8');
      const frontMatter = parseFrontMatter(fileContent);

      return {
        id: index + 1,
        type: 'post',
        attributes: {
          title: frontMatter.attributes.title,
          body: convertMarkdown(frontMatter.body),
        },
      };
    });

    return `
      <script class="bootstrap-data" type="text/template">
        ${JSON.stringify({ posts: data })}
      </script>
    `;
  }
};

1 个答案:

答案 0 :(得分:0)

在应用启动生命周期中,

document.body将始终为空。由于渲染尚未完成(在实例初始化阶段),因此不会替换fastboot占位符。

您可以执行以下任一操作:

  1. 您可以使用鞋盒API推送并获取fastboot引导数据:http://ember-fastboot.com/docs/user-guide#the-shoebox

  2. 如果您想在应用生命周期之外执行此操作,那么您可以在fastboot.visit请求完成后以及调用result.html()之后执行此操作。