了解Ember 2中的组件

孟沛
2023-12-01

本文由Edwin ReynosoNilson Jacques进行了同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!

组件是Ember应用程序的重要组成部分。 它们允许您定义自己的,特定于应用程序的HTML标记,并使用JavaScript来实现其行为。 从Ember 2.x开始,组件将替换视图控制器 (已弃用),并且是构建Ember应用程序的推荐方法。

Ember的组件实现尽可能符合W3C的Web组件规范 。 自定义元素在浏览器中变得广泛可用后,应该很容易将Ember组件迁移到W3C标准并使其可用于其他框架。

如果您想了解有关为什么可路由组件替换控制器和视图的更多信息,请观看Ember核心团队成员 Yehuda Katz和Tom Dale的这段简短视频

Tab切换器应用程序

为了深入了解Ember组件,我们将构建一个tab-switcher小部件。 这将包括具有相关内容的一组选项卡。 单击一个选项卡将显示该选项卡的内容,并隐藏其他选项卡的内容。 很简单? 让我们开始。

与往常一样 ,如果您想在浏览器中尝试该代码,则可以在我们的GitHub存储库Ember Twiddle上找到本教程的代码。

灰烬成分的解剖

一个Ember组件由一个Handlebars模板文件和一个随附的Ember类组成。 仅当我们需要与组件进行额外交互时才需要实现此类。 组件的使用方式与普通HTML标签类似。 当我们构建标签切换器组件时,我们将能够像这样使用它:

{{tab-switcher}}{{/tab-switcher}}

Ember组件的模板文件位于目录app/templates/components 。 类文件位于app/components 。 我们使用所有小写字母命名Ember组件,并用连字符将单词分隔。 此命名是按照惯例进行的,因此我们避免了与将来的HTML Web组件的名称冲突。

我们的主要Ember组件将是tab-switcher 。 注意,我说的是主要组件,因为我们将有几个组件。 您可以将组件与其他组件结合使用。 您甚至可以将组件嵌套在另一个父组件中。 对于tab-switcher ,我们将具有一个或多个如下所示的tab-item组件:

