js模板字符串自定义类名_Ember.js - 模版篇 自定义Helper (原创翻译)

文末附原文链接 -- 微信公众号首发

Wriring Helpers

Helper 可以为你的模板提供额外的功能。Helper最有用的功能就是帮你做数据的格式化或者是转化等等。

比如说,我们现在有一个 Invoice model,它包含了一个 totalDue 属性,该属性用来代表 invoice 的总金额。并且我们会以美分的形式来存储小数点后面的额金额。

然而,如果我们将 $1.00 显示成 100¢,那么客户可能会不认识这个数字的含义。在这种场景之下,我们就可以通过helper来做数据的格式化。

接下来,我们create一个名叫 format-currency 的helper,用来把美分转换成美元。

同样的,用 {{ }} 来调用它:

Your total is {{format-currency model.totalDue}} .

下面,我们来正式实现这个helper. Helper 是一个接收多个参数,返回一个结果的函数。

通过下面的CLI命令,helper将会被创建在应用的 helpers 目录下:

ember generate helper format-currency

该helper文件将会export一个被 Ember.Helper.helper( ) 封装的函数:

app/helpers/format-currency.js

import { helper } from '@ember/component/helper';

export function formatCurrency([value, ...rest]) {

let dollars = Math.floor(value / 100);

let cents = value % 100;

let sign = '$';

if (cents.toString().length === 1) {

cents = '0' + cents;

}

return `${sign}${dollars}.${cents}`;

}

export default helper(formatCurrency);

在上面例子中, 函数的第一个参数会接收以美分表示的金额数。并且会把美分换算成美元,然后进行字符串拼接再返回到调用helper的地方。

无论你在模板中何时调用它,Ember都会把helper最终的返回结果插入到DOM中。

所以呢,如果你想显示花费总金额,那么你就把钱数传到helper里:

Your total is {{format-currency 250}} .

上面的模板最终的渲染结果是:

Your total is $2.50 .

同样,传入Helper中的变量如果值发生改变,Helper也会将最新的结果更新到页面上。

Helper Names

Helper命名可以只用一个单词,也可以用多个单词。每个单词之间用 " - " 连接即可。

Helper Arguments

Helper可以被传入多个参数:

{{my-helper "hello" "world"}}

当传入多个参数的时候,如果函数的实参只有一个,那么将会以数组的形式来接收多个参数:

app/helpers/my-helper.js

import { helper } from '@ember/component/helper';

