访问组件的最佳实践ID

要在 JavaScript 或其他支持 Web 的语言中引用 Visualforce 组件,您必须 为该组件的属性指定一个值。DOM ID 由组合构成 的属性 组件和属性 包含该元素的所有组件。ididid

使用全局变量简化 引用为 Visualforce 组件生成的 DOM ID,并减少对整个页面的一些依赖 结构。$Component要引用特定 Visualforce 组件的 DOM ID,请使用点表示法将组件路径说明符添加到 在页面的组件层次结构中分隔每个级别。例如 用。以引用 Visualforce 组件层次结构中同一级别的组件,或使用 …以指定更完整的组件路径。$Component$ComponentitemId$ComponentgrandparentIdparentIditemId路径说明符 与组件层次结构匹配:

$Component

  • 在组件层次结构的当前级别,其中使用;然后$Component
  • 在组件层次结构中每个连续的更高级别,直到 找到匹配项,或达到组件层次结构的顶层。

没有回溯,所以如果你尝试的 ID 匹配需要向上遍历然后向下遍历,它不会 火柴。以下示例说明了 的几种用法:

$Component

<apex:page >

    <style>
    .clicker { border: 1px solid #999; cursor: pointer;
        margin: .5em; padding: 1em; width: 10em; text-align: center; }
    </style>

    <apex:form id="theForm">
        <apex:pageBlock id="thePageBlock" title="Targeting IDs with $Component">
            <apex:pageBlockSection id="theSection">
                <apex:pageBlockSectionItem id="theSectionItem">
                    All the alerts refer to this component.
                    
                    <p>The full DOM ID resembles something like this:<br/>
                    j_id0:theForm:thePageBlock:theSection:theSectionItem</p>
                </apex:pageBlockSectionItem>

                <!-- Works because this outputPanel has a parent in common 
                     with "theSectionItem" component -->
                <apex:outputPanel layout="block" styleClass="clicker"
                    onclick="alert('{!$Component.theSectionItem}');">
                    First click here
                </apex:outputPanel>
            </apex:pageBlockSection>
            
            <apex:pageBlockButtons id="theButtons" location="bottom">
                <!-- Works because this outputPanel has a grandparent ("theSection")
                     in common with "theSectionItem" -->
                <apex:outputPanel layout="block" styleClass="clicker"
                    onclick="alert('{!$Component.theSection.theSectionItem}');">
                    Second click here
                </apex:outputPanel>

                <!-- Works because this outputPanel has a distant ancestor ("theForm")
                     in common with "theSectionItem" -->
                <apex:outputPanel layout="block" styleClass="clicker"
                    onclick="alert('
                    {!$Component.theForm.thePageBlock.theSection.theSectionItem}');">
                    Third click here
                </apex:outputPanel>
            </apex:pageBlockButtons>

        </apex:pageBlock>

        <!-- Works because this outputPanel is a sibling to "thePageBlock",
             and specifies the complete ID path from that sibling -->
        <apex:outputPanel layout="block" styleClass="clicker"
            onclick="alert('{!$Component.thePageBlock.theSection.theSectionItem}');">
            Fourth click here
        </apex:outputPanel>
        
        <hr/>
        
        <!-- Won't work because this outputPanel doesn't provide a path 
             that includes a sibling or common ancestor -->
        <apex:outputPanel layout="block" styleClass="clicker"
            onclick="alert('{!$Component.theSection.theSectionItem}');">
            This won't work
        </apex:outputPanel>

        <!-- Won't work because this outputPanel doesn't provide a path 
             that includes a sibling or common ancestor -->
        <apex:outputPanel layout="block" styleClass="clicker"
            onclick="alert('{!$Component.theSectionItem}');">
            Won't work either
        </apex:outputPanel>

    </apex:form>
</apex:page>

使用唯一 ID

在页面的每个层次结构段中,组件必须是唯一的。但是,Salesforce 建议 您使用的唯一 在页面上,您需要引用的每个组件以及任何组件 在引用它所需的组件层次结构中。idid

例如,假设您在一个页面中有两个数据表。 如果两个数据表都包含在同一个页块中,则它们必须 具有独特的属性。 如果每个都包含在单独的页面块中,则有可能 给他们相同的组件.但是,如果这样做,则引用特定数据的唯一方法 table 是将一个 to 每个组件,然后使用 完整的层次结构,而不是让 Visualforce 自动完成。如果页面层次结构发生更改,则程序 将不再起作用。ididid

