在呈现视图后,使用aurelia动态地向页面添加数据

时间:2017-05-30 12:22:47

标签: javascript html ajax typescript aurelia

我正在尝试使用aurelia构建一个Web应用程序,并且在页面上的所有内容都已呈现后,我无法通过AJAX找到添加数据的方法。场景(简化):

有一个页面,其中一部分是由一个组件(比如数据表)动态组成的。 data-table有一个标题,table-rows用来显示数据。 data-table应该通过AJAX调用动态加载它的数据。我想要的是,在呈现页面后加载数据。

我尝试使用promises,但它恰恰相反,即aurelia在附加视图之前等待承诺解决(由Jeremy Danyow解释:" ...在此示例中Aurelia将等待Promise在将视图绑定到viewmodel之前,由activate方法返回以解析。"(在他的帖子标题为" ES7 async / await with Aurelia") 这会导致页面保持停顿状态,直到加载所有数据。

下面提供了一个简单的代码示例。在这里,如果您导航到此页面,则在加载所有数据之前,您将看不到任何内容(或页面不会被附加)。我想要的是,加载页面并显示"表格..."标题,同时开始在后台加载数据并在加载完成时显示表本身。所需的行为在以下" mock"的屏幕截图。

before the ajax requrest is completed

after the ajax request is completed

此外,可能需要根据用户选择更新表格(可能会加载其他数据并将其添加到表格中),或者可能需要将其他表格添加到页面中。

我不认为所需的行为与任何绑定/附加/分离等生命周期行为相匹配(但可能是错误的)。这可以使用body.onload(或jquery等)的变体来实现,但我想知道这是否可以仅使用aurelia(或大部分)。

也许,能够在附加所有内容后加载数据(例如," postattached"回调)可能有所帮助。在这种情况下,我会用已经加载的数据(例如它们的标题)加载所有必要的组件并显示它们。然后,在" postattached"我将开始加载数据。

示例代码:

test.ts

export class testPage {
  ids: number[] = [1,2,3] // for example 1,2,3; will be dynamically loaded as well
}

的test.html

<template>
  <h1>Test</h1>

  <div repeat.for="id of ids">
    <compose view-model="./components/table" model.bind="id"></compose>
  </div>
</template>

table.ts

import { Loader } from './loader';

export class table  {
  id: number
  tableData: number[][] = []

  activate(model)  {
    this.id = model
  }

  attached() {
    Loader.LoadData(this.id).then((res)=>{this.tableData = res})
  }
}

table.html

<template>
  <h2>Table for ${id}</h2>

  <div repeat.for="rows of tableData">${rows}</div>
</template>

loader.ts

export class Loader {
  static LoadData(tid): Promise<number[][]> { //simple stub to imitate real data loading
    let data: number[][] = []
    switch (tid) {
      case 1:
        data.push([11, 12, 13])
        data.push([14, 15, 16])
        break;
      case 2:
        data.push([21, 22, 23])
        data.push([24, 25, 26])
        break;
      case 3:
        data.push([31, 32, 33])
        data.push([34, 35, 36])
        break;
    }
    this.sleep()

    return new Promise((resolve, reject) => {
      this.sleep()
      resolve(data)
    })
  }

  protected static sleep(): boolean { // just to imitate loading time
    let miliseconds = Math.floor(Math.random() * (3 - 1 + 1) + 1);
    var currentTime = new Date().getTime();
    console.debug("Wait for a sec: " + miliseconds)
    while (currentTime + miliseconds * 1000 >= new Date().getTime()) {
    }
    return true
  }
}

编辑:更正了此处示例的错误代码

1 个答案:

答案 0 :(得分:0)

您应该尝试使用window.timeout来模拟加载时间。因为Javascript是单线程的,所以sleep函数将阻止线程上的所有其他执行。

这个答案可能有点过分,但更详细地解释了如何在javascript中编写睡眠函数:What is the JavaScript version of sleep()?