Ember 中 component 的简略介绍

component in Emberjs

1. 什么是 component

一个封装好的可以重复使用的功能单元.一个形象的比喻就是七巧板里面的每一块都是一个组件,每个组件都可以重复使用,通过调节 板的摆放方式(组件属性) 以及 与其他板的组合方式(父子组件的联动) 来实现不同的拼装样式(组件功能).

2. 解决了什么样的问题

在实际生产工作中,会经常遇到需要展示多个 item 的情况,比如 TMIST 项目中的医院列表、APM 项目中的 区域展示列表。在这样的情况下,我们如果使用一个个书写的方式把他们穷举出来,那需要写的就太多了,根据OAOO(一次且仅一次)的编程原则,我们需要一个这样的解决办法,写一次,来展现医院列表,如果我们提供的灵活性足够,我们可以达到写一次列表组件,展示一类事物的列表。
在 emberjs 中这样的解决思路就是使用 component 。

3. 使用

创建基本组件:

ember g component component-train

可以看到 ember-cli 帮我们生成了两个文件,一个是主管组件展示的template.hbs,另一个是主管组件逻辑的component.js1

组件的生命周期

任何框架的组件都有其生命周期,而每个框架提供的生命周期钩子不尽相同,但是设计思路是相似的:
life cycle
这个部分官方文档提供了一些具体钩子的具体使用范例:点击查看

组件的数据传递

在一个简单的组件中:

	{{!-- component-train-passing-properties/template.hbs --}}
	<h2>{{title}}</h2>

我们可以在 component.js 中为 title 变量赋值,在 handlebars 文件中将会展示出来:

	//	component-train-passing-properties/component.js
	//	...
	this.set('title','welcome to use emberjs');

而在调用组件页面我们将会看到这句话。

passing-properties
但是在实际项目中,我们基本上都是从后端接受数据再通过路由中的handlebars 文件调用组件,将数据传递进去,再进行相应的展示:

	{{!-- train/template.hbs --}}
	{{component-train-passing-properties title="Welcome to use component!"}}

这个时候,在组件的调用页面,我们就可以看到

usecomponent
展示在我们面前了。

自定义组件属性:

  1. 修改包裹体的标签:
    默认的 组件 外部的包裹元素为div,我们可以通过使用 tagName: 'li' 这种语法来修改包裹体的标签;
  2. 向组件添加 类 名:
    有以下几种方法:
    - 在定义的时候通过属性添加: classNames: ['header-title']
    - 在调用的时候通过属性传递: {{component-train-passing-properties class='passing-properties-container'}};
    - 绑定某一属性,动态添加类:
	//	component-train-passing-properties/component.js
	classNameBindings: ["showBg:show-background"]

而后在对应的 styles.scss文件内写上样式,这里是添加背景色。
在调用端:

{{!-- train/template.hbs --}}
<section local-class="defined-class">
	{{component-train-passing-properties title=title showBg=true}}
	{{component-train-passing-properties title=title showBg=false}}
</section>

可以看到:
动态绑定类名
如果classNameBindings 绑定的属性的值是一个字符串,那字符串将直接传递入组件的类中。

事件调用

在 component.js 文件中,我们可以在内部写一些事件处理逻辑:

	actions: {
		changeText(text) {
			this.set('text',text + ' !')
		}
	}

总结

上面就是 emberjs 中 component 的一些基础用法,包含 组件创建/数据传递/动态样式 等。在实际的项目中,我们需要从设计原图开始一步步做,这个时候就需要我们拆分页面,将可复用的部分拆分成一个个组件,然后再通过组件的相互嵌套完成一个个页面的拼装。

4. 拆分组件

这个问题呢,是一个比较偏经验性的问题,比较考验编程人员的抽象能力,这方面我做的就不是很好,但是我刚好从高人那里学到了几招,就在这里班门弄斧一下。

数据结构与组件

拿到设计图之后我们在充分了解了整个项目抑或是单个页面之后,我们需要考虑的是 页面结构,随之而来的一个问题是数据结构,这是不分家的,你期望你的页面数据是如何展示的,你的数据结构就应该辅助你,或者数据结构是这样的,那你的页面结构也应该相应的这么做。在之前杨总告诉我们要开始做的 ERD 图 也可以再设计ERD图的同时思考一下页面的结构。虽不尽相同,但思想一致。

自己的做法

在我们项目前期,我们不可能把一个组件抽离的完美,或者拆分页面结构非常清晰完整。也就是不要过早的过度拆分组件。我们也可以在一个route中将一个页面全写出来,在写的过程中我们就可以根据严谨的 html 结构 以及业务需求来了解到一个组件如何拆分。这样做的前提就是写出来的 html 结构必须清晰。

在拆分的过程中,我们肯定会考虑到组件的复用与灵活性。这个可以考虑使用 yield反出一些数据或可定制的子组件使调用者更加灵活。

是将数组传入组件还是将item传入组件

这是我做组件过程中思考过的一个问题,就是在像 药品列表 这样的样式中。两种数据传入是会产生不同的影响的。

总结

这个拆分组件过程写的比较浅显,更多的需要在项目中不断的思考。

其他 Service

在实际的项目中,我们通常会遇到相同或者相似的处理逻辑,如果每次都在component/controller/route中写一遍,或者靠 ctrl+c/ctrl+v 来完成,那就不符合我们上面提到的OAOO的编程原则。

创建service

ember g service change

ember cli就会自动帮我们生成一个service.js 文件:

import Service from "@ember/service";

export default Service.extend({
	changed(text) {
		return text + " changed!";
	}
});

注入到需要使用到的地方

可以注入到 route/controller/component 中,目前以 component 为例:

import Component from "@ember/component";
import { inject as service } from "@ember/service";

export default Component.extend({
	// 注入方式一
	change: service(),
	// 注入方式二
	mut: service("change"),
});

注入之后的 service 既可以在 js 文件中使用,亦可以在 handlebars 文件中使用。
文档中一些使用 service 的示例为:

  • User/session authentication.
  • Geolocation.
  • WebSockets.
  • Server-sent events or notifications.
  • Server-backed API calls that may not fit Ember Data.
  • Third-party APIs.
  • Logging.

总结

本文写的比较仓促,肯定存在错误,一些高级用法也没有解释的清楚,实际项目中的应用也未能举例说明,在之后的时间里会不断更新。

Written by Frank Wang.

有问题可以下方评论,或发邮件至 法研鲁迅 .


  1. 在使用原生的目录结构时,生成的文件名称可能有所不同;另外 组件的名称也必须有中划线。 ↩︎

猜你喜欢

转载自blog.csdn.net/peng_9/article/details/84332857