使用组件 ID 进行迭代

某些组件(如表和列表)支持迭代 超过记录集合。为这些类型分配 ID 后 的组件,系统分配一个唯一的“复合 ID” 根据初始 ID 对组件进行每次迭代。例如,以下页面包含一个 ID 设置为 。

theTable

<apex:page standardController="Account" recordSetVar="accounts" id="thePage">
    <apex:dataTable value="{!accounts}" var="account" id="theTable">
        <apex:column id="firstColumn">
            <apex:outputText value="{!account.name}"/>
        </apex:column>
        <apex:column id="secondColumn">
            <apex:outputText value="{!account.owner.name}"/>
        </apex:column>
    </apex:dataTable>
</apex:page>

呈现页面时,组件结果 在以下 HTML 中:

<apex:dataTable>

<table id="thePage:theTable" border="0" cellpadding="0" cellspacing="0">
<colgroup span="2"/>
<tbody>
    <tr class="">
        <td id="thePage:theTable:0:firstColumn">
            <span id="thePage:theTable:0:accountName">Burlington Textiles</span>
        </td>
        <td id="thePage:theTable:0:secondColumn">
            <span id="thePage:theTable:0:accountOwner">Vforce Developer</span>
        </td>
    </tr>
    <tr class="">
        <td id="thePage:theTable:1:firstColumn">
            <span id="thePage:theTable:1:accountName">Dickenson</span>
        </td>
        <td id="thePage:theTable:1:secondColumn">
            <span id="thePage:theTable:1:accountOwner">Vforce Developer</span>
        </td>
    </tr>
</table>

每个表格单元格都有一个唯一的 ID,该 ID 基于 包含组件的 ID 值。中的第一个表单元格 第一行有 ID,第一行的第二个单元格有 ID,第一行有 ID 第二行中的单元格具有 ID,依此类推。

thePage:theTable:0:firstColumnthePage:theTable:0:secondColumnthePage:theTable:1:firstColumn

要引用列中的所有条目,您有 遍历表行,引用 ID 如下的每个元素 列的格式。<td>

相同类型的 ID 生成是 对表格单元格中的元素执行。例如,帐户 第一行中的 name 生成为 ID 为 。请注意,ID 不包括列的 ID 值 它进来了。spanthePage:theTable:0:accountName

静态资源的最佳实践

显示属性为 的静态资源的内容action<apex:page>您可以 使用属性 在组件上 从 Visualforce 页面重定向到静态资源。此功能允许您添加 为您的 Visualforce 页面提供丰富的自定义帮助。例如,要将用户重定向到 PDF:

action<apex:page>

  1. 将 PDF 作为名为 customhelp 的静态资源上传。
  2. 创建以下页面:<apex:page sidebar="false" showHeader="false" standardStylesheets="false" action="{!URLFOR($Resource.customhelp)}"> </apex:page>

请注意,静态资源引用包装在函数中。如果没有这个, 页面未正确重定向。

URLFOR此重定向是 不限于 PDF 文件。您还可以将页面重定向到内容 的任何静态资源。例如,您可以创建静态资源 其中包括一个由许多混合的 HTML 文件组成的整个帮助系统 使用 JavaScript、图像和其他多媒体文件。只要有 是单个入口点,重定向有效。例如:

  1. 创建一个包含帮助内容的 zip 文件。
  2. 将 zip 文件作为名为 customhelpsystem 的静态资源上传。
  3. 创建以下页面:<apex:page sidebar="false" showHeader="false" standardStylesheets="false" action="{!URLFOR($Resource.customhelpsystem, 'index.htm')}"> </apex:page>

当用户访问该页面时,将显示静态资源中的 index.htm 文件。

控制器和控制器的最佳实践 扩展

在控制器中强制执行共享规则像其他 Apex 一样 类、自定义控制器和控制器扩展在系统中运行 模式。通常,您需要一个 控制器或控制器扩展,以尊重用户的 组织范围的默认值、角色层次结构和共享规则。你可以做 通过在类定义中使用关键字。with sharing有关信息,请参阅《使用 、 和关键字》中的“使用 Apex 开发人员 指南。with sharingwithout sharinginherited sharing

