优化 Visualforce 代码的实用指南
1. 代码复用
在开发过程中,代码复用是提高效率和可维护性的关键。下面介绍几种实现代码复用的方法:
- 包含其他 VF 页面 : <apex:include> 组件提供了最简单的代码复用形式,可将现有的 VF 页面插入到另一个页面中。更多代码片段和详细信息可访问 http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_include.htm 。不过,该组件仅适用于简单的代码复用需求。
- 定义模板或页面布局 : <apex:composition> 组件提供了一种基于模板的复杂页面内容处理方法。当多个页面需要遵循共同的布局模式(如包含通用的页眉、侧边栏和页脚,以及可变的主体部分)时,它特别有用。此组件在 Salesforce 站点中使用效果最佳,所有公共页面都需要遵循共同的布局。在组织中创建/启用站点时,平台生成的页面(如 SiteTemplate.page )能很好地展示该组件的最佳用法。更多代码片段和详细信息可访问 http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_composition.htm 。
- 定义自定义组件 :开发人员可以使用 <apex:component> 标签定义自己的组件。这些组件并非像 <apex:include> 标签那样只是简单的代码片段,而是具有高度的动态性和可定制性,以适应各种包含场景。组件的主要特点如下:
- 可以有自己的控制器,具备查询 sObjects、进行 HTTP 调用和 DML 调用的能力。
- 可以从容器页面获取属性,以自定义行为和外观。
更多代码片段和详细信息可访问 http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_component.htm 。
2. 限制视图状态
由于 HTTP 是无状态协议,页面的所有状态通过一个名为 ViewState 的字符串来回传输。ViewState 主要包含以下内容:
- 与控制器/扩展相关的所有非瞬态属性数据。
- 可从控制器/扩展中的非瞬态属性访问的对象图。
- 页面的组件结构以及应用于这些组件的相关状态值。
- VF 运行时维护的琐碎数据。
强烈建议了解如何最小化视图状态,原因如下:
- VF 运行时对视图状态施加了 135 KB 的限制(截至 Winter ‘13 版本),如果超过此限制将抛出异常。
- 较大的视图状态会影响 Visualforce 的性能,因为需要传输和处理更多的数据。
以下是一些最小化视图状态的建议:
- 使用视图状态检查器 :当页面性能缓慢或达到限制时,使用视图状态检查器是个不错的选择。启用视图状态检查器的步骤如下:
1. 进入 Setup。
2. 选择 Personal Setup。
3. 点击 My Personal Information。
4. 选择 Personal Information。
5. 点击 Edit 按钮。
6. 确保在 Development Mode 中勾选 Show View State。
- 尽可能使用静态变量 :在控制器中使用静态变量声明常量和变量,因为静态变量不属于视图状态的一部分。静态变量的优点是每次请求时都会恢复到原始值。以下是一些使用静态变量节省视图状态的示例:
public with sharing class CustomContactController {
// 声明常量
static final String RECORD_TYPE_NAME = 'My_Rec_Type';
// 可以进行直接查询
public static final Account [] accounts =
[Select Id, Name from Account Where BillingCity like
:ApexPages.currentPage().getParameters().get('billcity')];
// 为 VF 访问提供 getter 和 setter,在静态块中填充逻辑
public static final Contact[] contacts {get;set;}
static {
// 可以在静态块中进行任何复杂的处理
// 请注意,此块将在每次页面刷新和 Ajax 请求时执行
String reqdPhone =
ApexPages.currentPage().getParameters().get('phone');
if (reqdPhone != '' && reqdPhone != null) {
contacts = [Select Id, Name from Contact
Where Phone like :reqdPhone];
}
}
}
更多关于静态变量的信息可访问 http://www.tgerm.com/2010/09/visualforce-apex-static-instance.html 。
- 使用瞬态变量修剪视图状态 : transient 关键字用于标记实例变量,这些变量在序列化过程中不会被传输。序列化是将数据结构或对象状态转换为可存储(如文件或内存缓冲区)或通过网络连接传输的格式的过程。在 Apex 或 VF 代码中,序列化可能发生在以下几个位置:
- 视图状态,将控制器/扩展信息序列化为隐藏的 HTML 表单字段。
- Apex REST 调用,实例级属性从 JSON 或 XML 字符串中序列化/反序列化。更多信息可访问 http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_rest_methods.htm 。
- 其他可序列化的类,如 Batchable 或 Schedulable 接口。
以下是一个限制视图状态的示例,将用户列表标记为瞬态,因为该信息在 VF 页面上只需只读一次:
public class CaseCustomController {
public List<Case> casesToReassign {get;set;}
/*
将此集合标记为瞬态,因为在表单提交或回发时不需要该集合。
*/
public transient List<User> availableSupportReps {get;set;}
}
识别瞬态变量的方法是检查某些属性是否满足以下条件:
- 仅在页面渲染时需要,例如只读记录列表。
- 在回发(AJAX 调用)期间不提交。
- 可以在回发时使用其他视图状态信息(如记录 ID)恢复。
- 避免使用多个表单 :建议避免使用 <apex:form> 标签创建多个 HTML 表单,因为这会导致每个表单重复隐藏的视图状态变量。真正的问题出现在回发时,所有表单的视图状态都会提交回服务器。例如:
<!-- 使用多个表单 -->
<apex:page controller="CustomAccountController">
<!-- 表单 1 -->
<apex:form>
<apex:inputText value="{!accountName}"
<!-- 其他用于搜索的账户字段 -->
<apex:commandButton action="{!searchAccounts}" value=
"Search Accounts"/>
</apex:form>
<!-- 表单 2 -->
<apex:form>
<apex:inputField value="{!acc.Name}" />
<!-- 更多账户输入字段 -->
<apex:commandButton action="{!quickCreateAccount}" value=
"Quick Create Account"/>
</apex:form>
</apex:page>
解决此问题的方法是移除多个表单,并使用动作区域进行划分,示例代码如下:
<!-- 使用动作区域 -->
<apex:page controller="CustomAccountController">
<!-- 单个表单 -->
<apex:form>
<apex:actionRegion>
<apex:inputText value="{!accountName}"
<!-- 其他用于搜索的账户字段 -->
<apex:commandButton action="{!searchAccounts}" value=
"Search Accounts"/>
</apex:actionRegion>
<apex:actionRegion>
<apex:inputField value="{!acc.Name}" />
<!-- 更多账户输入字段 -->
<apex:commandButton action="{!quickCreateAccount}" value=
"Quick Create Account"/>
</apex:actionRegion>
</apex:form>
</apex:page>
不过,自 Summer ‘12 版本发布后,单视图状态功能已普遍可用。即使创建多个表单,它们也将共享单个视图状态。虽然问题已解决,但在这种情况下使用动作区域仍然是最佳实践。
- 仅查询所需字段 :SOQL 查询应仅获取业务逻辑或页面展示所需的字段/列。例如,以下是一个显示账户可编辑网格的 VF 页面,包含 Name 和 Description 两列:
<apex:pageBlockTable value="{!accounts}" var="acc">
<apex:column headerValue="Name">
<apex:inputField value="{!acc.Name}"/>
</apex:column>
<apex:column headerValue="Description">
<apex:inputField value="{!acc.Description}"/>
</apex:column>
</apex:pageBlockTable>
对应的控制器虽然逻辑正确,但查询了过多不需要的列,如电话、传真和运输详细信息字段等:
public with sharing class TooMuchInfoController {
public Account[] accounts {get;set;}
public TooMuchInfoController() {
accounts = [SELECT Name, Phone, Site, Description, Fax,
ShippingCity, ShippingCountry, ShippingState, ShippingStreet,
ShippingPostalCode FROM Account LIMIT 10];
}
}
这样做会导致视图状态增大,可以使用视图状态检查器轻松检查。更多关于视图状态的提示和技巧可访问 http://wiki.developerforce.com/page/An_Introduction_to_Visualforce_View_State 。
3. 使用字段集实现灵活页面
客户通常希望能够像页面布局一样灵活地更改/添加 VF 页面中的字段。在一定程度上,字段集可以实现这一需求。字段集本质上是通过点选配置确定的一组字段。在开发 AppExchange 应用并依赖标准对象时,这一点尤为重要。在大多数情况下,客户会在标准对象上创建自己的自定义字段,并希望这些字段在应用的 VF 页面上也能可见/可编辑。
- 创建字段集的方法可访问 https://ap1.salesforce.com/help/doc/en/fields_editing_field_sets.htm 。
- 学习如何在 Apex 和 VF 代码中使用字段集可访问 http://www.salesforce.com/us/developer/docs/pages/Content/pages_dynamic_vf_field_sets.htm 。
字段集还提供了通过点选标记某些字段为必需的功能。Apex 或 VF 代码可以读取此配置以执行所需的操作。示例代码如下:
<apex:repeat value="{!$ObjectType.Contact.FieldSets.auditform}" var="f">
<apex:inputField value=
"{!Contact[f]}" required="{!f.required}"/>
</apex:repeat>
4. 加速 Ajax 调用
Ajax 为任何网页增添了趣味性和响应性,但如果 Ajax 调用耗时过长,这种乐趣就会消失。以下是一些提高 Visualforce 页面中 Ajax 性能的关键提示:
- 使用 immediate 属性 :该属性可用于所有支持 VF 和 Ajax 的组件,如 <actionFunction> 、 <actionPoller> 、 <actionSupport> 、 <commandLink> 和 <commandButton> 。该属性默认设置为 false,这意味着在进行 AJAX 调用之前必须处理所有验证规则。但在某些情况下,无需进行验证,例如:
- 点击取消或重置按钮,这些按钮几乎会清除所有表单数据。
- 点击记录网格上的删除按钮,只需在 <apex:param> 中获取要删除记录的 ID 并刷新网格。
在上述情况下,将 immediate 属性设置为 true 可以显著提高性能。
- 仅重新渲染所需组件 :新开发人员有时会忽略 reRender 属性,该属性可用于所有支持 VF 和 AJAX 的组件。该属性指定在 AJAX 调用后应从新信息中刷新页面的哪些部分/组件。如果不设置该属性,将刷新整个页面,这肯定会花费更多时间。示例代码如下:
<apex:pageMessages id="messages"/>
<!-- … 其他标记和组件 -->
<apex:pageBlockSection id="contactFields">
<apex:repeat value="{!$ObjectType.Contact.FieldSets.auditform}"
var="f">
<apex:inputField value="{!Contact[f]}"
required="{!f.required}"/>
</apex:repeat>
</apex:pageBlockSection>
<!-- 仅重新渲染 contactFields 和 messages 部分 -->
<apex:commandButton value="Save" action="{!save}"
reRender="contactFields, messages"/>
使用 reRender 属性还可以避免一些 VF 错误。如果未指定 reRender 属性,像 <apex:commandButton/> 这样的组件可能无法正确获取 <apex:param/> 输入。更多详细信息可访问 http://success.salesforce.com/ideaView?id=08730000000YcV8AAK 。
- 使用动作区域进行划分 :AJAX 主要用于部分页面刷新,但有时控制每次 AJAX 请求处理的组件数量和数据量是有好处的。 <apex:actionRegion> 有助于划分这个边界,使有限数量的组件参与各种处理步骤。这不仅可以加快 AJAX 性能,还可以在某些情况下使 AJAX 调用绕过一些验证。更多关于动作区域的信息可访问:
- http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_actionRegion.htm
- http://www.tgerm.com/2010/09/visualforce-actionregion-deep-dive.html
5. 全局变量和函数
虽然这个主题在 VF 开发人员指南的附录部分提及,但作为开发人员,理解它非常重要。全局变量和函数通过以下表达式语法使用: {!$VAR or Function} 。以下是一些示例:
- $Action 全局变量可用于链接到新的账户页面:
<apex:outputLink value="{!URLFOR($Action.Account.New)}">
Create New Account
</apex:outputLink>
- 对于使用自定义标签的多语言应用,可以在页面中引用这些标签。例如,名为
error_msg_invoice的自定义标签可以在页面中访问如下:
{!$Label.error_msg_invoice }
- 可以创建一个安全的超链接到另一个名为
AccountCreationWizard的 VF 页面:
<apex:outputLink value="{!$Page.AccountCreationWizard }">
Start Account Creation
</apex:outputLink>
- 要在页面中访问字段标签,可以使用
$ObjectType:
{!$ObjectType.Account.Fields.Name.Label}
- 可以使用
NOW()函数打印当前时间:
Current Time: {!NOW()}
完整的全局变量和函数参考可访问 http://www.salesforce.com/us/developer/docs/pages/Content/pages_variables.htm 。
6. JavaScript 远程调用
JavaScript 远程调用通过 JavaScript 为 Apex 控制器中的方法提供了超快速的 AJAX 调用。如果不了解 JavaScript 远程调用,建议先阅读 http://www.salesforce.com/us/developer/docs/pages/Content/pages_js_remoting.htm 。以下是使用 JS 远程调用时的一些关键实现提示:
- 选择正确的访问修饰符 :在 JS 远程调用最初推出时,必须将 Apex 控制器设为全局,但随着最近的版本发布,这一限制已取消,Apex 控制器也可以是公共的。强烈建议在组织中尽量减少全局 Apex 代码的使用,特别是在为托管包开发应用时,因为全局类/方法不利于维护,并且在新版本中不能重命名或移除。
- 充分利用方法参数和返回类型 :JavaScript 远程调用在参数和返回值中支持基本类型和复杂类型。这使得页面和控制器之间可以以 JSON 形式来回序列化复杂信息。官方指南中提到:
- 方法可以接受 Apex 基本类型、集合、类型化和通用 sObjects 以及用户定义的 Apex 类和接口作为参数。通用 sObjects 必须有 ID 或 sobjectType 值来标识实际类型。接口参数必须有 apexType 来标识实际类型。
- 方法可以返回 Apex 基本类型、sObjects、集合、用户定义的 Apex 类和枚举、SaveResult、UpsertResult、DeleteResult、SelectOption 或 PageReference。
- 处理托管包中的命名空间前缀 :通过 JS 远程调用调用远程 Apex 控制器有两种方法:
- 方法一 :
[namespace.]controller.method([parameters...,] callbackFunction,
[configuration] );
// 命名空间 :abhinav
// 控制器 :GoogleChartsController
// 方法 :loadOpps
// 参数: accountName = document.getElementById('acctSearch').value;
abhinav.GoogleChartsController.loadOpps(accountName,
function(result, event){
alert('Total Records:' + result.length);
}, {escape:true});
这种方法适用于在非托管环境(即没有命名空间前缀)中工作的情况。例如,在沙箱中为一个 Salesforce 组织进行的组织定制开发的页面。
- 方法二 :
Visualforce.remoting.Manager.invokeAction('fully_qualified_remote_
action', invocation_parameters );
// 完全限定的远程操作: GoogleChartsController
// 调用参数: accountName = document.getElementById('acctSearch').value;
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.GoogleChartsController.loadOpps}',
accountName,
function(result, event){
alert('Total Records:' + result.length);
},
{escape: true}
);
这种方法适用于所有场景,因为它可以正确解析命名空间,无论是在托管还是非托管环境中工作。
7. 确保页面的安全合规性
在使用 Apex 和 Visualforce 时,很容易出现安全问题。如果正在开发/在 AppExchange 上列出应用,安全审查过程会确保应用符合指南。但如果是为单个组织进行 Force.com 定制,也应该注意安全问题。所有 Force.com 开发人员都应该阅读 http://wiki.developerforce.com/page/Secure_Coding_Guideline 。
- 编码/转义 :在页面上打印内容时,对其进行编码/转义通常是安全的。大多数 Visualforce 组件(如 <apex:outputField> 、 <apex:outputText> 等)默认会进行转义处理。但在某些情况下,最好在服务器端对文本进行编码。例如,以下代码在页面上打印账户 ID:
/apex/MyPage?Id={!$CurrentPage.parameters.Id}
如果用户在 ID 中传递了攻击字符串,代码将会出错。例如:
/apex/MyPage?Id=<script>alert('XSS');</script>
解决此类问题的简单方法是根据情况使用各种编码函数,如 JSENCODE 、 HTMLENCODE 、 JSINHTMLENCODE 和 URLENCODE 。上述代码可以通过以下代码修复:
/apex/MyPage?Id={!JSENCODE($CurrentPage.parameters.Id)}
更多关于转义函数的信息可访问:
- http://www.salesforce.com/us/developer/docs/pages/Content/pages_variables_functions.htm
- http://wiki.developerforce.com/page/Secure_Coding_Cross_Site_Scripting#Apex_and_Visualforce_Applications
- 实施 CRUD 和 FLS :对象(CRUD)和字段级安全(FLS)设置来自配置文件,用于根据不同配置文件的权限限制对对象类型和单个字段的访问。在大多数情况下,平台和 VF 运行时会自动处理 CRUD/FLS 强制执行。例如:
- 合并字段(即 {!object.field} )在页面渲染时会检查所需的权限。
- 像 <apex:inputField> 和 <apex:outputField> 这样的标签基于上述合并字段概念工作, inputField 标签在缺少权限时不会渲染或呈现为只读, outputField 标签在缺少权限时不会打印。
除了上述情况,开发人员在绕过原生功能的各种场景中也需要注意安全问题。例如:
- 将对象字段值复制到控制器属性或方法中,然后在 VF 页面上打印:
<apex:page controller="CustomContactController">
<apex:outputText value="{!FullName}" />
</apex:page>
public with sharing class CustomContactController {
public String getFullName() {
Contact con = [SELECT FirstName, LastName
FROM Contact
WHERE Id =:contactId];
return con.FirstName + ' ' + con.LastName;
}
}
上述代码片段可以在 Apex 或 VF 代码中修复。以下是两种修复方法(请选择其中一种):
- 修复后的 VF 页面 :
<apex:page controller="CustomContactController">
<apex:outputText value="{!FullName}" rendered="
{!AND($ObjectType.Contact.fields.FirstName.Accessible,
$ObjectType.Contact.fields.LastName.Accessible)}"/>
</apex:page>
- **修复后的控制器**:
public with sharing class CustomContactController {
public String getFullName() {
if
(!Schema.sObjectType.Contact.fields.
FirstName.isAccessible()
||
!Schema.sObjectType.Contact.fields.LastName.
isAccessible()
){
/*
根据业务需求,要么返回空字符串,要么抛出错误。
*/
return '';
}
Contact con = [SELECT FirstName, LastName
FROM Contact
WHERE Id =:contactId];
return con.FirstName + ' ' + con.LastName;
}
}
- 在自定义 DML 操作和其他组件(如相关列表)中访问对象。以下代码片段检查当前配置文件是否可以访问 Contact 对象:
<apex:relatedList list="Contacts" rendered="{!$ObjectType.Contact.accessible}"/>
综上所述,通过合理运用代码复用、限制视图状态、加速 Ajax 调用、使用全局变量和函数、JavaScript 远程调用以及确保安全合规性等方法,可以显著提高 Visualforce 代码的性能和可维护性。在实际开发中,应根据具体需求选择合适的技术和方法,以实现最佳的开发效果。
优化 Visualforce 代码的实用指南
8. 总结与最佳实践回顾
为了更清晰地回顾前面提到的优化 Visualforce 代码的方法,以下通过表格形式呈现关键要点和对应的操作建议。
| 优化方面 | 操作建议 | 具体示例 |
|---|---|---|
| 代码复用 | 使用 <apex:include> 插入现有 VF 页面; <apex:composition> 创建模板化布局; <apex:component> 定义自定义组件 | <apex:include page="ExistingPage"/> <apex:composition template="TemplatePage"> |
| 视图状态优化 | 使用视图状态检查器;使用静态和瞬态变量;避免多表单;仅查询所需字段 | static final String CONSTANT = 'Value'; public transient List<User> users; |
| 字段集使用 | 创建字段集并在代码中引用,可标记字段为必需 | <apex:repeat value="{!$ObjectType.Contact.FieldSets.auditform}" var="f"> <apex:inputField value="{!Contact[f]}" required="{!f.required}"/> |
| Ajax 调用加速 | 使用 immediate 属性跳过验证;仅重新渲染必要组件;使用 <apex:actionRegion> 控制处理范围 | <apex:commandButton immediate="true" action="{!action}"/> <apex:commandButton reRender="componentId" action="{!action}"/> |
| 全局变量和函数 | 通过 {!$VAR or Function} 语法使用 | {!$Action.Account.New} {!NOW()} |
| JavaScript 远程调用 | 选择合适访问修饰符;利用参数和返回类型;正确处理命名空间 | public class Controller {... } Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.Controller.method}', param, callback); |
| 安全合规 | 对输出内容编码;实施 CRUD 和 FLS 检查 | {!JSENCODE($CurrentPage.parameters.Id)} <apex:outputText rendered="{!$ObjectType.Contact.fields.FirstName.Accessible}"/> |
9. 实际应用中的流程示例
以下是一个使用 mermaid 绘制的流程图,展示了一个典型的 Visualforce 页面开发及优化流程:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A([开始开发 Visualforce 页面]):::startend --> B(设计页面布局和功能):::process
B --> C(实现基本代码逻辑):::process
C --> D{是否需要代码复用?}:::process
D -->|是| E(选择合适的复用组件):::process
D -->|否| F(继续后续开发):::process
E --> F
F --> G(编写查询语句):::process
G --> H(检查视图状态大小):::process
H --> I{视图状态是否过大?}:::process
I -->|是| J(应用视图状态优化方法):::process
I -->|否| K(添加 Ajax 功能):::process
J --> K
K --> L(优化 Ajax 性能):::process
L --> M(使用全局变量和函数简化代码):::process
M --> N(集成 JavaScript 远程调用):::process
N --> O(进行安全合规检查):::process
O --> P(修复安全问题):::process
P --> Q(测试页面性能和功能):::process
Q --> R([完成开发]):::startend
10. 常见问题及解决方案
在 Visualforce 代码开发和优化过程中,可能会遇到一些常见问题,以下是部分问题及对应的解决方案。
10.1 视图状态超出限制
- 问题描述 :页面加载缓慢或抛出视图状态超出 135 KB 限制的异常。
- 解决方案 :
- 检查控制器中是否有不必要的变量未标记为瞬态,如示例中的
availableSupportReps:
- 检查控制器中是否有不必要的变量未标记为瞬态,如示例中的
public class CaseCustomController {
public List<Case> casesToReassign {get;set;}
public transient List<User> availableSupportReps {get;set;}
}
- 优化查询语句,仅获取必要的字段,避免查询过多无用数据。
- 避免使用多个`<apex:form>`标签,可使用`<apex:actionRegion>`替代。
10.2 Ajax 调用性能不佳
- 问题描述 :Ajax 调用响应时间过长,影响用户体验。
- 解决方案 :
- 将
immediate属性设置为true,跳过不必要的验证,例如在取消或删除操作的按钮上:
- 将
<apex:commandButton immediate="true" action="{!cancelAction}" value="Cancel"/>
- 确保`reRender`属性指定了正确的组件 ID,仅刷新必要的部分:
<apex:commandButton reRender="targetComponent" action="{!updateAction}" value="Update"/>
10.3 安全漏洞风险
- 问题描述 :页面可能存在跨站脚本攻击(XSS)等安全漏洞。
- 解决方案 :
- 对输出内容进行编码,如使用
JSENCODE、HTMLENCODE等函数:
- 对输出内容进行编码,如使用
/apex/MyPage?Id={!JSENCODE($CurrentPage.parameters.Id)}
- 在代码中实施 CRUD 和 FLS 检查,确保用户只能访问其具有权限的对象和字段:
<apex:outputText value="{!FullName}" rendered="{!AND($ObjectType.Contact.fields.FirstName.Accessible, $ObjectType.Contact.fields.LastName.Accessible)}"/>
11. 未来趋势与拓展思考
随着 Salesforce 平台的不断发展,Visualforce 代码的开发和优化也将面临新的挑战和机遇。未来可能会出现更多自动化的工具和框架,帮助开发者更高效地完成代码优化工作。例如,智能代码分析工具可以自动检测视图状态问题、安全漏洞等,并提供相应的修复建议。
同时,随着用户对页面性能和响应速度的要求越来越高,对 Ajax 调用和 JavaScript 远程调用的优化将变得更加重要。开发者需要不断学习新的技术和方法,以适应这些变化。
在拓展方面,开发者可以考虑将 Visualforce 与其他 Salesforce 技术(如 Lightning Web Components)相结合,以实现更丰富的用户体验和更高的性能。例如,在一些复杂的页面中,可以使用 Lightning Web Components 来实现部分交互性强的功能,而 Visualforce 则负责处理一些传统的业务逻辑和数据展示。
总之,通过持续关注行业动态、学习新技术,并不断实践和优化,开发者可以更好地应对未来的挑战,开发出高质量的 Visualforce 应用。
超级会员免费看
35

被折叠的 条评论
为什么被折叠?



