Lightning框架示例 - 动态建立Lightning组件
动态建立Lightning组件
组件化前端开发是Lightning框架的优点之一。在进行Lightning应用开发时,我们可以将组件进行嵌套、引用,从而实现模块的封装和重用,提高开发效率。
组件的嵌套和引用最常用的方法是在Lightning组件中直接使用组件标签,比如:
<aura:component controller="ExampleController">
<c:ExampleChildComponent />
</aura:component>
在这段代码中,正在进行开发的Lightning组件中静态地引用了“ExampleChildComponent”组件。
另一种方法就是在控制器或辅助函数的Javascript代码中动态建立组件,主要使用“$A.createComponent()”函数(官方文档)。
本文将通过一个实例来阐述如何动态建立组件。
示例目标
本示例的目标是实现一个类似于Salesforce标准列表视图的应用,可以显示一个电话为“1234567890”的“客户”对象的列表,并可以更改它们的名字。
示例将包含以下几个部分:
- Lightning应用
- 列表组件,用于显示“客户”对象的列表
- 更新组件,在运行时动态建立,包括一个文本框和提交按钮,接收用户的输入并将输入的值更新到“客户”对象的“名字”字段中
- Lightning事件,用于在组件中传递数据
建立Lightning组件的Apex控制器
建立一个Apex类,取名为“AccountListViewController”,作为即将建立的Lightning组件的控制器。在这个Apex类中我们将编写“客户”对象相关的函数,包括了查找“客户”对象和更新“客户”对象。
为了演示简单起见,我们略去异常处理以及单元测试等代码。
代码如下:
public class AccountListViewController {
@AuraEnabled
public static String loadAccounts() {
List<Account> accountList = [SELECT Id, Name, AccountNumber, Phone, Website FROM Account WHERE Phone = '1234567890'];
return JSON.serialize(accountList);
}
@AuraEnabled
public static String updateAccount(String jsonString) {
Account acc = (Account)JSON.deserialize(jsonString, Account.class);
update acc;
return 'Success';
}
}
建立更新事件
为了在两个组件中传递数据(列表组件、更新组件),需要建立一个Lightning事件,取名为“accountListViewEvt”,其中包含了“客户”对象的ID和名字两个属性。
代码如下:
<aura:event type="COMPONENT">
<aura:attribute name="accountId" type="String" />
<aura:attribute name="accountName" type="String" />
</aura:event>
建立更新组件
建立一个新的Lightning组件,命名为“AccountNameUpdateCmp”,用于接收用户的输入,其中包含:
- 两个属性:“客户”的ID和名字
- 输入框,用于让用户输入“客户”名字
- 提交按钮,用于调用更新的函数
- 事件注册,用于调用刚才建立的更新事件,传递数据
组件外观代码如下:
<aura:component >
<aura:attribute name="accountId" type="String" access="public" />
<aura:attribute name="accountName" type="String" access="public" />
<aura:registerEvent name="accountListViewEvt" type="c:accountListViewEvt" />
<div class="slds-form slds-form_horizontal">
<div class="slds-form-element">
<label class="slds-form-element__label">名字</label>
<div class="slds-form-element__control">
<lightning:input value="{!v.accountName}" />
</div>
</div>
<div class="slds-form-element">
<div class="slds-form-element__control">
<lightning:button variant="brand" label="Submit" onclick="{!c.submit}" />
</div>
</div>
</div>
</aura:component>
组件控制器代码如下:
({
submit : function(component, event, helper) {
var cmpEvent = component.getEvent("accountListViewEvt");
cmpEvent.setParams({
'accountId': component.get('v.accountId'),
'accountName': component.get('v.accountName'),
});
cmpEvent.fire();
},
})
从上面可以看出:
- 此组件没有相关联的Apex控制器,只负责接收用户输入的值,作为“客户”对象的名字
- 当用户点击提交按钮后,在控制器中使用“component.getEvent()”函数启用更新事件,并用“fire()”函数将用户的输入发送出去。
接下来要建立的列表组件将动态创建此组件,并在此组件执行结束后接收用户的输入(通过更新事件发送的值)。
建立列表组件
建立一个Lightning组件,取名为“AccountListViewCmp”,并在其中建立:
- 一个列表类型的属性,用于存储要显示的“客户”对象
- 一个表格,用于显示“客户”对象的内容
- 一个初始化函数,用于读取“客户”对象
- 一个创建更新组件的函数,动态建立更新组件
- 一个事件处理函数,用于在更新组件提交后接收用户的输入,并通过Apex控制器更新“客户”对象的名字
组件外观的代码如下:
<aura:component controller="AccountListViewController">
<!-- 将需要动态建立的组件作为依赖注册在此 -->
<aura:dependency resource="c:AccountNameUpdateCmp" />
<!-- Aura.Component[] 类型的属性用于保存动态建立的组件 -->
<aura:attribute name="updateWidget" type="Aura.Component[]" access="public" />
<aura:attribute name="accountList" type="Object[]" access="public" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<!-- 在更新事件启动之后,接收事件传递的值,并更新“客户”对象 -->
<aura:handler name="accountListViewEvt" event="c:accountListViewEvt" action="{!c.handleUpdate}"/>
<!-- 这个部分默认是隐藏的,其中包括了变量“updateWidget”,所以更新组件建立后将被显示在此 -->
<div>
<section role="dialog" tabindex="-1" aria-modal="true" class="slds-modal" aura:id="modalBody">
<div class="slds-modal__container">
<div class="slds-modal__content slds-p-around_medium">
{!v.updateWidget}
</div>
</div>
</section>
<div class="slds-backdrop" aura:id="modalBackdrop"></div>
</div>
<!-- 列表的外观,用于显示“客户”对象 -->
<table class="slds-table slds-table_bordered">
<thead>
<tr class="slds-text-title">
<th scope="col">
<div class="slds-truncate" title="客户名">客户名</div>
</th>
<th scope="col">
<div class="slds-truncate" title="电话">电话</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.accountList}" var="acc">
<tr>
<td>
<div class="slds-truncate">
<a class="slds-th__action" href="javascript:void(0);" role="button"
onclick="{!c.startUpdate}" data-account-id="{!acc.Id}" data-account-name="{!acc.Name}">
{!acc.Name}
</a>
</div>
</td>
<td>
<div class="slds-truncate">
{!acc.Phone}
</div>
</td>
</tr>
</aura:iteration>
</tbody>
</table>
</aura:component>
组件的控制器代码如下:
({
doInit : function(component, event, helper) {
helper.loadAccountList(component, helper);
},
startUpdate : function(component, event, helper) {
var accountId = event.currentTarget.dataset.accountId;
var accountName = event.currentTarget.dataset.accountName;
// 动态建立更新组件,并将“客户”的ID和当前的“名字”的值传递到更新组件中
$A.createComponent(
"c:AccountNameUpdateCmp",
{
"accountId": accountId,
"accountName": accountName
},
function(newComponent, status, errorMessage){
if (status === "SUCCESS") {
component.set('v.updateWidget', newComponent);
var modalBody = component.find('modalBody');
var modalBackdrop = component.find('modalBackdrop');
$A.util.addClass(modalBody,'slds-fade-in-open');
$A.util.addClass(modalBackdrop,'slds-backdrop--open');
}
}
);
},
handleUpdate : function(component, event, helper) {
// 在更新事件结束后,得到其中包含的值,即“客户”对象的ID和用户输入作为对象新名字的值
var updateInfo = {
Id: event.getParam('accountId'),
Name: event.getParam('accountName')
};
// 调用Apex控制器的代码进行更新
var action = component.get('c.updateAccount');
action.setParams({
jsonString: JSON.stringify(updateInfo)
});
action.setCallback(this, function(response) {
var result = response.getReturnValue();
if (result == 'Success') {
helper.loadAccountList(component, helper);
}
});
$A.enqueueAction(action);
var modalBody = component.find('modalBody');
var modalBackdrop = component.find('modalBackdrop');
$A.util.removeClass(modalBody,'slds-fade-in-open');
$A.util.removeClass(modalBackdrop,'slds-backdrop--open');
},
})
辅助函数代码如下:
({
loadAccountList : function(component, helper) {
var action = component.get('c.loadAccounts');
action.setCallback(this, function(response) {
var result = response.getReturnValue();
var accountList = JSON.parse(result);
component.set('v.accountList', accountList);
});
$A.enqueueAction(action);
},
})
建立Lightning应用
建立一个Lightning应用,取名为“AccountListViewApp”,包含了刚才的列表组件。代码如下:
<aura:application extends="force:slds">
<c:AccountListViewCmp />
</aura:application>
小结
动态建立组件可以实现组件的灵活复用。
比如上面示例中的更新组件,我们可以再增加几个属性,扩展为通用的文本更新组件。它没有相关联的Apex控制器,没有很多逻辑,只负责接收和发送文本框中的数据(相关的逻辑由调用此组件的代码来处理)。
当然,动态建立的组件本身也可以包括Apex控制器和相关的逻辑,但是这样会增加和服务器端的通讯次数。为了保证运行效率,我们最好让它们只负责客户端的操作。
Salesforce对于动态建立的组件有垃圾回收机制,这只限于组件被创建后赋值给了“Aura.Component[]”类型的属性。当此组件不再被使用时,会被自动清除。
对于更新“客户”对象的“名字”功能,上面的示例有些过度设计了。但是在实际应用中,可以对和该示例类似的结构进行扩展,用于更复杂的场景,比如对于外部数据的CRUD操作(CRUD操作需要通过网络服务使用,Salesforce的默认功能可能无法使用)。
Lightning框架示例 - 动态建立Lightning组件的更多相关文章
- salesforce lightning零基础学习(一) lightning简单介绍以及org开启lightning
lightning对于开发salesforce人员来说并不陌生,即使没有做过lightning开发,这个名字肯定也是耳熟能详.原来的博客基本都是基于classic基于配置以及开发,后期博客会以ligh ...
- 使用form-create动态生成vue组件
使用form-create动态生成vue自定义组件和嵌套表单组件 [github] | [说明文档] 示例 let rule = [ { type:'row', children:[ { type:' ...
- salesforce lightning零基础学习(二) lightning 知识简单介绍----lightning事件驱动模型
看此篇博客前或者后,看一下trailhead可以加深印象以及理解的更好:https://trailhead.salesforce.com/modules/lex_dev_lc_basics 做过cla ...
- React-redux框架之connect()与Provider组件 用法讲解
react-redux 在react-redux 框架中,给我提供了两个常用的API来配合Redux框架的使用,其实在我们的实际项目开发中,我们完全可以不用react-redux框架,但是如果使用此框 ...
- salesforce lightning零基础学习(六)Lightning Data Service(LDS)
本篇可参看:https://trailhead.salesforce.com/modules/lightning_data_service Lightning中针对object的detail页面,一个 ...
- Vue加载组件、动态加载组件的几种方式
https://cn.vuejs.org/v2/guide/components.html https://cn.vuejs.org/v2/guide/components-dynamic-async ...
- C# 动态加载组件后怎么在开发环境中调试
动态加载组件 那就是简单的Assembly.Load动态加载dll而以.这网上资料也有不少.基本的思路基本上就是在本地上一个指定目录如[plugs]存在着一堆dll文件.主程序在初始运行时一般会把指定 ...
- Python框架之Django的相册组件
Python框架之Django的相册组件 恩,没错,又是Django,虽然学习笔记已经结贴,但是学习笔记里都是基础的,Django的东西不管怎么说还是很多的,要学习的东西自然不会仅仅用十几篇博文就能学 ...
- .net比较完美的动态注册com组件
.net中经常需要使用com组件,怎么样注册com组件呢? 一般想到的当然是直接通过系统cmd 调用regsvr32注册程序去注册,如下: regsvr32 name.dll 在.net中可以直接执行 ...
随机推荐
- 读入挂(IO)
快如闪电,清华杜瑜皓的读入挂,一模一样代码,加了这个之后... 细思极恐,and 整整行!!! namespace IO{ #define BUF_SIZE 100000 #define OUT_SI ...
- 解决C#调用执行js报检索 COM 类工厂中 CLSID 为 {0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC} 组件失败
最近做了一个模拟请求的网站简化原网站的繁琐数据,提出有用的数据简单展示并完成post.由于原网站数据有js加密,所以我抓出原网站的js解密方法,由C#调用js得到解密后的数据. 整个抓包的框架是用的苏 ...
- 《你不知道的javascript》读书笔记1
概述 放假读完了<你不知道的javascript>上篇,学到了很多东西,记录下来,供以后开发时参考,相信对其他人也有用. js的工作原理 引擎:从头到尾负责整个js的编译和运行.(很大一部 ...
- ios webview下footer部分fixed失效问题
场景: 如下图所示,一个很正常的页面需求,footer固定在底部,中间为滚动内容区 然后footer的css一般是这样的 footer{ position:fixed; bottom:; left:; ...
- [CocoaPods]使用CocoaPods进行测试
测试规格 从CocoaPods 1.3.0开始,pod现在可以提供测试规范(或简称测试规范).测试规范可用于描述给定pod的测试源. 这是一个示例CoconutLib.podspec,一个定义测试规范 ...
- 带你入门Python爬虫,8个常用爬虫技巧盘点
python作为一门高级编程语言,它的定位是优雅.明确和简单. 我学用python差不多一年时间了, 用得最多的还是各类爬虫脚本, 写过抓代理本机验证的脚本.写过论坛中自动登录自动发贴的脚本 写过自动 ...
- 架构书籍推荐:Java中高级、架构师值得一读!
上周我们免费送出了6本关于Python的重量级技术书籍,推出后反响特别强烈,有一个和最后一名仅差了一个赞,不过我们还是额外加送了一本送给这位朋友,以资鼓励,从另一面也可以看出Java程序猿对Pytho ...
- [视频]K8飞刀无代码编程之生成EXP
[视频]K8飞刀无代码编程之生成EXP 链接: https://pan.baidu.com/s/1CTBUpPrW3V8sHMd8yukZ8Q 提取码: ang7
- Java语言访问Redis数据库之Set篇
如果想通过Java语言对Redis数据库进行访问. 首先,需要安装Redis数据库,可以是Windows系统,或者Linux系统.(本文以Windows系统的本地Redis数据库为例,代码说明如何操作 ...
- 比较List和ArrayList的性能及ArrayList和LinkedList优缺点
List和ArrayList的性能比较 在使用ArrayList这样的非泛型集合的过程中,要进行装箱和拆箱操作,会有比较大的性能损失,而使用泛型集合就没有这样的问题.List是泛型,而ArrayLis ...