注意

如果 控制器扩展扩展了一个标准控制器,逻辑来自 标准控制器不在系统模式下执行。相反,它 在用户模式下执行,其中权限、字段级安全性和 当前用户的共享规则适用。控制器构造函数在 Setter 方法之前进行计算不要依赖于在构造函数之前计算的 setter 方法。为 例如,在以下组件中,组件的控制器依赖于 被召唤的 setter 在构造函数方法之前:selectedValue

<apex:component controller="CustCmpCtrl">
      <apex:attribute name="value" description="" 
                      type="String" required="true" 
                      assignTo="{!selectedValue}">
      </apex:attribute>
      //...
      //...
</apex:component>
public class CustCmpCtrl {
      
      // Constructor method
      public CustCmpCtrl() {
            if (selectedValue != null) {
                EditMode = true;
            }
      }
      
      private Boolean EditMode = false;

      // Setter method
      public String selectedValue { get;set; }
}

因为 构造函数在 setter 之前调用,调用构造函数时将始终为 null。 因此,永远不会设置为 真。selectedValueEditMode方法可以多次评估 – 不要使用副作用方法,包括控制器中的方法、操作属性和表达式, 可以多次调用。不要依赖于评估顺序或副作用 在控制器或控制器扩展中创建自定义方法时。

使用组件分面的最佳实践

分面由区域中的内容组成 提供有关数据的上下文信息的 Visualforce 组件 这在组件中呈现。例如,支持分面 用于表格的页眉、页脚和标题,而仅支持 facet 用于列的页眉和页脚。该组件允许 您可以使用自己的内容覆盖 Visualforce 组件上的默认分面。分面只允许一个子项 在开始和结束标记中。

<apex:dataTable><apex:column><apex:facet>

注意

并非所有组件 支持分面。这些列在标准组件参考中。

定义 时,它始终用作另一个 Visualforce 组件的子组件。属性 在 Facet 上确定覆盖父组件的哪个区域。<apex:facet>name

示例:将 Facet 与 <apex:dataTable> 一起使用

以下标记显示了组件如何 修改为:

<apex:dataTable><apex:facet>

<apex:page standardController="Account">
    <apex:pageBlock>
        <apex:dataTable value="{!account}" var="a">
            <apex:facet name="caption"><h1>This is 
              {!account.name}</h1></apex:facet>
            <apex:facet name="footer"><p>Information 
              Accurate as of {!NOW()}</p></apex:facet>
            <apex:column>
                <apex:facet name="header">Name</apex:facet>
                <apex:outputText value="{!a.name}"/>
            </apex:column>
            
            <apex:column>
                <apex:facet 
              name="header">Owner</apex:facet>
                <apex:outputText value="{!a.owner.name}"/>
            </apex:column>
        </apex:dataTable>
    </apex:pageBlock>        
</apex:page>

注意

要使此页面显示帐户数据,ID 必须在 页面的 URL。例如:

https://Salesforce_instance/apex/facet?id=001D000000IRosz

页面显示如下:

使用 Facet 扩展 <apex:dataTable>分面示例

将 Facet 与 <apex:actionStatus 一起使用>

另一个可以使用分面的组件是 。组件 可以扩展为在刷新页面时显示指示器。 例如,您可以使用以下标记定义进度轮:

<apex:actionStatus><apex:actionStatus>

<apex:page controller="exampleCon">
    <apex:form >
        <apex:outputText value="Watch this counter: {!count}" id="counter"/>
        <apex:actionStatus id="counterStatus">
            <apex:facet name="start">
                 <img src="{!$Resource.spin}"/> <!-- A previously defined image -->
            </apex:facet>
        </apex:actionStatus>    
        <apex:actionPoller action="{!incrementCounter}" rerender="counter"
            status="counterStatus" interval="7"/>
    </apex:form>
</apex:page>

关联的控制器更新 计数器:

public class exampleCon {
    Integer count = 0;
                        
    public PageReference incrementCounter() {
            count++;
            return null;
    }
                        
    public Integer getCount() {
        return count;
    }
}

页面显示如下:

使用 Facet 扩展 <apex:actionStatus>

页面块组件的最佳实践

将两个以上的子组件添加到<apex:pageBlockSectionItem>一个组件最多只能有两个子组件。不过,有时候, 您想要添加一个额外的子组件。例如,您可能需要 在之前添加星号,并且仍然显示关联的输入文本字段。你可以这样做 通过将星号和输出标签包装在组件中, 如下:<apex:pageBlockSectionItem><apex:outputLabel><apex:outputPanel>

注意

要使此页面显示帐户数据,ID 必须在 页面的 URL。例如:

https://Salesforce_instance/apex/myPage?id=001D000000IRosz
<!-- Page: -->
<apex:page standardController="Account">
    <apex:form >
        <apex:pageBlock title="My Content" mode="edit">
            <apex:pageBlockSection title="My Content Section" columns="2">
                <apex:pageBlockSectionItem >
                    <apex:outputPanel>
                        <apex:outputText>*</apex:outputText>
                        <apex:outputLabel value="Account Name" for="account__name"/>
                    </apex:outputPanel>
                    <apex:inputText value="{!account.name}" id="account__name"/> 
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

渲染 PDF 文件的最佳实践

将 Visualforce 页面呈现为 PDF 文件是共享有关 Salesforce 组织信息的好方法。这里有一些最好的 供您考虑的做法。

为了在渲染 Visualforce 页面时获得更好的性能,请参考静态图像和 通过 $Resource 全局的样式表资源 变量。

警告

在远程服务器上引用静态资源会增加所需的时间 将 Visualforce 页面呈现为 PDF 文件。将远程服务器添加到允许的远程站点列表:在“设置”中,输入“快速查找”框,然后选择“远程站点设置”。使用时无法引用远程资源 Visualforce 以 顶点触发器。这样做会导致异常。Remote Sites Settings

<apex:panelbar> 的最佳实践

将子组件的集合添加到组件<apex:panelBarItem><apex:panelBar>一个组件只能有子组件。但是,有时您想要添加一个集合 的子组件。例如,您可能希望为 与一个帐户关联的每个联系人。您可以通过包装组件来执行此操作,如下所示:<apex:panelBar><apex:panelBarItem><apex:panelBarItem><apex:repeat>

注意

要使此页面显示帐户数据,有效帐户的 ID 记录必须指定为页面 URL 中的查询参数。 例如:https:// Salesforce_instance/apex/myPage?id=001D000000IRosz

<apex:page standardController="account">
  <apex:panelBar >
    <apex:repeat value="{!account.contacts}" var="c">
      <apex:panelBarItem label="{!c.firstname}">one</apex:panelBarItem>
    </apex:repeat>
  </apex:panelBar>
</apex:page>

文档排版约定

Apex 和 Visualforce 文档使用以下排版约定。

公约描述
Courier font在语法说明中,等宽字体表示应 如图所示键入,括号除外。例如:Public class HelloWorld
Italics在语法描述中,斜体表示变量。您提供 实际值。在以下示例中,需要提供三个值:datatype variable_name [ = value];如果语法为粗体和斜体,则文本 表示需要您提供的值的代码元素,例如 类名或变量 价值:public static class YourClassHere { ... }
Bold Courier font在代码示例和语法描述中,粗体 courier 字体强调 部分代码或语法。
< >在语法描述中,小于和大于符号 (< >) 是 键入的内容与所示完全相同。<apex:pageBlockTable value="{!account.Contacts}" var="contact"> <apex:column value="{!contact.Name}"/> <apex:column value="{!contact.MailingCity}"/> <apex:column value="{!contact.Phone}"/> </apex:pageBlockTable>
{ }在语法说明中,大括号 ({ }) 的键入方式与所示完全相同。<apex:page> Hello {!$User.FirstName}! </apex:page>
[ ]在语法描述中,括号中包含的任何内容都是可选的。在 以下示例中,指定 自选: valuedata_type variable_name [ = value];
|在语法描述中,竖线符号的意思是“或”。您可以 执行下列操作之一(不是全部)。在以下示例中,您可以创建一个 通过以下两种方式之一新建未填充的集,也可以填充集:Set<data_type> set_name [= new Set<data_type>();] | [= new Set<data_type{value [, value2. . .] };] | ;