Ember.js-模版篇 自定义helper上

Named Arguments

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

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

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

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

{{format-currency350sign="£"}}

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

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

app/helpers/format-currency.js

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

export functionformatCurrency([value, ...reset], namedArgs) {

letdollars = Math.floor(value /100);

letcents = value %100;

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

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

cents ='0'+ cents;

}

return`$$.$`;

}

export defaulthelper(formatCurrency);

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

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

app/helpers/my-helper.js

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

export functionmyHelper(params, namedArgs) {

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

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

}

export defaulthelper(myHelper);

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

Class-based Helper

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

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

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

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

app/helpers/format-currency.js

importHelper from'@ember/component/helper';

export defaultHelper.extend({

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

letdollars = Math.floor(value /100);

letcents = value %100;

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

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

cents ='0'+ cents;

}

return`$$.$`;

}

});

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

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

app/helpers/format-currency.js

importHelperfrom'@ember/component/helper';

import{ injectasservice }from'@ember/service';

export defaultHelper.extend({

authentication: service( ),

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

letauthentication =this.get('authentication');

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

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

}else{

returnNot logged in';

}

}

});

Escaping HTML Content

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

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

app/helpers/make-bold.js

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

export functionmakeBold([param, ...rest]) {

return`$`;

}

export defaulthelper(makeBold);

我们这么调用它:

{{make-bold "Hello world"}}

Ember的转化结果:

Hello world

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

app/helpers/make-bold.js

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

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

export functionmakeBold([param, ...rest]) {

returnhtmlSafe(`$`);

}

export defaulthelper(makeBold);

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

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

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

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

现在,恶意用户只需要将其firstName设置为包含恶意代码的HTML的字符串(例如,客户的隐私数据通过包裹,然后发到server),那么他就可以轻松获得别人的资料了。

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

app/helpers/make-bold.js

importEmberfrom'ember';

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

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

export functionmakeBold([param, ...rest]) {

letvalue = Ember.Handlerbars.Utils.excapeExpresstion(params);

returnhtmlSafe(`$`);

}

export defaulthelper(makeBold);

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

Welcom back! alert('pwned!');</script; has joined the channel..</p><p><strong>每天学习一点点,日积月累也能变大神!</strong></p>

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180612G1UVBT00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励