{{#each tabItems as |tabItem| }}
  {{tab-item item=tabItem 
             setSelectedTabItemAction="setSelectedTabItem" }}
{{/each}}

如您所见,组件也可以像原生HTML元素一样具有属性。

创建一个Ember 2.x项目

要遵循此入门指南,您需要创建EMber 2.x项目。 就是这样:

使用npm安装Ember。 有关npm的教程,请参见此处

npm install -g ember-cli

在撰写本文时,它将引入版本1.13

ember -v
=> version: 1.13.8

接下来,创建一个新的Ember应用程序:

ember new tabswitcher

导航到该目录并编辑bower.json文件,以包括最新版本的Ember,ember-data和ember-load-initializers:

{
  "name": "hello-world",
  "dependencies": {
    "ember": "^2.1.0",
    "ember-data": "^2.1.0",
    "ember-load-initializers": "^ember-cli/ember-load-initializers#0.1.7",
    ...
  }
}

回到终端运行:

bower install

Bower可能会提示您输入Ember的版本解析。 从提供的列表中选择2.1版本,并在其bower.json加上一个感叹号,以将分辨率保持为bower.json

下一步启动Ember CLI的开发服务器:

ember server

最后,浏览至http:// localhost:4200 /并检查浏览器控制台的版本。

创建选项卡切换器组件

让我们使用Ember的内置生成器创建一个标签切换器组件:

ember generate component tab-switcher

这将创建三个新文件。 一个是我们HTML的Handlebars文件( app/templates/components/tab-switcher.hbs ),第二个是我们组件类的JavaScript文件( app/components/tab-switcher.js ),最后一个是测试文件( tests/integration/components/tab-switcher-test.js )。 测试组件超出了本教程的范围,但是您可以在Ember网站上阅读有关该组件的更多信息

现在运行ember server以加载服务器并导航到http:// localhost:4200 / 。 您应该会看到一条标题为“欢迎使用Ember”的欢迎消息。 那么为什么我们的组件不显示呢? 好吧,我们还没有使用过,所以现在就开始使用。

使用组件

打开应用程序模板app/templates/application.hbs 。 在h2标签之后添加以下内容以使用该组件。

{{tab-switcher}}

在Ember中,组件有两种使用方式。 第一种方法称为内联表单 ,它是在没有任何内容的情况下使用它们。 这就是我们在这里所做的。 第二种方法称为块形式 ,它允许向组件传递一个Handlebars模板,该模板将在出现{{yield}}表达式的位置的组件模板内呈现。 在本教程中,我们将坚持使用内联表单。

但是,这仍然没有在屏幕上显示任何内容。 这是因为组件本身没有任何要显示的内容。 我们可以通过将以下行添加到组件的模板文件( app/templates/components/tab-switcher.hbs )中来进行更改:

<p>This is some content coming from our tab switcher component</p>

现在,当页面重新加载时(应该自动发生),您将看到上面显示的文本。 激动人心的时刻!

创建一个选项卡项目组件

现在我们已经设置了主要的tab-switcher组件,让我们创建一些tab-item组件以嵌套在其中。 我们可以创建一个新的tab-item组件,如下所示:

ember generate component tab-item

现在将新组件的把手文件( app/templates/components/tab-item.hbs )更改为:

<span>Tab Item Title</span>
{{yield}}

接下来,让我们在主要的tab-switcher组件内嵌套三个tab-items 。 将tab-switcher模板文件( app/templates/components/tab-switcher.hbs )更改为:

<p>This is some content coming from our tab switcher component</p>

{{tab-item}}
{{tab-item}}
{{tab-item}}

{{yield}}

如上所述, yield帮助器将呈现传递到我们组件中的所有Handlebars模板。 但是,仅当我们以其块形式使用tab-switcher ,这才有用。 由于不是,所以我们可以完全删除yield助手。

现在,当我们查看浏览器时,我们将看到三个tab-item components ,都说“ Tab Items Title”。 我们的组件现在是静态的,因此让我们添加一些动态数据。

添加动态数据

当Ember应用程序启动时, 路由器负责显示模板,加载数据以及设置应用程序状态。 通过将当前URL与您定义的路由进行匹配来实现。 让我们为应用程序创建一条路由:

ember generate route application

对命令行问题回答“否”,以避免覆盖现有的application.hbs文件。 这还将生成一个文件app/routes/application.js 。 打开它并添加一个模型属性:

export default Ember.Route.extend({
  model: function(){
  });
});

模型是一个对象,代表您的应用程序提供给用户的基础数据。 用户期望看到的任何内容均应由模型表示。 在这种情况下,我们会将选项卡的内容添加到模型中。 为此,请按照以下方式更改文件:

import Ember from 'ember';

export default Ember.Route.extend({
  model: function(){
    var tabItems = [
      {
        title: 'Tab 1',
        content: 'Some exciting content for the tab 1'
      },
      {
        title: 'Tab 2',
        content: 'Some awesome content for the tab 2'
      },
      {
        title: 'Tab 3',
        content: 'Some stupendous content for the tab 3'
      }
    ];
    return tabItems;
  }
});

然后将tab-switcher模板文件( app/templates/components/tab-switcher.hbs )更改为:

{{#each tabItems as |tabItem| }}
  {{tab-item item=tabItem }}
{{/each}}

接下来,将tab-item模板文件( app/templates/components/tab-item.hbs )的内容更改为:

<span>{{item.title}}</span>
{{yield}}

最后,将application.hbs文件中的tab-switcher用法更改为:

{{tab-switcher tabItems=model}}

这演示了如何将属性传递给组件。 我们已经使tab-item组件模板可以访问item属性。 页面刷新后,您现在应该看到选项卡项目标题反映了来自模型的数据。

使用动作添加互动

现在,确保当用户单击tab-item标题时,我们将显示该tab-item的内容。 将tab-switcher模板文件( app/templates/components/tab-switcher.hbs )更改为:

{{#each tabItems as |tabItem| }}
  {{tab-item item=tabItem setSelectedTabItemAction="setSelectedTabItem" }}
{{/each}}

<div class="item-content">
  {{selectedTabItem.content}}
</div>

此更改假定我们在tab-switcher组件上具有tabItem属性。 此属性表示当前选择的tab-item 。 我们目前没有任何此类属性,因此让我们进行处理。

在常规模板中,操作会冒泡到控制器。 在组件模板内部,该操作会上升到组件的类。 它不会使层次结构进一步冒泡。

我们需要一种将点击操作发送到tab-switcher组件的方法。 单击其任何子tab-item组件后,应该会发生这种情况。 记得我曾说过,操作被发送到组件的类,而不是进一步到达层次结构。

因此,似乎不可能有任何来自子组件的动作到达父组件。 不用担心,因为这只是组件的默认行为,并且有一种变通方法来规避它。

一种简单的解决方法是将操作添加到tab-switcher模板( app/templates/components/tab-switcher.hbs ),如下所示:

{{#each tabItems as |tabItem| }}
  <div {{action "setSelectedTabItem" tabItem}} >
    {{tab-item item=tabItem setSelectedTabItemAction="setSelectedTabItem" }}
  </div>
{{/each}}

<div class="item-content">
  {{selectedTabItem.content}}
</div>

并将tab-switcher类文件( app/components/tab-switcher.js )更改为

export default Ember.Component.extend({
  actions: {
    setSelectedTabItem: function(tabItem){
      this.set('selectedTabItem', tabItem);
    }
  }
});

此时,如果您在浏览器中查看我们的应用程序,它将正常运行。

但是,这种解决方法不能解决一个事实,即动作只会冒泡到组件的类,所以让我们以一种可行的方式来做。 保留app/components/tab-switcher.js的更改,但将app/templates/components/tab-switcher.hbs恢复到先前的状态:

<div class="item-content">
  {{selectedTabItem.content}}
</div>

{{#each tabItems as |tabItem| }}
  {{tab-item item=tabItem setSelectedTabItemAction="setSelectedTabItem" }}
{{/each}}

现在,将tab-item模板更改为:

<span {{action "clicked" item }}>{{item.title}}</span>
{{yield}}

然后将tab-item类文件更改为:

export default Ember.Component.extend({
  actions:{
    clicked: function(tabItem){
      this.sendAction("setSelectedTabItemAction", tabItem);
    }
  }
});

在这里,您可以看到我们添加了一个动作处理程序来处理对tab-item标题的单击。 这会将动作从tab-item组件发送到其父项,即tab-switcher组件。 该动作将层次结构与参数(即我们单击的tabItem 。 这样可以将其设置为父组件上的当前tab-item

请注意,我们正在使用属性setSelectedTabItemAction作为要发送的动作。 这不是实际发送的操作名称,而是属性中包含的值—在本例中为setSelectedTabItem ,它是父组件的处理程序。

结论

至此,我们结束了对Ember组件的介绍。 我希望你喜欢它。 在整个Ember项目中使用可重复使用的组件所带来的生产力收益不容小((实际上在整个项目中也是如此)。 为什么不试试呢? 本教程的源代码可在GitHub找到

您是否已在Ember中使用组件? 到目前为止,您的经历是什么? 希望收到您的评论。

From: https://www.sitepoint.com/understanding-components-in-ember-2/

 类似资料: