Aurelia中的HTML行为介绍


Aurelia模板引擎的自定义属性和自定义元素功能的概述,不仅包括如何创建基本版本,还包括如何在您的应用程序中本地和全局使用它们。


介绍


       Aurelia中的术语“HTML行为”包含两个基本概念:自定义元素和自定义属性。HTML行为几乎是每个Aurelia应用程序的基本组成部分。他们用高度可重用的代码去帮助创建组件化的应用程序。在这个介绍性文档中,我们将探讨一些基本的主题,以帮助您在Aurelia应用程序中理解使用这些概念。


什么是HTML行为


       HTML行为是如何在Aurelia用程序中使用自定义元素和自定义属性扩展HTML。自定义元素:顾名思义,是你的标记的元素。他们通常会有一些标记,这些标记将作为应用程序页面的一部分呈现。另一方面,“自定义属性”可用于在标准HTML元素中(如div或button)或“自定义元素”中以更改元素的行为。自定义元素和自定义属性都支持Aurelia强大的数据绑定。


除了一个例外,HTML行为要求您为行为创建一个类。这个类对于自定义元素和自定义属性都被称为“视图模型”。自定义元素的视图模型通常与HTML“View”配对。自定义属性的视图模型不与视图配对。Aurelia为类提供了一个命名约定,允许您告诉框架某个类是自定义元素或自定义属性的视图模型。这个命名约定非常简单:在你的视图模型的名称后追加CustomElement或CustomAttribute。这真的很简单。

 

把自定义元素设为默认值

其实,你甚至不需要附加CustomElement到一个类来把它变成一个自定义的元素。其原因是,如果Aurelia不能匹配任何其他约定,并且找不到任何明确的配置,那么将认为该类是一个自定义元素。

 

如果你正对你的HTML行为的类使用命名约定,则Aurelia将使用该类的名称来确定您的行为在HTML视图中的名称。JavaScript类的标准命名约定是InitCaps,意思是每个字母首字母大写; 然而,HTML是不区分大小写的,通常归一化为小写。为了缩小这个差距,Aurelia将采取类名称,去掉它CustomElement或CustomAttribute后缀,然后将类名转换为dash-case。这意味着,当你在模板中使用它时,HelloWorldCustomElement要变为hello-world和RedSquareCustomAttribute要变为red-square。


您可以覆盖的命名约定,并通过在你的HTML行为的视图模型中使用@customAttribute或@customElement装饰器来明确命名你的HTML行为。你传递一个字符串到装饰器,这成为你的行为将使用的名称。Aurelia不会以任何方式改变这个字符串。这意味着@customElement('helloworld')会给你一个名为<helloworld>的自定义元素。这两个装饰器可以从aurelia-framework模块导入。在使用这些装饰器之一时,不需要遵循上面提到的命名约定,因为装饰器的使用告诉Aurelia您正在创建自定义元素或自定义属性。事实上,当你使用这些装饰器时,你的类名对Aurelia来说并不重要!我们来看一个使用@customAttribute 修饰器来明确地命名自定义属性的例子。


1.  //red-square.js  

2.   

3. import {customAttribute} from 'aurelia-framework';  

4.    

5. @customAttribute('red-square')  

6.  export class BlueSquare {  

7. }  


如你所见,即使这个类是被命名BlueSquare,这个自定义属性的名字也是red-square。你显然不希望在实际代码中给出这样的矛盾名称,但是在这写的目的是为了显示当你在使用装饰器明确命名行为时,类名并不重要。

命名实践

通常建议定制自定义元素和自定义属性,这样HTML行为在其名称中便带有连字符。使用hello-world ,而不是helloworld。虽然Aurelia或浏览器中的任何内容都无法阻止您,但为了与Web组件进行前向兼容,我们建议您始终使用带连字符的名称。通常的做法是采用双字母前缀,并将其用于整个公司或应用程序。

 

获取行为中的DOM元素


在创建HTML行为时,会出现很多情况,您需要对与您的行为相关的DOM元素进行一些操作。最初,你可能会想,“没什么大不了的,我只需用document.querySelector或jQuery来获取DOM元素。” 但是这会很快分崩离析,因为HTML行为可能会在页面上反复使用。你将如何确切地查询哪个元素?好在,幸运的是,Aurelia为您提供了一个非常简单的方法来获取您的行为与之相关联的元素的引用:只需将它注入到您的ViewModel(视图模型)中。


当您告诉Aurelia将Element类的实例注入到您的类中时,Aurelia将注入与您的HTML行为关联的DOM元素。所以没有必要与DOM查询争执!让我们来把我们的red-square属性,将其设置为红色的方块。只需将传入的对象分配给类中的属性,这样就可以了。


1.  //red-square.js  

2. //ES Next  

3.    

4. import {inject} from 'aurelia-framework';  

5.    

6.     @inject(Element)  

7.      export class RedSquareCustomAttribute {  

8.       constructor(element){  

9.          this.element = element;  

10.  

11.         this.element.style.width = this.element.style.height = '100px';  

12.        this.element.backgroundColor = 'red';  

13.       }  

14.    }  


记住,你不需要jQuery来获取HTML行为所附带的元素。Aurelia可以提供给你!

 

尽量避免浏览器全局

在上面的例子中,我们使用了浏览器全局:Element。有时使用浏览器全局可能会导致测试问题。情况并非如此。但是,如果您希望利用服务器端渲染,则需要使代码库免受浏览器全局性影响。你可能要提前做好准备。为了帮助您避免浏览器全局,Aurelia提供了一个平台抽象层(PAL),其提供了三个出口DOM,FEATURE和PLATFORM。在上述情况下,你可以用DOM.Element代替Element。

 

在试图中使HTML行为可用


到目前为止,我们只讨论了创建HTML行为,但是如果您不能使用它,创建一个行为并不是很有用。那么你如何使用它呢?那么,首先我们必须在视图中提供它。HTML行为(和其他视图资源)默认情况下是全局不可用。这意味着您必须让Aurelia知道在每个视图中可用的资源。这是使用require元素完成的。该require元素有两个属性from和as。您必须为该from属性提供一个值,但是as是可选的。您不能在require上使用数据绑定from或as属性。当“需要”一个视图资源与require元素,Aurelia将使其可用于你的视图。


1.  //Require an External Resource  

2. //HTML  

3.    

4. <template>  

5.     <require from="my-custom-element"></require>  

6.   

7.     <my-custom-element></my-custom-element>  

8. </template>  


您在from属性中提供的路径可以采用以下两种形式之一:它可以相对于应用程序的根或相对于当前视图的路径。没有./或../启动路径的路径将是相对于你的应用程序的根,而一个路径./或../将是相对于你的视图的路径。请注意,您可以..根据需要使用多个..s遍历所需的目录树。


1.  //外部资源的相对路径  

2. //HTML  

3.    

4. <template>  

5.     <require from="./my-custom-element-one"></require>  

6.    <require from="../another-dir/my-custom-attribute"></require>  

7.    

8.    <my-custom-element-one></my-custom-element-one>  

9.     <div my-custom-attribute></div>  

10.</template>  


资源在您的视图中所采用的名称可以通过以下三种方式之一来确定:1.按照Aurelia惯例,2.通过资源中的明确命名,3.使用as属性覆盖。如果碰巧使用具有相同名称的多个资源,则必须用as属性为所有冲突资源提供一个值。只要您想要为资源起个别名,也可以使用该属性。也许HTML行为的标准名称很长,你想给它一个简短的名字。该as属性可以帮助你。


1.  //覆盖资源名称  

2. //HTML  

3.    

4. <template>  

5.    <require from="my-custom-element-one"></require>  

6.   <require from="../another-dir/my-custom-element-one" as="override-the-name"></require>  

7.    

8.   <my-custom-element-one></my-custom-element-one>  

9.    <override-the-name></override-the-name>  

10.</template>  


你通常不需要为from属性添加文件扩展名。这有多个原因。首先,开发环境中文件的文件扩展名可能与浏览器运行的文件扩展名不同(例如.ts使用TypeScript时的文件)。其次,大多数(但不是全部)自定义元素都需要Aurelia同时引入javascript 视图模型和HTML 视图。Aurelia的加载器将决定哪个文件扩展名需要附加到您提供的文件名。这个规则有一个例外,但是,Aurelia提供了“纯HTML的自定义元素”。您必须通过在from属性提供.html扩展名来告诉Aurelia您正在使用一个只有HTML的自定义元素。这是Aurelia开发者常见的混淆之处,所以记住这个细微差别对于使用这个require元素来说非常重要!


1.  //带有外部资源的示例模板  

2. //HTML  

3.    

4. <template>  

5.    <require from="my-custom-element"></require>  

