我应该什么时候在小组件中使用 JavaScript?
小组件包含 JavaScript,可用于执行客户端行为。包括针对 REST API 平台发出 REST 请求,对自定义小组件定义的端点发出 AJAX 请求,通过客户端模板渲染数据,使用平台提供的 JavaScript API,以及提供更丰富的用户体验。
注册 JavaScript
注册 JavaScript 时,请注意:
- 始终使用 #registerEndOfPageHtml 指令注册脚本块(见下文)。
- 如果超过几行,则将 Javascript 放在外部脚本文件中,并使用 $limyee_v1_widget.GetFileUrl('FILENAME')链接到该文件。
- JavaScript 模块应该使用特定于供应商的命名空间来扩展 jQuery。核心小组件的脚本放置在 jQuery.limyee.widgets 命名空间中,该命名空间应根据小组件实例标识符命名。例如,动态流小组件的 JavaScript 位于 $.limyee.widgets.activityStoryStream 中。
- 仅在模块上公开必要的方法。
为了便于注册页面底部的<script></script>块,提供了 #registerEndOfPageHtml 指令。它的语法是:
#registerEndOfPageHtml(uniqueRegistrationKey) // Markup To render at the end of the page. #end
指令中的标记块将在 HTML 页面的末尾呈现。
关于此指令的一些注意事项:
- 在预览模式下,标记将以内联方式呈现,而不是在页面底部呈现。这可确保在编辑页面时将 JavaScript 正确呈现给客户端。
- uniqueRegistrationKey 是可选的。对于应始终注册的脚本(例如:配置小组件当前实例的脚本),可以在不带参数的情况下调用指令。如果指定了参数,则块将仅使用该 Key 呈现一次,即使多个小组件尝试使用相同的 Key 注册 HTML 也是如此。
- 一种常见的模式是当注册包含脚本或外部脚本时使用 uniqueRegistrationKey 参数,但在实例化该脚本的模块时不使用 Key。
注册内联 JavaScript
在小组件的 Velocity 内容中简单地包含内联 JavaScript,如下所示:
#registerEndOfPageHtml() <script> alert("Hello from JavaScript!"); </script> #end
注册 JavaScript 小组件附件
作为包含小组件定义的 JavaScript 文件示例,这是一个名为 myWidget 的小组件脚本,该小组件名为 widget.js 存储在小组件附件中。
(function ($, global, undef) { // 更改命名空间避免客户端代码冲突 $.myNameSpace.myWidget = { register: function(options) { // 使用传递的 options 初始化客户端脚本 } } })(jQuery, window);
然后,可以使用以下内容引用和调用脚本附件:
#registerEndOfPageHtml('myNameSpace.myWidget') <script type="text/javascript" src="$limyee_v1_encoding.HtmlAttributeEncode($limyee_v1_widget.GetFileUrl('widget.js'))"></script> #end #registerEndOfPageHtml() <script type="text/javascript"> jQuery(document).ready(function(){ jQuery.myNameSpace.myWidget.register({ key1: 'value1', key2: 'value2' }); }); </script> #end
请注意:
- 使用 $limyee_v1_widget.GetFileUrl() 获取用于加载小组件定义的 widget.js 附件的 URL。
- 将小组件实例特定的数据传递到脚本定义的 myWidget 模块。
- 通过 #registerEndOfPageHtml() 指令注册时,注册在执行时发生。如果小组件没有呈现(通过不呈现任何内容或通过调用 $limyee_v1_widget.Hide()),重新初始化后,模块在页面末尾的 HTML 仍将呈现。在执行任何页末 HTML 注册之前调用 $limyee_v1_widget.Hide() 非常重要。
访问 REST 接口
Limyee 电商平台包括对 jQuery 的 AJAX API 自定义扩展,以促进与 REST 的交互和对 Limyee 电商平台的回调。
jQuery.limyee.get(options) jQuery.limyee.post(options) jQuery.limyee.put(options) jQuery.limyee.del(options)
这些函数有与 jQuery.ajax() 相同的 API,但有以下优点:
- Limyee 电商平台身份验证令牌会自动加入到请求的头数据。
- data 的项目会自动插入到参数化的端点 URL 中。
- REST API 端点的参数会自动进行 URI 编码
- 多个 REST 请求可以批处理为并行或按顺序统一请求。
作为发出简单 REST GET 请求的示例,以下请求平台的名称并将其显示在警报中。
jQuery.limyee.get({ url: jQuery.limyee.site.getBaseUrl() + 'api/v1/info.json', success: function(response) { alert('Hello from ' + response.InfoResult.SiteName); } });
请注意在 REST URL 之前附加的 getBaseUrl() 的使用。此端点和所有其他端点都在 REST API 文档中定义。
使用这些 REST 函数时,将通过数据参数传递的值(这些值也在提供的 url 中标识)将被替换。在 url 中找不到的任何数据值都将作为查询字符串数据(对于 get 方法)或 POST 数据(对于 post、put 和 del 方法)传递。例如,url 中的 {GroupId} 和 {UserId} 参数将替换为数据参数中定义的值:
jQuery.limyee.del({ url: jQuery.limyee.site.getBaseUrl() + 'api/v1/groups/{GroupId}/members/users/{UserId}.json', data: { GroupId: 5, UserId: 2107 }, success: function(response) { console.log(response); } });
JavaScript REST API 示例
从群组中删除用户
请注意,URL 中的 {GroupId} 和 {UserId} 参数将赋值,data 中的项目将在请求 URL 之前解析该 URL。
jQuery.limyee.del({ url: $.limyee.site.getBaseUrl() + '/api/v1/groups/{GroupId}/members/users/{UserId}.json', data: { GroupId: 5, UserId: 2107 }, success: function(response) { console.log(response); } });
向现有对话添加消息
请注意,在这种情况下,Id 将插入到原始 API 端点中解析为 /api/v1/conversations/50.json,但“Subject”和“Body”仍作为 post 参数传递,而 Id 不会
jQuery.limyee.post({ url: $.limyee.site.getBaseUrl() + '/api/v1/conversations/{Id}.json', data: { Id: 50, Subject: "New Mesage Subject", Body: "New Message Body" }, success: function(response) { console.log(response); } });
请求对话
这是一个更传统的方案,其中 PageSize 和 PageIndex 作为查询字符串参数传递到 URL,这不需要插值。
jQuery.limyee.get({ url: $.limyee.site.getBaseUrl() + '/api/v1/conversations.json', data: { PageSize: 10, PageIndex: 3 }, success: function(response) { console.log(response); } });
REST 批处理
多个 REST 请求可以批处理为单个 HTTP 请求,并行或按顺序执行。这有时可以提供更高效的用户体验优势。
使用REST批处理的最简单方法是使用 jQuery.limyee.batch 函数。batch() 是一个高级包装器,它在HTTP 请求的单个批处理中运行所有包装的 REST 请求。每个 REST 请求仍支持单独的 success/error 回调以及单独的 promise 回调,尽管在批处理完成之前不会执行这些回调。不必将显式批处理 ID 传递给 batch() 调用的 REST 请求。使用此方法创建的批处理不能嵌套。批处理将返回一个 promise,该 promise 在整个批处理完成时解决。
批处理 REST 请求如下所示:
$.limyee.batch(function() { // ordinary REST requests // $.limyee.post({...}) // $.limyee.get({...}) // $.limyee.put({...}) }, options);
默认情况下,批处理并行运行。若要按顺序运行批处理,请传递“sequential: true”数据。顺序批处理包含了失败请求将暂停该批处理中的所有后续请求,并拒绝整个批处理 promise。任何成功的子请求仍会解析。并行请求包含了一个或多个失败请求仍会解析整个批处理,并且不会停止其他子请求。
除了高级 batch() 方法之外,还存在用于定义和使用批处理的较低级别函数,包括:
var batchId = $.limyee.batch.start();
start() 是专门用于创建批处理上下文的较低级别方法。对 get()、post()、put() 和 del() 的调用支持批处理参数,该参数将其执行推迟到运行关联的批处理。批处理上下文在未执行 60 秒后过期。
$.limyee.batch.process(batchId, options);
process() 是一种较低级别的方法,它运行一个批处理 REST 请求,其中包含与该批处理 ID 关联的所有 REST 请求。返回一个 promise,该 promise 在整个批处理完成时解决。支持的选项与传递到 batch() 包装器时的选项相同。
使用更高级别的 $.limyee.batch() 方法通常更简单,除非单个函数作用域中包装所有 REST 请求不可行。
自定义小组件定义的 AJAX 端点
只要有可能,当小组件需要 AJAX 功能时,应首选 REST API。但是,在某些情况下,需要自定义 AJAX 端点,包括:
- 复杂且昂贵的自定义格式,可以在服务器端 AJAX 处理程序上更轻松地实现,而不是通过客户端将多个(甚至是批处理的)REST API 调用和模板化的结果拼凑在一起。
- 当 REST API 未公开平台 API,无法使用脚本扩展调用该 API。
小组件支持以 Velocity 脚本形式调用自定义的 AJAX 端点,该端点可以使用特殊的 URL 格式被小组件引用,并在请求时执行链接的文件。
小组件定义端点是在平台中定制自定义处理程序的方法之一,包括自定义 REST 端点和自定义 HTTP 处理程序。当单个小组件仅需要数据时,小组件端点为最佳。HTTP 处理程序插件最适合插件的客户端行为,但不能公开访问。REST 插件最适合与平台定义的 REST 端点一起公开使用。
自定义小组件终端节点 API:
自定义端点需要使用 $limyee_v1_widget.GetExecutedFileUrl()
$limyee_v1_widget.GetExecutedFileUrl('script.vm')
GetExecutedFileUrl 返回一个 URL,当请求该 URL 时,该 URL 将执行其参数命名的 velocity 脚本。执行结果将以 HTTP 请求的响应返回。该脚本将有与调用小组件相同的上下文。
自定义小组件终端节点示例:
通过 GET 调用自定义 AJAX 端点并返回 HTML 片段
下面的示例返回给定用户的最新状态更新 HTML 格式片段。
假设有一个名为 lateststatus.vm 的小组件附件,其 velocity 脚本如下:
#set ($userId = $limyee_v1_page.GetQueryStringValue('w_userId')) #set($messages = $limyee_v1_statusMessage.List("%{ UserId = $userId, PageSize = 1 }")) #foreach($message in $messages) <span class="status-message">$message.Body</span> <span class="status-date">$limyee_v1_language.FormatAgoDate($message.CreatedDate)</span> #end
可以调用自定义端点的客户端脚本。请注意使用 GetExecutedFileUrl 以及参数前缀“w_”,避免与传递给端点的其他查询字符串参数发生冲突。
jQuery.limyee.get({ url: '$limyee_v1_encoding.JavascriptEncode($limyee_v1_widget.GetExecutedFileUrl('lateststatus.vm'))', data: { w_userId: 1234 }, success: function(response){ // 将响应添加到页面 jQuery('#element').html(response); } });
通过 POST 调用自定义 AJAX 端点并返回 JSON
自定义 AJAX 端点还可以返回 JSON,当 API 只向 Velocity 公开,无法使用 REST 调用时,这可能是一种有用的模式,例如:使用 Velocity 方法调用自定义扩展或自定义响应,生成单个、经过处理的统一数据响应。
以下示例是使用 JavaScript 调用 Velocity 扩展的自定义小组件端点并返回 JSON。 让我们考虑使用 $limyee_v1_language.Truncate()。让我们考虑一个小组件要通过 JavaScript 来使用它。
假设有一个名为 truncate.vm 的小组件附件,
#if ($limyee_v1_page.IsPost) #set($text = $limyee_v1_page.GetFormValue('w_text')) #set($length = $limyee_v1_utility.ParseInt($limyee_v1_page.GetFormValue('w_length'))) #set($truncatedText = $limyee_v1_language.Truncate($text, $length)) $limyee_v1_page.SetContentType('application/json') { "truncated": "$limyee_v1_encoding.JavascriptEncode($truncatedText)" } #end
客户端脚本可以调用自定义端点。注意使用 GetExecutedFileUrl
jQuery.limyee.post({ url: '$limyee_v1_encoding.JavascriptEncode($limyee_v1_widget.GetExecutedFileUrl('truncate.vm'))', data: { w_text: 'Test Text To Truncate' id: 6, }, dataType: 'json', success: function(response){ alert('Truncated response: ' + response.truncated); } });