export function myHelper(params){

let [arg1, arg2] = params;

console.log(arg1); // => "hello"

console.log(arg2); // => "world"}

export default helper(myHelper);

你也可以通过解构来获取多个参数:

app/helpers/my-helper.js

import { helper } from '@ember/component/helper';

export function myHelper([arg1, arg2]){

console.log(arg1); // => "hello"

console.log(arg2); // => "world"}

export default helper(myHelper);

Named Arguments

一般的,参数用来做数据传入是比较方便的,但是由于一次传入多个参数时,参数的在helper 函数中接收的顺序并不确定。所以我们需要一种方法来解决这个问题。

那就是说,作为开发者我们需要helper的行为可配置。我们重新审视一下之前创建的 format-currency helper,我们再次稍微改造一下这个helper,让它带有一个可配置的货币符号。

Helper会将命名参数作为一个JavaScript对象传递到函数里,该对象包含参数的名称以及它的值。 命名参数不受接收的参数位置的影响。

例子: 我们传一个名为 sign 的参数到 format-currency helper 中:

{{ format-currency 350 sign="£" }}

上面的助手将会输出英镑:£3.50

命名参数被传入函数的时候是作为第二个参数被接收的。下面的代码就是我们改造后的 helper:

app/helpers/format-currency.js

import { helper } from '@ember/component/helper';

export function formatCurrency([value, ...reset], namedArgs) {

let dollars = Math.floor(value / 100);

let cents = value % 100;

let sign = namedArgs.sign === undefined ? '$' : namedArgs.sign;

if (cents.toString( ).length === 1) {

cents = '0' + cents;

}

return `${sign}${dollarts}.${cents}`;

}

export default helper(formatCurrency);

你想传多少命名参数都可以,这些参数都在 namedArgs 里面:

{{my-helper option1="hello" option2="world" }}

app/helpers/my-helper.js

import { helper } from '@ember/component/helper';

export function myHelper (params, namedArgs) {

console.log(namedArgs.option1); // => "hello" console.log(namedArgs.option2); // => "world"}

export default helper(myHelper);

普通参数和命名参数可以同时传入helper。

Class-based Helper

默认的,helper是无状态的。他们接收多个输入,经过一系列操作返回一个输出。它没啥副作用并且它不会保存任何东西。

不过在某些场合,你可能需要helper支持一些交互行为。那么,这时候,你就可以创建基于类的helper了,它可以保存状态和访问service。

相对于之前创建helper的方式,要创建类基的helper,你需要继承 Ember.Helper . 并且必须要包含一个名为 compute 的方法(该方法相当于之前创建helper时定义的函数)。

作为练习,我们来重构一下之前创建的 format-currency helper使它成为一个类基的helper:

app/helpers/format-currency.js

import Helper from '@ember/component/helper';

export default Helper.extend({

compute([value, ...reset], hash) {

let dollars = Math.floor(value / 100);

let cents = value % 100;

let sign = hash.sign === undefined ? '$' : hash.sign;

if (cents.toString( ).length === 1) {

cents = '0' + cents;

}

return `${sign}${dollarts}.${cents}`;

}

});

改造完毕,上面的例子与改造之前的 function 版本目前是等价。

下面,我们将为这个helper注入service:

app/helpers/format-currency.js

import Helper from '@ember/component/helper';

import { inject as service } from '@ember/service';

export default Helper.extend({

authentication: service( ),

compute([value, ...reset], hash) {

let authentication = this.get('authentication');

if (authentication.get('isAuthenticated')) {

return 'Welcome back, ' + authentication.get('username');

} else {

return Not logged in';

}

}

});

Escaping HTML Content

为了抵御跨站脚本攻击(XSS),Ember会把从helper中返回的任何值都转换为安全的字符串。

例子, 现在有个 make-bold helper,它返回的值中带有HTML标签:

app/helpers/make-bold.js

import { helper } from '@ember/component/helper';

export function makeBold([param, ...rest]) {

return `${param}`;

}

export default helper(makeBold);

我们这么调用它:

{{make-bold "Hello world"}}

Ember的转化结果:

<b>Hello world </%gt;

结果就是,helper返回的内容被当作字符串原样输出了。不过我们也可以让Ember不转化返回内容:

app/helpers/make-bold.js

import { helper } from '@ember/component/helper';

import { htmlSafe } from '@ember/string';

export function makeBold([param, ...rest]) {

return htmlSafe(`${param}`);

}

export default helper(makeBold);

如果你返回的是一个 SafeString . 那么Ember就知道你已经确保返回值中没有恶意的代码。

但是请注意,在上面的代码中,我们可能会无意中在应用程序中引入了XSS漏洞! 通过盲目地将字符串标记为安全,恶意用户可以将自己的HTML导入我们的应用程序,从而允许他们执行访问敏感的客户数据等操作。

例如,假设我们有一个聊天应用程序,并使用我们的make-bold助手来欢迎新用户:

Welcome! {{make-bold model.firstName}} has joined the channel..

现在,恶意用户只需要将其firstName设置为包含恶意代码的HTML的字符串(例如,客户的隐私数据通过

为了应对这种行为,Ember提供了 excapeExpression 来防止恶意script注入。

app/helpers/make-bold.js

import Ember from 'ember';

import { helper } from '@ember/component/helper';

import { htmlSafe } from '@ember/string';

export function makeBold([param, ...rest]) {

let value = Ember.Handlerbars.Utils.excapeExpresstion(params);

return htmlSafe(`${param}`);

}

export default helper(makeBold);

现在,被注入的恶意脚本将不会起作用了。

Welcom back! <script type="javascript">alert('pwned!');</script; has joined the channel..Writing Helpers - Templates - Ember Guides​guides.emberjs.comv2-99c60a70bf501182696e660669420aa3_180x120.jpg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值