Ember 资源和故障排除

我们的最后一篇 Ember 文章为您提供了一系列资源,您可以利用这些资源进一步学习,此外还有一些有用的故障排除和其他信息。

预备知识

至少,建议您熟悉核心 HTMLCSSJavaScript 语言,并了解 终端/命令行

Ember 大量使用现代 JavaScript 特性(如类、模块等),因此深入理解这些特性将非常有益。

目标 提供更多资源链接和故障排除信息。

更多资源

一般故障排除、陷阱和误解

这远不是一个详尽的列表,但它是编写本文时(最新更新,2020 年 5 月)出现的一些内容的列表。

如何调试框架中发生的事情?

对于框架特定的事项,有 ember-inspector 附加组件,它允许检查

  • 路由和控制器
  • 组件
  • 服务
  • Promises
  • 数据(即来自远程 API — 默认来自 ember-data)
  • 废弃信息
  • 渲染性能

对于一般的 JavaScript 调试,请查看我们的 JavaScript 调试指南以及与浏览器的其他调试工具的交互。在任何默认的 Ember 项目中,都会有两个主要的 JavaScript 文件:vendor.js{app-name}.js。这两个文件都带有 sourcemap,因此当您打开 vendor.js{app-name}.js 搜索相关代码时,放置调试器后,sourcemap 将被加载,并且断点将放置在预转译代码中,以便更容易与您的项目代码关联。

有关 sourcemap、它们为何需要以及 ember-cli 如何处理它们的更多信息,请参阅高级用法:资产编译指南。请注意,sourcemap 默认启用。

ember-data 预装了;我需要它吗?

完全不需要。虽然 ember-data 解决了任何处理数据的应用程序都会遇到的最常见问题,但也可以自己开发前端数据客户端。任何功能齐全的前端数据客户端的一个常见替代方案是 Fetch API

使用框架提供的设计模式,一个使用 fetch()Route 看起来像这样

js
import Route from "@ember/routing/route";

export default class MyRoute extends Route {
  async model() {
    let response = await fetch("some/url/to/json/data");
    let json = await response.json();

    return {
      data: json,
    };
  }
}

有关指定 Route 的模型的更多信息,请参见此处。

为什么我不能只使用 JavaScript?

这是 Ember 用户从有 React 经验的人那里听到的常见问题。虽然在技术上可以使用 JSX 或任何其他形式的 DOM 创建,但目前还没有任何像 Ember 模板系统那样健壮的工具。有意的极简主义强制了某些决策,并允许更一致的代码,同时使模板更具结构性,而不是充满定制逻辑。

另请参阅:ReactiveConf 2017: Glimmer VM 的秘密

mut 助手的现状如何?

本教程没有介绍 mut,它实际上是 Ember 从双向绑定数据转向更常见、更容易理解的单向绑定数据流的过渡时期遗留下来的包袱。可以将其视为一个构建时转换,用 setter 函数包装其参数。

更具体地说,使用 mut 允许声明仅限模板的设置函数

hbs
<Checkbox
  @value={{this.someData}}
  @onToggle={{fn (mut this.someData) (not this.someData)}}
/>

然而,如果没有 mut,则需要一个组件类

js
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";

export default class Example extends Component {
  @tracked someData = false;

  @action
  setData(newValue) {
    this.someData = newValue;
  }
}

然后像这样在模板中调用

hbs
<Checkbox @data={{this.someData}} @onChange={{this.setData}} />

由于使用 mut 的简洁性,可能希望使用它。然而,mut 具有不自然的语义,在其存在期间引起了很多困惑。

有几个新想法以附加组件的形式组合在一起,它们使用公共 API,包括 ember-set-helperember-box。这两个都试图通过引入更明显/“更少魔法”的概念来解决 mut 的问题,避免构建时转换和隐式的 Glimmer VM 行为。

使用 ember-set-helper

hbs
<Checkbox @value={{this.someData}} @onToggle={{set this "someData" (not
this.someData)}} />

使用 ember-box

hbs
{{#let (box this.someData) as |someData|}}
  <Checkbox
    @value={{unwrap someData}}
    @onToggle={{update someData (not this.someData)}}
  />
{{/let}}

请注意,这些解决方案在社区成员中都不常见,总的来说,人们仍在努力寻找一种符合人体工程学且简单的 API,用于在仅限模板的上下文中设置数据,而无需后端 JS。

控制器的目的是什么?

控制器单例,可以帮助管理活动路由的渲染上下文。表面上,它们的功能与组件的后端 JavaScript 非常相似。控制器(截至 2020 年 1 月)是管理 URL 查询参数的唯一方式。

理想情况下,控制器的职责应该相当轻量,尽可能委托给组件和服务。

路由的目的是什么?

当用户在应用程序中从一个地方导航到另一个地方时,路由表示 URL 的一部分。路由只有几个职责

  • 加载渲染路由(或视图子树)所需的最少量数据
  • 控制对路由的访问,并在需要时进行重定向。
  • 处理最少量数据的加载和错误状态。

路由只有 3 个生命周期钩子,所有这些都是可选的

  • beforeModel — 控制对路由的访问。
  • model — 数据加载的地方。
  • afterModel — 验证访问。

最后,路由能够处理配置 model 产生的常见事件

  • loading — 当 model 钩子正在加载时该怎么做。
  • error — 当 model 抛出错误时该怎么做。

loadingerror 都可以渲染默认模板以及应用程序中其他地方定义的自定义模板,从而统一加载/错误状态。

有关路由可以做的所有事情的更多信息,请参阅 API 文档