6.   <require from="./my-html-only-custom-element.html"></require>  

7.    

8.   <my-custom-element></my-custom-element>  

9.    <my-html-only-custom-element></my-html-only-custom-element>  

10.</template>  


需求启示

Aurelia的require元素受到了ES 2015中的import声明的启发。与现代JavaScript具有包含导入的模块相同,Aurelia的视图也是模块化的,并且可以包含我们通过require完成的导入。你可能想知道为什么我们没有命名我们的import元素,而是用的require。那些一直使用Aurelia的人可能会记得,最初的名字实际上是“import”。该名称现已更改,以便与旧版本的Internet Explorer兼容,后者不喜欢使用import。

 

全局资源


开发Aurelia应用程序时,您可能会拥有在多个视图中使用的某些资源。在这些情况下,在您的应用程序中全面使用这些资源可能是明智的。幸运的是,Aurelia以简单的方式为您提供这个功能。这通常是在应用程序启动时在您的main.js文件(或任何您称为您的应用程序启动文件)中完成的。FrameworkConfiguration类提供的globalResources,把一个或多个的资源路径的字符串作为参数。全球化资源不需要被模板所要求。


用来配置Aurelia的文件将有一个configure方法。Aurelia会调用这个方法,并将Aurelia类的一个实例传递给它。这个类通过它的use属性为访问FrameworkConfiguration对象提供了一个流畅的接口。FrameworkConfiguration对象上的方法返回FrameworkConfiguration对象,使您可以将多个调用链接在一起,如下所示。


1.  //main.js  

2. //ES Next  

3.    

4. export function configure(aurelia) {  

5.    aurelia.use  

6.     .standardConfiguration()  

7.      .developmentLogging()  

8.     .globalResources('custom-element`, 'another-directory/custom-attribute');  

9.    

10.  aurelia.start().then(() => aurelia.setRoot());  

11. }  


请注意,有关文件扩展名的相同规则(仅适用于只有HTML的自定义元素)适用于传递给globalResources的路径。您可以全球化使用该require元素的任何内容,包括自定义元素,纯HTML自定义元素,自定义属性,值转换器和绑定行为。

 

在HTML行为中创建可绑定属性


就像你现在可能知道的那样,Aurelia的关键特性之一就是强大的数据绑定系统,我相信你很想知道如何在你的HTML行为上创建可绑定的属性。好,你走运了,因为我们现在准备讨论@bindable装饰器。最后一件事是:这部分是创建可绑定属性的一个非常基本的介绍,并没有充分地探讨这个话题。有关完整的解释,我们鼓励您查看自定义元素和自定义属性文档。


该@bindable装饰可以从aurelia-framework模块中导入。当你把@bindable装饰器用在您的视图模型的一个属性上时,Aurelia将允许您使用Aurelia提供的所有绑定命令(bind,two-way,one-way,one-time,等)来绑定到该属性。我们来看一个自定义元素的简单例子。


1.  //greet-customer.js  

2. //ES Next  

3.    

4. import {bindable} from 'aurelia-framework';  

5.    

6. export class GreetCustomerCustomElement {  

7.    @bindable customerName = '';

8. }

 

1.  //greet-customer.html  

2. //HTML  

3.    

4. <template>  

5.    Welcome to Pizza Planet, ${customerName}!  

6. </template>  

 

1.  //绑定到自定义元素  

2. //HTML  

3.    

4. <template>  

5.    <require from="./greet-customer"></require>  

6.   

7.    <greet-customer customer-name.bind="name"></greet-customer>  

8. </template>  


该页面的name属性将被绑定到greet-customer自定义元素的customerName属性。请注意,前面提到的将JavaScript名称转换为破折号的惯例适用于可绑定属性名称。当他们在HTML作为属性出现时,他们会被从驼峰形式转换为dash-case形式。


默认情况下,可绑定属性只允许one-way(单向)数据绑定。这意味着数据会流进HTML行为,而不是从自定义元素流出。幸运的是,这可以被覆盖,或者通过将一个配置对象传递给@bindable装饰器,使用一个名为defaultBindingModeset 的属性设置为bindingMode枚举值之一。此枚举位于在aurelia-framework模块,其有三个值:oneWay,twoWay,和oneTime。以下是如何为属性设置默认绑定模式为two-way的简单示例:


1.  //greet-customer.js  

2. //ES Next  

3.    

4. import {bindable, bindingMode} from 'aurelia-framework';  

5.    

6. export class GreetCustomerCustomElement {  

7.    @bindable({ defaultBindingMode: bindingMode.twoWay }) customerName = '';  

8. }  


自定义属性的绑定相比自定义元素稍有一点差别,因为自定义属性支持三种类型的绑定:单值,选项绑定和动态选项绑定。在这个文档中,我们只会看单个值绑定。有关如何实现和使用所有三种类型的绑定的示例,请查看“自定义属性”文档。


在使用自定义属性进行单一值绑定时,@bindable装饰器不会被绑定,因为所有属性默认都有一个value属性。这是由Aurelia确保的。相反,我们实现了一个由Aurelia调用 的valueChanged的回调函数,以提醒我们自定义属性的绑定值已更改。Aurelia会将该值设置为自定义属性的视图模型的value属性,并将两个参数传递给valueChanged回调:新值和旧值。我们来看一个例子。


1.  //square.js  

2. //ES Next  

3.    

4. import {inject} from 'aurelia-framework';  

5.    

6. @inject(Element)  

7.  export class SquareCustomAttribute {  

8.   constructor(element){  

9.      this.element = element;  

10.    this.element.style.width = this.element.style.height = '100px';  

11.   }  

12.  

13.   valueChanged(newValue, oldValue){  

14.    this.element.style.backgroundColor = newValue;  

15.   }  

16.

 

1.  //简单的属性值绑定  

2. //HTML  

3.    

4. <template>  

5.    <require from="./square"></require>  

6.   

7.    <div square.bind="color"></div>  

8. </template>  


只要绑定值发生变化,Aurelia就会调用valueChanged回调函数。这使属性有机会改变元素的背景颜色。在这个例子中,我们甚至不需要使用Aurelia为我们设定的value属性。


HTML行为的继承


对于想要利用继承的开发人员,可绑定属性只能通过自定义元素(不是自定义属性)的类层次结构继承。


在下面的例子中,我们创建了一个通用图标按钮组件,icon-button,并且集成font-awesome。

1.  //icon-button.js  

2. //ES Next  

3.    

4. import {bindable} from 'aurelia-templating';  

5.    

6. export class IconButton{  

7.    @bindable icon = 'ban';  

8.   

9.    onClick(){  

10.    alert("Default method");  

11.   }  

12.}  

 

1.  //icon-button.html  

2. //HTML  

3.    

4. <template>  

5.    <button click.delegate="onClick">  

6.     <i class="fa fa-${icon}"></i>  

7.    </button>  

8. </template>  


下一个组件继承了通用按钮,设置其默认图标以及不同的onClick行为

 

1.  //add-button.js  

2. //ES Next  

3.    

4. import {useView, customElement} from 'aurelia-templating';  

5.  import {IconButton} from './icon-button';  

6.   

7.  @useView('./icon-button.html')  

8. @customElement()  

9.  export class AddButton extends IconButton {  

10.  constructor(){  

11.     super();  

12.    this.icon = 'plus';  

13.     this.onClick = this.add;  

14.  }  

15.   

16.  add(){  

17.     alert('Base add button');  

18.  }  

19. }  


首先,要注意的是,在上面的例子中,我们声明` @ useview('./icon-button.html')`使用相同的视图作为基类。如果我们没有提供这一点,框架将寻找`./add-button.html`。其次,注意我们明确宣布`@customElement()`。*任何时候你继承一个自定义元素,必须添加`customElement`装饰器。*这里展示这些组件将如何被用于在一个视图:

 

1.  //view.html  

2. //HTML  

3.    

4. <template>  

5.    <require from="./icon-button"></require>  

6.   <require from="./add-button"></require>  

7.    

8.   <icon-button></icon-button>  

9.    <icon-button icon="cogs"></icon-button>  

10.  

11.   <add-button></add-button>  

12.  <add-button icon="plus-square-o"></add-button>  

13. </template>  


只有HTML的自定义元素


早些时候,我们说规则的一个例外是所有的HTML行为都必须有一个JavaScript类来充当ViewModel(视图模型),但是我们从来没有解释过这个例外。这个例外就是纯HTML自定义元素。Aurelia为您提供了创建自定义元素而无需创建ViewModel类的功能。对于那些需要将某些东西封装到自己的自定义元素中的情况,这是非常好的,但是无论你封装什么东西都不需要任何复杂的逻辑,也不需要像数据服务那样的依赖。


创建一个只有HTML的自定义元素就像创建一个HTML视图文件一样简单,然后用.html扩展名将它请求到您的视图中,如上面“在视图中创建HTML行为”部分所述。您甚至可以在您的仅HTML自定义元素上具有可绑定属性。这些属性默认为one-way数据绑定,但不能更改默认值,尽管在绑定到自定义元素时仍然可以自由明确的设置绑定方向。要创建可绑定的属性,只需提供一个逗号分隔的属性名称列表到template元素的bindable属性上,如下所示。


1.  //hello-world.html  

2. //HTML  

3.    

4. <template bindable="firstName, lastName">  

5.     Hello, ${firstName} ${lastName}!  

6. </template>  

 

1.  //app.html  

2. //HTML  

3.    

4. <template>  

5.    <require from="./hello-world.html"></require>  

6.   

7.    <hello-world first-name.bind="firstName" last-name.two-way="lastName"></hello-world>  

8. </template

 

HTML行为生命周期


所有HTML行为都有一个定义好的生命周期。使用这个生命周期,您可以点击并触发代码以在适当的时候运行。以下是标准生命周期回调列表:


constructor(): - 视图模型的构造函数被首先调用。


created(owningView: View, myView: View):- 如果视图模型实现了created回调,那么接下来会调用它。如果你的行为是一个自定义的元素,它的视图也被创建,并且视图模型和视图都连接到它们的控制器。被创建的回调将接收“owningView”的实例。这是组件在内部声明的视图。如果组件本身有一个视图,将被第二个参数传递。


bind(bindingContext: Object, overrideContext:Object) - 数据绑定是在视图和视图模型上被激活。如果视图模型有一个bind回调,这个时候就会被调用。绑定组件的“绑定内容”作为第一个参数被传递,“重写内容”是被传递的第二个参数。重写内容包含用于遍历父层次结构的信息,也可用于添加组件要添加的任何上下文属性。值得注意的是,当视图模型完成了bind回调时,数据绑定框架将不会为视图模型的可绑定属性调用已更改的处理程序,直到更新这些属性的“下一个”时间。如果您需要对可绑定属性执行特定的后处理,那么在执行bind 回调时,你应该在回调自身内手动执行。


attached() - 接下来,该组件被附加到DOM(在文档中)。如果视图模型有一个attached回调,这个时候就会被调用。


detached() - 在将来的某个时候,组件可能会从DOM中删除。如果/当发生这种情况,并且如果视图模型有一个detached回调,则它将被调用。


unbind() - 组件分离后,通常会解除绑定。如果你的视图模型有unbind回调,它将在这个过程中被调用。


使用生命周期事件就像在行为视图模型类中实现上面的任何方法一样简单。下面是自定义属性使用附加(attached)和分离(detached)回调方法,和封装jQuery插件时常见事项的一个示例:


1.  //some-plugin.js  

2. //ES Next  

3.    

4. import {inject} from 'aurelia-framework';  

5.    

6. @inject(Element)  

7.  export class SomePlugginCustomAttribute {  

8.   constructor(element){  

9.      this.element = element;  

10.  }  

11.   

12.  attached() {  

13.     this.plugin = jQuery(this.element).somePlugin();  

14.  }  

15.   

16.  detached() {  

17.     this.plugin.destroy();  

18.  }  

19. }  

结论


如果你已经做到这一点,你应该有创建HTML行为的基础知识。Aurelia中的HTML行为可以是自定义元素或自定义属性。这两个都有ViewModels(视图模型),而只有Custom Elements可以有Views。您不需要使用jQuery或document.querySelector获取与您的行为相关联的DOM元素,因为您可以简单地将Aurelia注入到ViewModel中。您必须确保您使用的模板可以访问HTML行为,方法是使用该require元素或使行为成为全局资源。在执行这些操作之一时,除非指定纯HTML的自定义元素,否则不要在路径中为行为提供文件扩展名。


您可以使用@bindable装饰器为自定义元素创建可绑定属性,而如果您正在对自定义属性执行单值绑定,则Aurelia将在您的CustomAttribute的ViewModel上调用valueChanged回调方法。最后,如果您在template元素的bindable属性中指定它们,只有纯HTML的自定义元素可以具有可绑定的属性。


现在您已经有了一个坚实的基础,我们鼓励您阅读关于自定义元素和自定义属性的更高级和深入的文档!编码快乐!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值