Lightning-组件(6)输入

学习目标

完成本单元后,您将能够:

  • 创建一个窗体来显示当前值并接受新的用户输入。
  • 从表单元素读取值。
  • 验证用户输入并显示无效输入的错误消息。
  • 将组件的控制器中的代码重构为其助手。

使用表单输入数据

就这个单元而言,我们完成了helloWhatever-style的组件。从这里开始,我们将创建和组装我们之前预览过的费用跟踪器迷你应用程序。我们将花费大部分的单位建设和理解的形式,让你创造一个新的开支。

费用应用程序容器

但是在开始之前,我们还需要做一些简单或者彻头彻尾的丑陋的组件。那么我们要做的第一件事就是引入Salesforce Lightning Design System或SLDS,并在我们的应用程序中“激活”它。我们这样做的方式让我们谈一谈关于应用程序容器。

注意

我们实际上不会在这个单元里讨论SLDS本身,或者在模块的其余部分的任何地方。我们将重点介绍将它添加到应用程序中,然后在我们的示例代码中,我们将使用SLDS类,但不会详细解释它们。有关SLDS的更多信息,请参阅参考资料。

今天,在Lightning Experience或Salesforce应用程序中运行SLDS时,SLDS将自动提供给您的组件。我们有时会在one.app容器中调用它。该内置版本与许多标准Lightning组件使用的版本相同。但是,SLDS在独立应用程序中默认情况下不可用,或者在“闪电输出”或“闪电组件”中使用您的组件用于Visualforce。这些是不同的应用程序容器,它们提供不同的服务和资源。我们希望以这种方式创建我们的费用应用程序,使其在所有这些情况下都能够正常工作。幸运的是,这并不是很难做到。

我们将这样做的方式是将SLDS添加到我们的线束应用程序。然后,在“真正的”费用应用程序(实际上是顶级组件及其所有子组件)中,我们可以使用SLDS工具和技术,而不用担心SLDS资源样式表,图标等等 – 来自。也就是说,我们的应用程序容器(线束应用程序)在其上下文中设置资源,以便在该容器内运行的任何应用程序都拥有所需的资源。

让我们把这些罗嗦的概念转换成一些代码。使用以下标记创建一个新的expensesApp.app闪电应用程序。

<aura:application extends="force:slds">
       
        <!-- This component is the real "app" -->
        <!-- c:expenses/ -->

</aura:application>

这是怎么回事通过包含Lightning Experience和Salesforce应用程序提供的Lightning Design System样式,extends =“force:slds”属性将激活此应用程序中的SLDS。但请注意,这个线束应用程序只是一个包装,一个外壳。真正的应用程序是费用组件,我们还没有创建。 (这是<! – c:expenses / – >部分;它被注释掉了,因为我们不能保存我们的应用程序直到费用组件实际存在。)

通过包装器应用程序,我们的组件使用extends =“force:slds”机制从这个应用程序运行时访问SLDS。当他们在Lightning Experience或Salesforce应用程序中运行时,无需更改代码,他们就会使用该容器自动包含SLDS。

在这种情况下,这相当于同样的事情。但是,这个使用外部线束应用程序来设置上下文的概念,以便真正的应用程序不需要担心上下文的差异,并不仅限于样式资源。你可以用它来提供替换事件处理程序,例如…虽然这已经超越了我们自己。在我们尝试飞行之前,我们学习走路吧!

应用程序组件的费用

下一步是创建我们的费用应用程序的顶级组件。 (请记住,尽管我们将其称为“应用程序”,但它实际上只是另一个Lightning组件)。在开发者控制台中,创建一个名为“费用”的新Lightning组件,并使用以下代码替换默认标记。

<aura:component>

    <!-- PAGE HEADER -->
    <lightning:layout class="slds-page-header slds-page-header--object-home">
        <lightning:layoutItem>
            <lightning:icon iconName="standard:scan_card" alternativeText="My Expenses"/>
        </lightning:layoutItem>
        <lightning:layoutItem padding="horizontal-small">
            <div class="page-section page-header">
                <h1 class="slds-text-heading--label">Expenses</h1>
                <h2 class="slds-text-heading--medium">My Expenses</h2>
            </div>
        </lightning:layoutItem>
    </lightning:layout>
    <!-- / PAGE HEADER -->

    <!-- 新的费用表格 -->
    <lightning:layout>
        <lightning:layoutItem padding="around-small" size="6">

        <!-- [[ 费用表单在这里]] -->

        </lightning:layoutItem>
    </lightning:layout>
    <!-- / NEW EXPENSE FORM -->

</aura:component>
我们在这里创建的是使用由<lightning:layout>和<lightning:layout>组件提供的网格布局的页眉。 size =“6”会创建一个宽度为50%(或12的6)的<div>容器。您可能已经注意到,闪电名称空间中的组件与Lightning Experience和Salesforce应用程序中的组件类似。除按钮和布局之外,您还可以在此名称空间中找到许多其他有用的组件,这些组件可与SLDS样式开箱即用。

注意

注意<lightning:icon>标签?这个组件呈现你喜欢的SLDS图标。你不得不创建一个帮助组件来显示SLDS图标的日子已经一去不复返了。

现在,您可以在实际的.app中取消注释<c:expenses />标记,并打开现在只是一个空壳的预览。你应该看到像下面这样的东西。

Basic My Expenses form

现在还不是很多,但是看到SLDS造型已经有了效果,这真是令人兴奋。请记住,我们不会解释大部分SLDS标记,但我们将在标记中包含注释。你可以看到我们如何为应用程序创建标题,并开始获得这个想法。

新的费用表格

在我们开始表格之前,我们先来确认一下:我们要做的只是暂时的。记住所有的谈话谈话谈论分解你的应用程序分成更小的组件,然后从那里建立?我们现在还没有这样做 – 还没有 – 坦率地说,这有点作弊。

但是,这样做会使代码不能太复杂太快。我们这样做,所以我们可以一次集中一堂课。而且,对于你自己来说,这不是一个坏的方法:在一个组件内部构建,直到它变得太忙,然后重构并分解成更小的子组件。只要你记得重构!

好,</ preaching>。在费用组件中,将<! – [[费用表单转到此处]] – >注释替换为添加费用表单的以下代码。

    <!-- 创建新的费用 -->
    <div aria-labelledby="newexpenseform">

        <!-- BOXED AREA -->
        <fieldset class="slds-box slds-theme--default slds-container--small">

        <legend id="newexpenseform" class="slds-text-heading--small 
          slds-p-vertical--medium">
          Add Expense
        </legend>
  
        <!-- 创建新的费用表格 -->
        <form class="slds-form--stacked">          
            <lightning:input aura:id="expenseform" label="Expense Name"
                             name="expensename"
                             value="{!v.newExpense.Name}"
                             required="true"/> 
            <lightning:input type="number" aura:id="expenseform" label="Amount"
                             name="expenseamount"
                             min="0.1"
                             formatter="currency"
                             step="0.01"
                             value="{!v.newExpense.Amount__c}"
                             messageWhenRangeUnderflow="Enter an amount that's at least $0.10."/>
            <lightning:input aura:id="expenseform" label="Client"
                             name="expenseclient"
                             value="{!v.newExpense.Client__c}"
                             placeholder="ABC Co."/>
            <lightning:input type="date" aura:id="expenseform" label="Expense Date"
                             name="expensedate"
                             value="{!v.newExpense.Date__c}"/>
            <lightning:input type="checkbox" aura:id="expenseform" label="Reimbursed?"  
                             name="expreimbursed"
                             checked="{!v.newExpense.Reimbursed__c}"/>
            <lightning:button label="Create Expense" 
                              class="slds-m-top--medium"
                              variant="brand"
                              onclick="{!c.clickCreate}"/>
        </form>
        <!-- / 创建新的费用表单-->
  
      </fieldset>
      <!-- / BOXED AREA -->

    </div>
    <!-- / 创建新的费用 -->
这看起来像很多代码要立即把握。不是。当你剥离SLDS标记和类时,这个表格归结为一系列输入字段和一个表单提交按钮。

这是由此产生的形式。

New Expense form

注意

<lightning:input>是输入字段的瑞士军刀,融入了SLDS造型的优点。每当你发现自己到达<ui:input>组件变种(如<ui:inputText>,<ui:inputNumber>等)时使用它。 ui命名空间中的组件不具有SLDS样式,并且被认为是遗留组件。

首先,请注意,我们正在使用特定的数据类型创建<lightning:input>组件的多个实例。也就是说,您不希望使用type =“date”和日期字段,等等。有一系列不同的类型,远远超出了指定的类型,最好将组件类型与数据类型相匹配。如果您不指定类型,则默认为文本。原因可能不是很明显,但它会是当你在手机上试用这个应用程序特定的组件可以提供最适合的形式因素的输入小部件。例如,日期选择器针对鼠标或指尖进行了优化,具体取决于您访问的位置。

接下来,请注意,每个输入组件都在其上设置了标签,并且标签文本自动显示在输入栏旁边。还有一些我们以前没见过的属性:required,placeholder,type,min和step。这些属性中的大多数与HTML对应类似。例如,min指定输入的最小值。如果你不能猜出这些是什么,你可以在Lightning Components开发者指南中找到它们。 (我们会回到那个欺骗性的要求。)

接下来,在每个标签上设置一个aura:id属性。那个有什么用途?它在添加的每个标签上设置一个(本地)唯一的ID,该ID是如何从表单字段中读取值的。在这个例子中,所有的字段共享相同的ID,这样我们就可以将它们作为一个数组来访问,用于字段验证。我们将很快考虑如何做到这一点。

 

Salesforce对象的属性(sObject)

但首先,我们需要看看值属性。每个标签都有一个值,设置为一个表达式。例如,{!v.newExpense.Amount__c}。从表达的格式,你应该能够推断出一些东西。

  • v表示这是视图值提供程序的属性。这意味着这是组件上的一个属性。 (我们还没有创建。)
  • 基于点符号,你可以知道newExpense是某种结构化的数据类型。也就是说,newExpense本身具有属性。还是……字段?
  • 从大多数属性名称末尾的“__c”中,您可以猜测这些映射回自定义字段,最有可能在费用自定义对象上。
  • 所以,newExpense可能是一个费用对象!

很酷,我们还没有讨论这个呢!这里是实际的属性定义,您应该在打开<aura:component>标签之后添加到组件顶部。

    <aura:attribute name="newExpense" type="Expense__c"
         default="{ 'sobjectType': 'Expense__c',
                        'Name': '',
                        'Amount__c': 0,
                        'Client__c': '',
                        'Date__c': '',
                        'Reimbursed__c': false }"/>

这里发生的事情其实很简单。您已经知道的名称属性。毫无疑问,这种类型是我们自定义对象的API名称。到现在为止还挺好。

默认属性不是新的,但其值的格式是。但是不要太难把握。这是一个sObject的JSON表示,指定对象的类型(同样是API名称),以及默认设置的每个字段的值。在这种情况下,我们基本上把所有东西都设置为一个空值的表示。

这就是大部分你需要了解的关于sObject的知识!从这里开始,Lightning组件框架将允许您使用JavaScript和标记来处理newExpense,就像Salesforce中的记录 – 即使我们尚未从Salesforce中加载它!

在一个Action Handler中处理表单提交

所以我们有一个表格。现在,如果您填写并点击按钮来创建新的费用,会发生什么?除非你已经提前创建了它,否则你将会得到关于缺少控制器操作的另一个错误。这是因为控制器和<lightning:button>上指定的操作处理程序都没有被创建。

在Developer Console中,单击费用组件的CONTROLLER按钮以创建控制器资源。然后用下面的代码替换默认的代码。

({
    clickCreate: function(component, event, helper) {
        var validExpense = component.find('expenseform').reduce(function (validSoFar, inputCmp) {
            // 显示无效字段的错误消息
            inputCmp.showHelpMessageIfInvalid();
            return validSoFar && inputCmp.get('v.validity').valid;
        }, true);
        // 如果我们通过错误检查,做一些真正的工作
        if(validExpense){
            // Create the new expense
            var newExpense = component.get("v.newExpense");
            console.log("Create expense: " + JSON.stringify(newExpense));
            helper.createExpense(component, newExpense);
        }
    }
})
好的,这是全新的,所以我们仔细看看。首先,我们注意到,这个动作处理函数基本上分为三个部分,或者是步骤:
  1. 设置
  2. 处理表单值
  3. 如果没有错误,请做一些事情

这种结构对您来说可能是熟悉的,因为这是在Web应用程序中处理用户输入的基本方法。让我们看看每个步骤,看看他们如何在闪电组件。

对于设置,我们所做的只是初始化错误检查的状态。这是一个简单的标志,这是一个有效的开支?每次调用clickCreate操作处理程序时,我们都会假设费用数据正常,然后在发现问题时使其无效。下面是validExpense标志的简要说明,初始值设置为true。

  • component.find(‘expenseform’) 获取需要验证的<lightning:input>字段数组的引用。如果ID是唯一的,则引用返回组件。在这种情况下,ID不是唯一的,引用返回一个组件数组。
  • JavaScript reduce()方法将数组减少为由validSoFar捕获的单个值,该值保持为真,直到找到无效字段,将validSoFar更改为false。无效字段可以是空的必填字段,具有低于指定最小数字的字段的字段等等。
  • inputCmp.get(‘v.validity’).valid返回数组当前输入字段的有效性。
  • inputCmp.showHelpMessageIfInvalid() 显示无效字段的错误消息。 <lightning:input>提供了默认的错误消息,可以通过messageWhenRangeUnderflow等属性进行自定义,您可以在费用表单中看到该消息。

让我们进入一些有趣的细节。回到helloMessageInteractive,我们没有使用find()来找出被点击的按钮的标签文本。这是因为我们不需要。我们可以通过使用event.getSource()将其从事件参数中拉出来直接获得对该按钮的引用。你并不总是有这种奢侈;事实上,从用户输入中获得的所有内容都只来自事件,这是非常罕见的。

所以,当你的控制器需要一种方法来获取子组件时,首先在标记中设置该组件上的aura:id,然后使用component.find(theId)在运行时获取组件的引用。

注意

component.find()只允许你访问直接的子组件。在组件层次结构中漫游并读取或更改内容不是一种神奇的方式。请记住,组件应该是独立的,或者与…进行交流,那么我们就可以做到这一点。

使用<lightning:input>进行验证将利用底层HTML输入元素的处理能力来处理表单值,所以在大多数情况下您不需要这样做。需要验证一个电话号码?使用type =“tel”并使用正则表达式定义模式属性。需要验证一个百分比值?在formatter =“percent”中使用type =“number”。需要验证别的东西吗?让<lightning:input>为你做重担。

当验证失败时,事情会再次变得有趣。当用户输入无效的输入时,我们希望发生两件事情:

  1. 不要试图创造费用。
  2. 显示有用的错误消息。

首先,当inputCmp.get(’v.validity’)。valid引用的字段有效性计算结果为false时,我们将validExpense标志设置为false。第二,我们利用内置的验证错误或为错误提供自定义消息。在费用表单中,如果该字段为空,并且您尝试提交表单,则所需的名称字段将显示“完成此字段”。但是,您可以通过指定messageWhenValueMissing =“您忘了我吗?”来提供您自己的自定义消息。

相反,如果该字段通过验证,则validExpense标志的计算结果为true,并且不显示任何错误。

就这一点而言,我们正在处理表单提交的第三步:实际上是在创造费用!正如您所看到的,为了做好准备,我们从component属性中获取完整的newExpense对象:component.get(“v.newExpense”)。这给我们一个单一的变量,我们可以用它来创建一个新的费用记录。

但是,在我们做到这一点之前,您需要考虑一个问题:为什么我们不从NewExpense中提取表单值呢?在动作处理程序的开始处获取一次结构化变量,然后访问它的属性,而不是一系列find()。get()调用?

原因很简单:因为我们需要对各个字段的引用来调用showHelpMessageIfInvalid()。验证原始表单数据也是一个很好的做法。您的验证逻辑不知道在newExpense对象内可能发生什么类型的处理。

创建新的费用

记得早些时候我们说过把费用表单放在主要的组件上有点作弊了吗?那么,下一节没有得到“一点”限定符。我们在这里做的只是避免真正创造记录的复杂性。而现在我们正在避免它,因为那是整个下一个单位。所以,让我们用简单的东西来包装这个,但是这仍然给我们一些重要的概念。

首先,我们创建一个“存储”新开支的地方。我们将简单地创建一个本地支出数组来保存它们。在费用组件标记的顶部,在newExpense属性之前,添加一个新的费用属性,该属性将包含一组费用对象。

    <aura:attribute name="expenses" type="Expense__c[]"/>

我们所要做的就是更新费用数组。事实证明,这很容易(以我们形式的作弊者的形式),并且说明了另一个重要的概念。

在我们的控制器中,我们隐藏了在这个函数调用后面实际创建新开销的工作:helper.createExpense(component,newExpense)。在软件开发中,“隐藏”这个词是抽象的。而我们正在使用一种叫做助手的方式来抽离我们的作弊行为。

我们之前简要地讨论过帮助者,而我们不打算介绍这个模块中帮助者的高级细节。现在,让我们说三件关于帮手的事情:

  • 组件的帮助程序是将代码在几个不同的操作处理程序之间共享的合适位置。
  • 组件的帮助程序是放置复杂的处理细节的好地方,所以您的操作处理程序的逻辑保持清晰和精简。
  • 助手功能可以有任何功能签名。也就是说,它们不受控制器中动作处理程序的限制。 (这是为什么呢?因为你直接从你的代码中调用helper函数,相反,框架通过框架运行时调用动作处理函数。)这是一个约定和推荐的做法,总是提供组件作为帮助函数的第一个参数。

好吧,让我们继续吧。在开发人员控制台中,单击费用组件的HELPER按钮以创建关联的助手资源,然后将示例代码替换为以下内容。

({
    createExpense: function(component, expense) {
        var theExpenses = component.get("v.expenses");
 
        //将费用复制到一个新的对象这是一个令人讨厌的,暂时的黑客
        var newExpense = JSON.parse(JSON.stringify(expense));
 
        theExpenses.push(newExpense);
        component.set("v.expenses", theExpenses);
    }
})
目前,忽略令人厌恶的黑客部分。其他三行代码说明了我们以前见过的一个常见模式,您将一遍又一遍地使用它:get-process-set。首先,我们从费用属性中获得一系列费用。然后我们添加新的费用“记录”。然后我们用更改的数组更新(设置)费用属性。

参考不是收集

这里有什么新东西是第一次,我们正在更新一个集合,一个数组。如果你是一个有经验的程序员,你可能想知道:“为什么我需要set()在这里?

也就是说,component.get(“v.expenses”)获取存储在组件属性中的数组的引用。 component.set(“v.expenses”,theExpenses)只是将组件属性设置为相同的引用。当然,在这之间,数组的内容已被添加到,但容器是相同的:数组的引用实际上并没有改变!那么,为什么更新呢?

如果您无法理解这意味着什么,请在关键语句之前和之后添加两条日志语句,并将这些Expenses的内容转储到控制台。

console.log("创建之前的开支: " + JSON.stringify(theExpenses));
theExpenses.push(newExpense);
component.set("v.expenses", theExpenses);
console.log("创建后的费用: " + JSON.stringify(theExpenses));

重新加载并运行应用程序,添加至少两个费用,并查看费用的结构。现在注释掉component.set()行,并再次执行。

什么…? component.set()根本不影响Expenses!但!但!但?它究竟做了什么?!?

你问这个问题绝对正确。答案是:魔法!

什么component.set()在这里没有更新费用属性的值。它会触发费用属性已更改的通知。

结果是,在您的应用程序中的任何位置您已经引用了表达式中的费用属性,该表达式的值将更新,并且该更新会在所有使用费用属性的地方级联。而且他们都根据新的内容更新为放弃。这一切都发生在幕后,由Lightning Components框架处理,作为使用{!v.expenses}时发生的自动布线的一部分。总之,魔法。

总而言之,如果这是纯JavaScript,则不需要component.set()。为了触发内置在Lightning组件中的基础效应,您可以这样做。如果你编写了一些控制器或者帮助代码,测试一下,没有任何反应,确保你已经完成了所需的component.set()。

“恶心的黑客”围绕着类似的问题与参考。要查看该问题,请更改该行以除去两个JSON调用,然后测试该应用程序。你会很快看到问题是什么。我们将在下一个单元中删除它,所以不会进一步解释。

显示费用列表

所以,对于所有讨论“神奇地”更新任何使用{!v.expenses}的东西,猜猜看是什么。没有别的使用它,但。我们来解决这个问题。

在开发人员控制台中,创建一个名为expenseItem的新Lightning组件,并使用以下代替默认标记。如果您已经创建了费用项目,只需更新标记。您已经看到了之前访问费用记录中的字段的表达式。该版本包含SLDS标记,使其更加时尚。另外,使用{!v.expense.Reimbursed__c? ‘slds-theme-success’:”}当费用已经报销时,表达式在容器上设置绿色。

<aura:component>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="formatdate" type="Date"/>
    <aura:attribute name="expense" type="Expense__c"/>


    <lightning:card title="{!v.expense.Name}" iconName="standard:scan_card"
                    class="{!v.expense.Reimbursed__c ?
                           'slds-theme--success' : ''}">
        <aura:set attribute="footer">
            <p>Date: <lightning:formattedDateTime value="{!v.formatdate}"/></p>
            <p class="slds-text-title"><lightning:relativeDateTime value="{!v.formatdate}"/></p>
        </aura:set>
        <p class="slds-text-heading--medium slds-p-horizontal--small">
           Amount: <lightning:formattedNumber value="{!v.expense.Amount__c}" style="currency"/>
        </p>
        <p class="slds-p-horizontal--small">
            Client: {!v.expense.Client__c}
        </p>
        <p>
            <lightning:input type="toggle" 
                             label="Reimbursed?"
                             name="reimbursed"
                             class="slds-p-around--small"
                             checked="{!v.expense.Reimbursed__c}"
                             messageToggleActive="Yes"
                             messageToggleInactive="No"
                             onchange="{!c.clickReimbursed}"/>
        </p>
    </lightning:card>
</aura:component>
接下来,用下面的代码创建一个客户端控制器expenseItemController.js。在这里,我们将稍后由服务器返回的日期转换为JavaScript Date对象,以便通过<lightning:formattedDateTime>和<lightning:relativeDateTime>正确显示。此转换在组件初始化期间处理,由<aura:handler>标签捕获。这是处理初始化事件的有用方法,稍后我们将在从Salesforce加载数据时再次使用它。
({
    doInit : function(component, event, helper) {
        var mydate = component.get("v.expense.Date__c");
        if(mydate){
            component.set("v.formatdate", new Date(mydate));
        }
    },
})
在开发者控制台中,创建一个名为expensesList的新Lightning组件,并使用以下代码替换默认标记。
<aura:component>

    <aura:attribute name="expenses" type="Expense__c[]"/>

    <lightning:card title="Expenses">
        <p class="slds-p-horizontal--small">
            <aura:iteration items="{!v.expenses}" var="expense">
                <c:expenseItem expense="{!expense}"/>
            </aura:iteration>
        </p>
    </lightning:card>

</aura:component>

这里没有太多新东西。这是一个显示费用列表的组件。它有一个属性费用,这是一个费用数组(Expense__c)对象。它使用<aura:iteration>为每个这些费用对象创建一个<c:expenseItem>。正如我们所指出的那样,总体效果是显示费用清单。到现在为止还挺好。

现在将费用清单组件添加到费用组件的末尾。在expenses.cmp中的结尾</ aura:component>标记之前添加它。

<c:expensesList expenses="{!v.expenses}"/>

如果您重新加载应用程序,则会在窗体下方看到“费用”部分。 (视觉上不太对,但现在已经足够了。)

我们刚刚做了什么?我们添加了费用列表组件,并将主费用属性传递给它。那么现在费用列表的费用实例和费用组件所具有的费用实例是一样的。它们是对相同记录数组的引用,并且通过Lightning组件的魔法,当更新主要费用数组时,费用列表组件将“注意到”并重新列出其列表。给它一个旋转!

呼!这是一个很长的单位,它需要一个休息时间。请站起来走走几分钟。

然后回来,我们会告诉你如何为真正的节省新的开支。

Lightning-组件(5)操作

学习目标

完成本单元后,您将能够:

  • 创建一个客户端控制器来处理用户操作。
  • 从组件属性读取值。
  • 从组件中的用户界面控件读取值。
  • 用JavaScript编写控制器代码来改变用户界面。

处理与控制器的行动

到目前为止,我们只使用XML风格的标记。到目前为止,让组件的输出更改的唯一方法是更改​​该标记。到目前为止,我们的组件没有对用户输入做出反应。到目前为止,我们还没有编写任何JavaScript。

这个单位的所有变化。

为了开始,我们来看一个非常简单的组件,想象一下为了处理它的简单行为需要做些什么。

Message of the day: You look nice today button, Today is going to be a great day button

这是helloMessageInteractive,很难想象一个简单的组件“做些什么”。它是一些静态文本,一个(当前空白)消息和两个按钮。代码如下:

<aura:component>
 
    <aura:attribute name="message" type="String"/>
 
    <p>Message of the day: {!v.message}</p>
 
    <div>
        <lightning:button label="You look nice today."
            onclick="{!c.handleClick}"/>
 
        <lightning:button label="Today is going to be a great day!"
            onclick="{!c.handleClick}"/>
    </div>
 
</aura:component>

这应该看起来很熟悉。我们真正做的是将两个<lightning:button>组件添加到helloMessage。当你点击一个按钮,当天的消息被更新。

那么,还不完全。如果您已经输入了代码并自己尝试过,那么您已经注意到,当您单击其中一个按钮时,您会收到错误消息。

There is a problem

我们将首先承认,并不是每一个你会在Lightning Components中看到的错误信息都像你所希望的那样有帮助。但是这个是!它说没有名为“handleClick”的控制器操作。 “handleClick”从哪里来?它来自我们分配给两个<lightning:button>标签中每一个的onclick属性的表达式:

onclick="{!c.handleClick}"

鉴于这是一个按钮,你可能会猜测onclick属性是如何为点击按钮分配一个行为。但是我们分配了什么?表达式{!c.handleClick},可能有点神秘。

这其实很简单。就像前面的v.message表达式一样,c.handleClick是一个值提供者c,带有一个属性handleClick。 c是组件客户端控制器的值提供者,handleClick是在该控制器中定义的函数。所以,{!c.handleClick}是对组件控制器中的一个动作处理器的引用。

c.handleClick: c is a value provider for the component controller, with the property handleClick, a function defined in that controller

Uh, 什么是控制器?

哎呦!控制器基本上是一组代码,用于定义应用程序在“事情发生”时的行为,其中“事物”是指用户输入,定时器和其他事件,数据更新等等。如果你在任何数量的开发者网站上查找“模型 – 视图 – 控制器”,你会得到不同的定义。就我们的目的而言,对于Lightning组件,控制器是组件包中的一个资源,该组件包含该组件的操作处理程序。而动作处理程序只是具有特定功能签名的JavaScript函数。

超越基础

我们在这个单元中谈了很多关于控制器的知识,而且我们知道这个组件本身就是一个视图。我们甚至提到了MVC或模型 – 视图 – 控制器的设计模式,这在Web应用程序框架中很常见。闪电组件建立在MVC模式上吗?

总之,没有。可以肯定的是有相似之处,但是说Lightning组件是View-Controller-Controller-Model或者View-Controller-Controller-Database可能更为正确。

为什么“控制器”在这个模式名称翻倍?因为在与Salesforce交互时,除了我们在本单元中使用的客户端控制器外,您的组件还将拥有服务器端控制器。这个双控制器设计是Lightning组件和MVC之间的主要区别。

“模型”和“数据库”有什么区别?在传统的MVC中,模型是底层数据存储(通常是关系数据库)和其他应用程序之间的程序化抽象(通常是一个类)。在Lightning组件中,没有Apex类直接位于@AuraEnabled控制器方法和DML操作之间。但是再一次,sObjects已经是您的Apex代码和底层存储层之间的抽象了。您可以添加计算字段,验证逻辑,甚至以触发器的形式添加完全的编程行为。那么,这是一个数据库还是一个模型?我们说po-TAY-tow,但是如果你想用po-TAH-tow去,那真是太酷了。

困惑?激动吗?我们将在后面的单元中对服务器端控制器的细节进行分类。

让我们更详细地看看helloMessageInteractive控制器,并解释更具体一些。

({
    handleClick: function(component, event, helper) {
        var btnClicked = event.getSource();         // the button
        var btnMessage = btnClicked.get("v.label"); // the button's label
        component.set("v.message", btnMessage);     // update our message
    }
})
控制器资源有一个有趣的格式。它们是包含名称 – 值对映射的JavaScript对象,其中名称是操作处理程序的名称,值是函数定义。


行动处理程序

名称 – 值对和特定函数签名的组合是一个动作处理程序。您将会听到或看到交替使用的术语“动作处理程序”,“控制器动作”和“控制器功能”,而且大部分都是正确的。他们几乎总是提到同样的事情。 (我们不会担心这个模块中的异常。)

不要太担心控制器资源的特殊格式。当您在开发者控制台中点击CONTROLLER按钮时,您将获得一个已添加示例操作处理程序的控制器资源。一个技巧是 – 如果你忘记了,你会得到语法错误 – 你需要在操作处理程序之间加逗号。这只是基本的JavaScript语法,我们稍后会看到具体细节。

实际的handleClick函数只有四行代码,但起初似乎很难理解。在高层次上,这很简单:点击按钮时,其操作处理程序被调用(1)。在动作处理程序中,控制器获取被单击的按钮,将标签文本从中拉出,然后将组件的消息属性设置为该文本(2)。并且当天的消息被更新(3)。你今天看起来不错!

In the action handler, the controller gets the clicked button text, then sets the component message attribute

很简单,对吧?好…

因为这是非常重要的,让我们逐行分解。

handleClick: function(component, event, helper) {

操作处理程序名称,后跟一个匿名函数声明。这里重要的是函数签名。虽然这不是技术上的要求,但您应该始终声明您的控制器功能采取这三个参数。现在我们将更多地讨论它们,但是现在这些参数代表:

  • component—组件。在这种情况下,它是helloMessageInteractive。
  • event—导致操作处理程序被调用的事件。
  • helper—组件的助手,另一个可重用函数的JavaScript资源。
    var btnClicked = event.getSource();         // the button
请记住,handleClick已连接到我们的<lightning:button>标记及其onclick属性。那么,事件就是有人点击按钮。在这个事件里面,它有一个源的概念,即产生事件的东西,也就是按钮本身。所以,调用event.getSource()让我们引用被点击的特定<lightning:button>。
    var btnMessage = btnClicked.get("v.label"); // the button's label

我们现在做什么,我们有一个参考按钮?我们在里面查看它的标签,它在组件标记中的<lightning:button>上设置。例如,<lightning:button label =“今天看起来不错。” …>。

让我们再想一想。我们没有在我们面前定义<lightning:button>,但标签只是另一个属性,非常类似于我们添加到helloMessageInteractive的消息属性。您可以在任何组件上调用get(),并以v.attributeName的格式提供您想要检索的属性的名称。结果是属性值。

请注意,就像在组件标记中一样,v代表视图,组件本身 – 但在这种情况下,它是<lightning:button>子组件,而不是helloMessageInteractive!想想这样。 btnClicked.get(“v.label”)在任何组件btnClicked的肩膀上点击并且说“嘿,给我v.label”。该组件认为“v就是我”,在自己的内部查找,并返回其标签属性的值。

所以,现在我们有一个从按钮中检索的文本字符串,我们只剩下一步:将我们的消息属性更改为新的消息文本。毫不奇怪,就像get()从组件中读取值一样,set()写入一个值。

    component.set("v.message", btnMessage);     // update our message
但是,让我们注意一个重要的区别。我们在btnClicked上调用了get(),这是helloMessageInteractive中的<lightning:button>。我们在组件上调用set() – helloMessageInteractive组件本身。实际上,您将在每个创建的组件中重复这种模式:从子组件获取值,可能会进行一些处理,并在组件中设置值。


闪电组件视图 – 控制器编程模型

好的,检查一下时间。这是有道理的吗?当然?如果你这么想,确保你已经使用前面的代码创建了helloMessageInteractive组件。它是一个组件,复制/粘贴代码需要两分钟的时间,但能够使用它是理解处理操作的关键。

你在这里做的事情看起来很简单,因为它不是很多代码行。但是这些代码行说明了使用Lightning组件构建应用程序的一些基本概念。

您可以将组件连接到动作处理程序上,将它们连接起来。将helloMessageInteractive想象成一个简单的电路。有开关,还有灯泡。 (Lightning组件框架提供电源。)本身,一个开关可能会发出一个很好的咔哒声,但是直到你连接它,它不是功能。你可以有最时尚的爱迪生风格的灯泡,但直到你把它连接起来,它不会照亮任何东西。

Lightning组件也是如此。就在前面,我们说组件捆绑中的不同资源是相互“自动连接”的。这是真的:接线采取v和c值提供商的形式。它们会自动创建并在您的组件中可用,因此您的控制器可以引用组件,反之亦然。但是这个自动接线只发生在组件.cmp资源和控制器.js资源之间的高层次 – helloMessageInteractive中。这是下图中的绿色箭头。

helloMessageInteractive and its controller are auto-wired

将一个特定的<lightning:button>组件连接到一个特定的动作处理程序 – 也就是将产生事件的东西(比如按钮)连接到处理事件的东西,比如一个特定的控制器功能 – 这是你需要的连线自己做。其实,你只是做了你自己!这些是完成工作电路所需的红色箭头。

将{!c.handleClick}添加到<lightning:button>组件(1)的onclick属性,将其连接到特定的操作处理程序。调用component.set(“v.message”,newMessage)(2)将该操作处理程序的结果连接到组件的消息属性。它本身连接到{!v.message}表达式。

您可以进一步将onclick事件视为沿着您创建的电路流动的电子。如果你还没有创建一个完整的电路,事件不会发生,没有任何反应。当你开始编写自己的组件时,记住这一点。你有一个完整的电路?你确定?如果有疑问,有时候可以在白板或纸上画出全部草图,并确认每个连接。

你会把组件,事件和处理程序连接在一起,所以你经常会感觉像电工。 (或者,考虑到框架的名字,也许是本·富兰克林。)把事情联系在一起是Lightning组件的基本编程模型。

所以,我们再做一些。毕竟,练习是完美的。

函数链接,重新布线和简单调试

我们的handleClick的第一个版本是三行代码,因为我们将get-process-set模式中的每一步分解成单独的行。你可以使用一些叫做函数链的东西把它们折成较少的行。由于您可能会在其他Lightning组件代码中看到这一点,因此我们可以让它自己旋转。在handleClick之后,将以下附加代码添加到helloMessageInteractive控制器中。

    handleClick2: function(component, event, helper) {
        var newMessage = event.getSource().get("v.label");
        component.set("v.message", newMessage);
    },

    handleClick3: function(component, event, helper) {
        component.set("v.message", event.getSource().get("v.label"));
    }

Whoopsie!尝试保存时是否出现语法错误?当我们说你需要在你的动作处理程序之间添加逗号的时候,记得早些时候?这是这个问题。在handleClick的最后一个大括号(“}”)后面添加一个逗号,就像你在前面的代码片段的handleClick2的末尾可以看到的那样。

这些动作处理程序与handleClick完全相同,使用更少的代码行。他们通过跳过中间变量来做到这一点,通常通过直接将“链接”链接到下一个函数调用,通过将该调用添加到前一个函数调用的结尾,以句点分隔。 (在查看handleClick和handleClick2之间的差异时,这个概念是最清楚的。)

你喜欢哪种风格是个人品味的问题,也许你的组织的编码风格。你的卑微的作者喜欢handleClick2,分离得到和设置,但不打扰与按钮的变量,我们只需要它的标签文本。

当然,通过将onclick属性设置为{!c.handleClick2}或{!c.handleClick3},您无法验证新的动作处理程序是否正常工作,直到连线<lightning:button>才能使用其中的一个。把它看作是从一个灯泡断开电线,然后把它们连接到另一个灯泡。就这么简单!

在这一点上,你重新加载应用程序,点击一个重新布线的按钮,…呃,这是相同的设计,不是吗?我们甚至可以告诉哪个动作处理程序被调用?

有时候简单是最好的。让我们添加一些记录到一个动作处理函数:

    handleClick2: function(component, event, helper) {
        var newMessage = event.getSource().get("v.label");
        console.log("handleClick2: Message: " + newMessage);
        component.set("v.message", newMessage);
    },

现在,如果连接一个<lightning:button>来处理Click2,则只要您点击它,您就会在浏览器的JavaScript控制台中看到一条日志消息。

是的,有更复杂的调试工具,但打印到控制台的东西是一个悠久的调试技术。如果要输出某种类型的对象,请使用JSON.stringify(yourObject)将其包装,以获取更多有用的细节。当你快速浏览时,console.log()是你的朋友。

我们不会在这里介绍更复杂的调试工具和技术,但请参阅参考资料中的一些精彩的工具和说明。

好的,helloMessageInteractive很简单,并且有一个硬编码(和无情的积极)的态度。在下一个单元中,我们将处理更复杂的事情,并学习如何捕捉真实的用户输入。而且,由于现实世界中的人们并不总是如此积极,我们也将学习如何验证他们的输入。

Lightning-组件(4)属性

学习目标

完成本单元后,您将能够:

  • 在组件上定义属性,并将属性值传递给嵌套组件。
  • 理解组件定义和组件实例之间的区别,并创建组件的多个实例。
  • 创建基本表达式来显示更改和计算的值。
  • 为动态输出创建条件表达式。

组件属性

到目前为止,虽然我们已经创建了几个组件,并且在构建应用程序方面学到了一些(高层次的),但是我们编写的代码并没有做比HTML更简单的工作。也就是说,我们创建的两个组件输出相同的静态文本,不管我们做什么。你可以把他们放在同一个屏幕上,他们总是会说同样的事情。

无聊。

要改变这一点,我们需要学习两件事情。首先,我们需要学习如何使组件在创建时接受输入。也就是说,我们需要在组件上设置值。我们使用属性来做这件事。

(我们需要学习的第二件事是如何实际使用这些值来改变组件的行为和输出,在我们弄清楚属性之后,我们会这样做)。

组件上的属性就像对象中的实例变量一样。这是一种保存更改值的方法,也是一种命名这些值占位符的方法。例如,假设我们想编写一个打印自定义消息的helloMessage组件。我们可以想象为这个组件添加一个消息属性来定制它的输出。然后,我们可以在将组件添加到我们的应用程序时设置该消息,如下所示。

<aura:component>
	  
    <c:helloMessage message="You look nice today."/>
	    
</aura:component>

您需要将其添加到您的组织中,因为我们将继续使用它。但是,如果你现在做,你会得到一个错误。这是为什么?因为helloMessage组件还不存在。闪电组件在您编写代码时验证您的代码。如果你试图保存它知道是无效的代码,例如引用一个不存在的组件,你会得到一个错误。所以,让我们先弄清楚如何创建helloMessage。
您可以在创建组件时设置组件的属性,就像我们在前面的示例中所做的那样。您还可以在组件生命周期的过程中更改它们,以响应用户采取的操作或其他地方发生的事件等等。你当然可以用许多不同的方式读取和使用属性值。当我们到达表达式时,我们会看看那些。

现在,我们来看看如何定义组件的属性。使用<aura:attribute>标记定义属性,该标记需要名称和类型属性的值,并接受这些可选属性:default,description,required。

哇,这是在句子中使用“属性”的很多不同的方法!在这里很容易混淆,因为我们有三个不同的名称相似的概念。让我们具体。

  1. 组件属性是可以存储值的地方。在前面的例子中,helloMessage组件有一个名为message的组件属性。大多数时候我们正在讨论组件属性。
  2. 您可以使用<aura:attribute>标签定义组件属性。我们稍后会看到一个例子。我们来调用这些属性定义。
  3. 使用它时,<aura:attribute>标签本身就具有属性! 😖也就是说,使用<aura:attribute>标记定义组件属性时,可以在<aura:attribute>上设置属性,以指定要定义的组件属性的“形状”。 😡等等,让我们再试一次:通过设置属性定义的属性来添加一个组件属性定义。 component组件属性的属性定义是否具有属性? 😴
    这就是为什么作家😱。我们试着用一些代码来解决这个术语问题。 😄

下面是我们的helloMessage组件的开始:

<aura:component>

    <aura:attribute name="message" type="String"/>

    <p>Hello! [ message goes here, soon ]</p>

</aura:component>
helloMessage组件具有一个组件属性,该属性通过设置属性的名称和类型来定义。该属性的名称是消息,一旦我们了解表达式,这就是你如何引用它。它仍然只输出静态文本和HTML,但我们正在接近有用的东西。

👍 ?

我们在这里使用的另一个属性是type,我们已经设置了它,因为它在属性定义中是必需的。它说消息属性包含一个字符串,这是有道理的。我们将详细讨论属性数据类型和属性定义的其他部分,但是首先让我们学习表达式,然后让helloMessage实际上做一些事情。

表达式

不要再让我们迷失,而是让我们按照预期使用helloMessage。

<aura:component>

    <aura:attribute name="message" type="String"/>

    <p>Hello! {!v.message}</p>

</aura:component>
难道是这样的还是什么?

我们使用表达式{!v.message}输出消息的内容。也就是说,这个表达式引用了消息属性。表达式被评估,并解析为当前存储在消息中的文本字符串。这就是表达式输出到组件主体的内容。

嗯…这是什么“表达”?

表达式基本上是一个公式或计算,您将其放在表达式分隔符(“{!”和“}”)中。所以,表达式如下所示:

{!<expression>}

表达式的正式定义有点令人生畏,但让我们看一下,然后解压它:表达式是可以解析为单个值的任何一组字面值,变量,子表达式或运算符。

是的,基本上是一个公式,就像你在计算领域,过滤标准或Visualforce中写的一样。公式或表达式可以包含各种各样的东西。字面值应该是显而易见的;他们是像数字42,或字符串“你好”的东西。变量就像消息属性一样。运算符就像+, – 等等,子表达式基本上意味着你可以使用括号把事物分组在一起。

让我们试试这个,让我们的表情稍微复杂一些。

<aura:component>

    <aura:attribute name="message" type="String"/>

    <p>{!'Hello! ' + v.message}</p>

</aura:component>
我们所做的就是将“Hello”部分从表达式外部的静态文本移动到表达式中的文本文本。请注意,我们使用“+”运算符将两个字符串连接在一起。这可能看起来像一个很小的差异,但移动表达式中的问候语文本可以使用标签,而不是文本文本,这使得更新(和翻译)组件更容易。例如:
{!$Label.c.Greeting + v.message}

你注意到我们对表达式的正式定义有什么遗漏吗? JavaScript函数调用。 Lightning Components标记中的表达式中不能使用JavaScript。

在我们继续之前,关于表情的最后一件事。您可以将它们传递给另一个组件来设置该组件上的值。这是一个将自定义值传递给helloMessage组件的新组件。将值传递给其他组件会覆盖该组件上的值。

<aura:component>
    <aura:attribute name="customMessage" type="String"/>
    <p> <c:helloMessage message="{!v.customMessage}"/> </p>
</aura:component>

.

价值提供者

实际上,我们需要谈谈表情的另一个方面。在前面的例子中,我们用v.message引用了helloMessage组件的消息属性。什么是“v”部分?

v是所谓的价值提供者。价值提供者是分组,封装和访问相关数据的一种方式。价值提供者是一个复杂的话题,所以现在把v想象成一个可供你使用的自动变量。在我们的组件中,v是视图的值提供者,它是helloMessage组件本身。

v给你一个“钩子”来访问组件的消息属性,这就是你如何访问组件的所有属性。

值提供者中的值作为命名属性被访问。要使用值,请使用点(句点)分隔值提供程序和属性名称。例如,v.message,正如我们所见。

当组件的属性是对象或其他结构化数据(即不是原始值)时,使用相同的点符号访问该属性上的值。例如,{!v.account.Id}访问帐户记录的Id字段。对于深度嵌套的对象和属性,继续添加点来遍历结构并访问嵌套的值。

属性数据类型

访问结构化数据是讨论属性的一个很好的部分,特别是关于非基本属性类型。消息是一个字符串,但是有许多不同的属性类型。

  • 原始数据类型,如布尔值,日期,日期时间,十进制,双精度,整数,长或字符串。任何编程语言通常的使用的。
  • 标准和自定义Salesforce对象,例如Account或MyCustomObject__c。
  • 集合,例如List,Map和Set。
  • 自定义Apex类。
  • 特定于框架的类型,如Aura.Component或Aura.Component []。这些比我们在这个模块中会更先进,但是你应该知道它们存在。

这是一个精简的费用项目组件,我们将在稍后填写。它演示了如何为自定义对象定义属性,以及如何访问记录中的字段。

<aura:component>

    <aura:attribute name="expense" type="Expense__c"/>

    <p>Amount:
        <lightning:formattedNumber value="{!v.expense.Amount__c}" style="currency"/>
    </p>
    <p>
        Client: {!v.expense.Client__c}
    </p>
    <p>
        <lightning:input type="toggle"                            
                         label="Reimbursed?"                           
                         name="reimbursed"                         
                         checked="{!v.expense.Reimbursed__c}" />
     </p> 
    <!-- Other markup here -->

</aura:component>
这个组件有一个属性,开销,这是我们在本模块开始时创建的自定义对象。该组件的目的是通过使用{!v.expense.fieldName}表达式引用Expense__c记录中的字段来显示费用的详细信息。我们使用类型=“toggle”的<lightning:input>组件,这是一个切换形式的复选框,以便我们稍后可以更新UI中的值。

其他方面的属性定义

当涉及到您在<aura:attribute>标签上设置的属性时,以下是您需要了解的其余部分。

  • 默认属性定义了默认的属性值。它在引用属性时使用,但尚未设置该属性的值。
  • 必需的属性定义属性是否是必需的。默认值是false。
  • description属性定义了属性及其用法的简要摘要。

为具有复杂数据类型的属性设置默认值可能有些棘手。不过,我们稍后会看到一个例子,所以现在我们只是把你的头抬起来。

乐趣与属性和表达式

为了说明更多关于属性和表达式的概念,让我们用下面的标记创建一个非常愚蠢的组件helloPlayground。

<aura:component>

    <aura:attribute name="messages" type="List"
        default="['You look nice today.',
            'Great weather we\'re having.',
            'How are you?']"/>


    <h1>Hello Playground</h1>

    <p>Silly fun with attributes and expressions.</p>


    <h2>List Items</h2>

    <p><c:helloMessage message="{!v.messages[0]}"/></p>
    <p><c:helloMessage message="{!v.messages[1]}"/></p>
    <p><c:helloMessage message="{!v.messages[2]}"/></p>


    <h2>List Iteration</h2>

    <aura:iteration items="{!v.messages}" var="msg">
        <p><c:helloMessage message="{!msg}"/></p>
    </aura:iteration>


    <h2>Conditional Expressions and Global Value Providers</h2>

    <aura:if isTrue="{!$Browser.isIPhone}">
        <p><c:helloMessage message="{!v.messages[0]}"/></p>
    <aura:set attribute="else">
        <p><c:helloMessage message="{!v.messages[1]}"/></p>
        </aura:set>
    </aura:if>

</aura:component>

现在将helloPlayground组件添加到你的线束应用程序,并看看它是如何运行的!

这里有很多新东西。我们现在不会对它们进行深入的了解,但是你会再次看到所有这些。

首先,helloPlayground有一个属性消息,这是一个复杂的数据类型List。它有一个默认值的列表,这是一个由逗号分隔的三个单引号字符串组成的数组。而且,在“列表项”部分中,您可以看到如何使用索引访问每个字符串。

如果有人用两条消息创建一个<c:helloPlayground>,会发生什么?访问第三个项目将失败,虽然它不会导致崩溃,但可能会有更复杂的组件。

因此,在List Iteration部分中,您可以看到更好的方法来处理列表中的所有项目。 <aura:iteration>组件在其items属性中的每个项目重复其身体一次,所以列表收缩或增长,因为我们有更少或更多的消息。

在“条件表达式”和“全球价值提供商”部分,您可以看到在两种不同可能的输出之间进行选择的方法。这种格式有点尴尬,因为这是标记而不是JavaScript,但是<aura:if>组件允许您例如只在用户具有对该对象的编辑权限时才将编辑按钮添加到页面。

最后,有些不那么明显。在面向对象编程中,类和类的实例是有区别的。组件有一个相似的概念。当您创建.cmp资源时,您正在提供该组件的定义(类)。当你把一个组件标签放到一个.cmp文件中时,你正在创建一个对该组件(的实例)的引用。

我们可以添加具有不同属性的相同组件的多个实例,这并不奇怪。在前面的例子中,当你使用消息的默认值时,你最终会得到8个对<c:helloMessage>组件实例的引用。如果你通过一个更长的名单,你可以结束(多)更多。所有来自我们的一个小组件!

对此,朋友,我们认为你已经准备好了一些真正的工作。

Lightning-组件(3)创建组件

学习目标

完成本单元后,您将能够:

  • 在开发者控制台中创建和编辑Lightning组件包资源。
  • 创建一个“线束”应用程序,用于测试开发中的组件。
  • 执行编辑和重新加载循环以预览开发中的组件。
  • 列出构成Lightning组件包的不同资源。

创建和编辑闪电组件

好!时间写一些代码! #最后!

编写Lightning组件代码的第一步是,呃,设置编写代码。幸运的是,这非常简单。在您的组织机构中,打开您的名字下的开发者控制台或快速访问菜单(设置齿轮图标Setup gear icon)。

闪电体验 Salesforce 经典
Opening the developer console
Classic mode: Opening the developer console

繁荣,你已经准备好写Lightning组件代码!

Boom: you can start writing component code

在开发者控制台中创建Lightning组件

所以,我们来写点东西吧。选择 File | New | Lightning Component 创建一个新的闪电组件。在New Lightning Bundle面板中,输入helloWorld作为组件名称,然后单击Submit。

New Lightning Bundle panel

这将创建一个新的helloWorld组件包,其中包含两个打开的选项卡。关闭helloWorld选项卡,并保持helloWorld.cmp选项卡打开。

helloWorld.cmp包含Lightning组件的开始和结束标签,<aura:component>。在它们之间,添加以下标记,并保存:

<p>Hello Lightning!</p>
你的组件标记应该如下所示。
Hello Lightning markup

呜呼,你的第一个闪电组件!现在…我们如何看待它的样子?

简单的回答是,这是棘手的。你不能直接运行你的组件,看看它是如何工作的。相反,您的组件需要在容器应用程序中运行,我们将其称为容器。容器的例子是Lightning Experience或Salesforce应用程序,或者是使用Lightning App Builder构建的应用程序 – 基本上,您在前一个单元结束时看到的任何内容。您将组件添加到其中一个容器,然后在该容器中访问它。

稍后我们将更多地讨论容器,以及其他Lightning组件模块。现在,让我们来简单介绍一下。

选择 File | New | Lightning Application 以创建一个新的闪电应用程序。在New Lightning Bundle面板中,输入“harnessApp”作为应用程序名称,然后单击Submit。

这将创建一个新的harnessApp包,其中包含两个打开的标签。关闭harnessApp选项卡,并保持harnessApp.app选项卡打开。

harnessApp.app包含Lightning应用程序的开始和结束标记,<aura:application>。在它们之间,添加以下标记,并保存:

<c:helloWorld/>

这将我们之前创建的helloWorld组件添加到harnessApp应用程序。

在我们解释这个看似简单的应用之前,请在开发者控制台的harnessApp.app和helloWorld.cmp标签之间来回点击。除了标记之外,你注意到哪些不同?

What is different?

有一个:预览按钮。应用程序有一个,组件不。现在点击它,另一个浏览器窗口应该打开并显示你的应用程序。

Preview the app.

现在我们正在用…做饭,好吧,这只是“你好世界”。但是这里有一些有趣的事情要注意,尽管标记是微不足道的。

我们从开发者控制台开始。如果您已经使用它来编写Visualforce或Apex,那么您肯定会注意到任何Lightning软件包编辑窗口右侧的调色板中出现的额外控件。每个带有“创建”标签的不同按钮都代表您可以添加到软件包的不同资源。我们将在下一节讨论资源和捆绑。现在,只要知道开发者控制台为您提供了一个简单的方法来创建和切换它们。

事实上,开发人员控制台具有许多与Lightning组件配合使用的功能。还有 File | Open | Lightning Resources, 可以让你一次打开一堆闪电资源。有用!

开发者控制台是编写Lightning代码的好地方,我们将在这个模块的其余部分使用它。但是,由于Lightning资源可通过Force.com Tooling API访问,因此还有其他方法可以创建和编辑它们。 Salesforce DX为开发Lightning组件的各个方面提供了强大的支持。 Force.com IDE是一个很好的独立客户端,并且有很好的第三方工具,如Sublime Lightning和VS Code。不要以为只限于开发者控制台!

在我们转向代码之前最后一件事。我们“预览”的URL实际上是我们的应用程序永久的家(一旦它提供给我们的用户)。 URL的格式如下:https:// <yourDomain> .lightning.force.com / <yourNamespace> / <yourAppName> .app。

<yourAppName>表示应用程序包的名称,在这种情况下为harnessApp。在你的Trailhead DE组织中,你不应该有一个配置好的名字空间,所以你应该在这个URL部分看到一个“c”。 “c”表示默认的命名空间…它会在以后回来困扰我们。 URL格式的其余部分应该是不言自明的。

好的,在代码上!

什么是组件?

你好的世界并不是经常触发存在的问题,但我们在这里。让我们来讨论一下我们的helloWorld示例中的组件是什么。实际上,一个组件是一个捆绑包,它包含一个用标记编写的定义资源,并且可以包含额外的可选资源,如控制器,样式表等等。资源有点像文件,但存储在Salesforce中而不是文件系统上。

我们的helloWorld.cmp组件定义资源很容易理解。

<aura:component>
    <p>Hello Lightning!</p>
</aura:component>

有<aura:component>标签的开始和结束,以及一些静态的HTML。这很难变得更简单,你可能会想它是一个“页面”,不要。我们会稍微回顾一下。

我们已经提到了组件包,但他们究竟是什么?一个捆绑就像一个文件夹。它将单个组件的相关资源分组。捆绑中的资源通过每种资源类型的命名方案自动连接在一起。自动布线只是意味着组件定义可以引用其控制器,帮助器等,这些资源可以引用组件定义。他们彼此(大部分)自动挂钩。

让我们看看这是如何工作的。使用helloWorld.cmp激活,单击右侧组件面板中的STYLE按钮。这会为添加到helloWorld包的样式资源打开一个新选项卡。它开始于一个单一的空选择器.THIS。要查看这是如何工作的,请在样式表中添加一个简单的样式,使其如下所示。

.THIS {
}

p.THIS {
    font-size: 24px;
}

然后重新加载harnessApp.app的预览窗口。 Voilà,更大的文字!但是,.THIS是如何工作的?这是自动布线的魔力!在运行时.THIS被替换为您的组件命名的样式范围字符串。它将样式规则限制为仅限于此组件,以便您可以创建特定于组件的样式,而不用担心这些样式可能会如何影响其他组件。

所以现在我们的helloWorld包有两个资源,组件定义helloWorld.cmp和样式表helloWorld.css。你可以把它想象成一个文件夹或者一个大纲:

  • helloWorld — 组件包
    • helloWorld.cmp — 组件的定义
    • helloWorld.css — 组件的样式

如您在开发者控制台中看到的那样,您可以添加到组件包中的其他许多资源类型。继续并单击CONTROLLER和HELPER项目,将这些资源添加到包中。现在你的包看起来像这样,你可以开始看到命名系统。

  • helloWorld — 组件包
    • helloWorld.cmp — 组件的定义
    • helloWorldController.js — 组件的控制器或主JavaScript文件
    • helloWorldHelper.js — 组件的助手或辅助JavaScript文件
    • helloWorld.css —组件的样式

在这个模块中,我们只使用这四种资源类型。当我们真正开始为他们编写代码时,我们会更多地讨论控制器和辅助资源。现在,你可以保留默认的实现。毕竟,这只是你好世界!

什么是应用程序?

现在我们知道什么是组件,实际上很容易解释一个应用程序是什么 – 一个应用程序只是一种特殊的组件!对于本模块而言,您可以将应用程序视为与组件不同,而只有两种有意义的方式:

  • 一个应用程序使用<aura:application>标记而不是<aura:component>标记。
  • 开发者控制台中只有一个应用具有“预览”按钮。

而已!

什么是应用程序?

就像听起来那么简单,关于如何使用应用程序和组件,有一些实用的细节。主要内容如下。

  • 编写标记时,可以将组件添加到应用程序,但不能将应用程序添加到其他应用程序或应用程序添加到组件。
  • 一个应用程序有一个独立的URL,您可以在测试时访问,也可以发布给您的用户。我们经常将这些独立的应用程序称为“my.app”。
  • 您无法将应用程序添加到Lightning Experience或Salesforce应用程序 – 只能添加组件。在最后一个单位之后,这听起来很奇怪。如果不是应用程序,到底应该将什么添加到应用程序启动器?您添加到应用启动器的是一个Salesforce应用程序,该应用程序包装了一个Lightning组件,这个组件在<aura:component>中定义。 Lightning组件应用程序(即<aura:application>中定义的某些内容)不能用于创建Salesforce应用程序。有点奇怪,但它是。

那么,什么是适合的应用程序?你为什么要用一个?我们之前回答了这个问题。您使用容器发布使用Lightning组件构建的功能。 Lightning组件应用程序是Lightning组件的一种容器。

再一次实用,这通常意味着你在顶级组件中构建了所有的“应用程序”功能。然后,最后,将一个组件粘贴到一个容器中 – 也许是一个Lightning组件应用程序,也许是Salesforce应用程序,也许还有其他的东西。如果使用my.app,那么容器可以为您的主要组件设置服务,否则就是在那里托管组件。

让我们再看看我们创建的应用程序。这里再一次是harnessApp.app定义资源:

<aura:application>
	  
    <c:helloWorld/>
	    
</aura:application>

无论我们决定添加多少功能,我们将添加到我们的helloWorld“应用程序”,它都将进入helloWorld组件。它可以嵌入一个Quip风格的编辑器来修改hello消息,但是我们的harnessApp.app定义仍然非常简单。

从这里开始,我们将假设您正在使用实际的Lightning Application捆绑包作为您创建的组件的容器或线束。随意继续使用harnessApp.app!但是,当我们谈论创建应用程序时,我们的确意味着在一个组件包中构建功能,而不是应用程序包,因为这就是在现实世界中构建“应用程序”的方式。

包含组件的组件,包含…组件!

harnessApp.app定义也很有趣,因为不是静态的HTML,而是我们的helloWorld组件。我们说harnessApp包含helloWorld组件。让我们深入一点,让helloWorld更复杂一点。

在开发者控制台中,创建一个名为helloHeading的新Lightning组件。对于它的标记,粘贴在下面的代码。

<aura:component>
    <h1>W E L C O M E</h1>
</aura:component>
现在,请回到helloWorld.cmp,并在“Hello Lightning”行上面添加<c:helloHeading />。您的helloWorld组件定义现在应该如下所示:
<aura:component>
	  
    <c:helloHeading/>
	    
    <p>Hello Lightning!</p>
	    
</aura:component>
重新加载应用程序以查看更改。你的组件结构,包含什么,现在看起来像这样:
  • harnessApp.app
    • helloWorld.cmp
      • helloHeading.cmp
      • (static HTML)

我们说helloHeading是helloWorld的子组件,或者helloHeading嵌套在helloWorld中,或者…。有许多不同的方式可以说helloWorld包含helloHeading。更重要的是,您可以将其他组件中的组件嵌套到几乎任何您关心的级别。在遇到Lightning组件的局限之前,开始很难保持头脑清醒。

这个将组件放在一起的过程是构建Lightning组件应用程序的基础。您可以从简单的“细粒度”组件开始,或者构建简单的“细粒度”组件,其中每个组件都提供了一组自定义的功能。然后,将这些组件组装成具有更高级功能的新组件。然后你使用这些组件,并再次“升级”。

让我们用软件环境以外的我们熟悉的隐喻来谈论这个问题。想象一下房子。更好的是,让我们给你看一个。

House animation

当你看这个房子,你看到了什么?如果你不再把它想象成一个“房子”,而是作为一个房子的组成部分,你也会开始看到它所构成的棋子和图案。

在最大的规模,这个房子是由三个相似的结构组成。这三个组件具有相似但不相同的设计。每一个都可以进一步分解成更小的组件,比如窗户,窗户可以分解成单独的窗格。这些较小部件的排列或组成定义了三个较大结构之间的差异。

三个结构通过两个较小的狭窄结构/部件连接在一起,这些结构/部件本身可以分解成更小的可重复使用的模式。这些连接部件将三个独立的结构组合成一个更大的整体:房子。

就像我们在架构方面所做的一样,所以我们可以使用一个网络应用。稍后在这个模块中,您将获取细粒度的输入组件,并使用它们创建一个表单组件。然后,您将获取该表单组件并将其放入另一个组件,以构建应用程序级别的功能。

Expenses app composition

看起来并不像房子那么漂亮,但是构图过程背后的原理非常相似。 在组件和组成方面进行思考是您在整个模块中开发的一项基本技能,每当您使用Lightning组件构建应用程序。

在这里你已经做了一点,但是在我们真的能够构建能够做某事的组件之前,我们需要了解属性,类型,值和表达式。 在此之前,虽然,你的第一个代码挑战!

Lightning-组件(2)入门

学习目标

完成本单元后,您将能够:

  • 描述什么是Lightning组件框架,以及它的用途。
  • 列出Lightning组件和其他Web应用程序框架之间的四个主要区别。
  • 列出至少五种不同的方式,您可以使用Lightning组件来自定义Salesforce。

Lightning组件入门

是!你仍然和我们在一起!我们非常高兴地欢迎您来到Lightning Component派对,这是一个派对。当我们说Lightning组件是我们多年来建立的最令人兴奋和最强大的应用程序开发技术时,这是一个大胆的说法。我们知道这是事实,因为我们使用它构建了Salesforce应用程序和Lightning Experience。我们认为,一旦了解Lightning组件,您就会像使用它一样兴奋。

什么是闪电组件框架?

Lightning组件是为移动和桌面设备开发Web应用程序的UI框架。这是一个现代的框架,用于为Force.com应用程序构建具有动态响应用户界面的单页面应用程序。它在客户端使用JavaScript,在服务器端使用Apex。

这是很多流行语。让我们看看我们是否不能再次尝试,用正常的人使用的话。

Again, looking at a very high level architecture

“闪电组件是一个开发Web应用程序的框架。”这似乎是可以理解的。应用程序框架是代码和服务的集合,使您可以更轻松地创建自己的自定义应用程序,而无需亲自编写所有代码。有很多不同的Web应用程序框架,比如Ruby on Rails,Grails,AngularJS,Django,CakePHP等等。我们甚至有我们自己的,Visualforce,客户知道和爱。闪电组件是新的,我们认为它是非常特殊的。我们将讨论为什么它更特别,希望在本单元的最后,你会同意!

“移动和桌面设备的网络应用程序。”再次,这似乎很容易掌握。但是…你注意到那里的订单吗? Lightning组件诞生于并用于构建移动应用程序的Salesforce平台。 Mobile已经成为Lightning组件的核心,它使开发移动和桌面设备的应用程序比许多其他框架更简单。

“这是一个用于构建单页应用程序的现代框架。”好的,现在我们有点嗡嗡了。 “现代”只是营销,对不对?什么是“单页面应用程序”?

我们不认为现代是“只是”营销。在“闪电体验开发”模块中,我们详细地讨论了Web应用程序如何从简单的,逐页面向的体验演变为具有与原生应用程序相同的行为和交互性的高响应性应用程序,在台式机上尤其是在移动设备上。为了实现这些交互式用户体验,现代Web应用程序被构建为从单个URL加载的紧密绑定的代码集合,然后在您使用它时连续运行。这些单页面应用程序的构建与本机应用程序非常相似,其中管道由一个框架处理。像Lightning组件这样的框架。

“Force.com应用程序的动态响应用户界面”只是将上述想法应用于您在Salesforce之上构建的应用程序。最后,“它在客户端使用JavaScript,在服务器端使用Apex”本身就是不言自明的,即使它遗漏了一些关于什么地方的具体细节。我们很快就会做到的

示例闪电组件

好吧,这是很多谈话谈话,而不是很多的代码。让我们来看看一个真正的Lightning组件,看看这些话题是什么。首先,这是屏幕上显示的组件的外观:

Lightning component: not much to look at, but a fair bit going on

它看起来可能不多,但是还有一点点。这是它的代码;这是我们稍后将详细介绍的一个组件。

<aura:component>

    <aura:attribute name="expense" type="Expense__c"/>
    <aura:registerEvent name="updateExpense" type="c:expensesItemUpdate"/>

    <!-- 如果费用报销 - 将项目变为绿色 -->
    <lightning:card title="{!v.expense.Name}" iconName="standard:scan_card"
                    class="{!v.expense.Reimbursed__c ?
                           'slds-theme--success' : ''}">
        <aura:set attribute="footer">
            <p>Date: <lightning:formattedDateTime value="{!v.formatdate}"/></p>
            <p class="slds-text-title"><lightning:relativeDateTime value="{!v.formatdate}"/></p>
        </aura:set>
        <p class="slds-text-heading--medium slds-p-horizontal--small">
            Amount: <lightning:formattedNumber value="{!v.expense.Amount__c}" style="currency"/>
        </p>
        <p class="slds-p-horizontal--small">
           Client: {!v.expense.Client__c}
        </p>
        <p>
            <lightning:input type="toggle" 
                             label="Reimbursed?"
                             name="reimbursed"
                             class="slds-p-around--small"
                             checked="{!v.expense.Reimbursed__c}"
                             messageToggleActive="Yes"
                             messageToggleInactive="No"
                             onchange="{!c.clickReimbursed}"/>
        </p>
    </lightning:card>
</aura:component>

即使在您对Lightning组件了解之前,您仍然可以注意到有关此示例的一些信息。首先,它是XML标记,并将静态HTML标记与自定义Lightning组件标记混合,如引导样本的<aura:component>标记。如果您使用过Visualforce,则该标签的格式很熟悉:namespace:tagName。正如你以后会看到的,内置的组件可以来自各种不同的命名空间,比如aura :(如这里)或者force :, lightning :,或者ui :.

您可能已经注意到有像<lightning:input>和<lightning:formattedNumber>这样的组件。再次,这是Visualforce开发人员熟悉的模式。如果你不是其中之一,现在我们会说你使用输入组件来收集用户输入,其他组件显示只读值。以下是片段中突出显示的几个组件。

  • <lightning:card>围绕一组信息创建一个容器。
  • <lightning:formattedDateTime>显示格式化的日期和时间。
  • <lightning:relativeDateTime>显示当前时间和提供的时间之间的相对时间差。

注意

什么是名字(空间)?闪电命名空间提供了许多使用Salesforce Lightning Design System或SLDS的UI组件。我们建议您尽可能在闪电命名空间中使用组件。例如,使用<lightning:input>而不是<ui:inputText>,<ui:inputNumber>等等。大多数输入类型,如文本,数字,电子邮件,还有更多可供您使用。

我们将在后面的单元中找到其余的组件。现在,最后需要注意的是,使用静态HTML和许多以“slds”开头的CSS类名称。我们将使用SLDS来设计我们的组件,虽然我们不会在这个模块中详细解释SLDS,但是我们希望您看到它的实例。

好的,酷,Lightning组件标记是XML。但是,我们之前没有谈过关于JavaScript的东西吗?请注意切换开关上的onchange =“{!c.clickReimbursed}”属性,这是一个真正复杂的复选框,可左右滑动以表示已选中和未选中的值。这意味着“当这个值改变时,调用控制器的clickReimbursed函数。”让我们看看它附加的代码。

({
    clickReimbursed: function(component, event, helper) {
        var expense = component.get("v.expense");
        var updateEvent = component.getEvent("updateExpense");
        updateEvent.setParams({ "expense": expense });
        updateEvent.fire();
    }
})

这是用JavaScript编写的组件的客户端控制器。组件控制器中的clickReimbursed函数对应于组件标记中复选框的onchange =“{!c.clickReimbursed}”属性。

在Lightning组件中,一个组件是一组代码。它可以像“.cmp资源”中的前面的示例一样包含标记,还可以包含JavaScript代码,并包含在许多关联的资源中。相关资源是相互“自动连线”的,它们一起构成组件包。

我们将在下一个单元中详细介绍,但现在,您已经看到了两个最重要的Lightning组件代码类型。

什么关于Visualforce?

我们从客户那里得到的问题是:“我应该使用Lightning组件还是Visualforce?”简短的回答是:是的!

Visualforce和Lightning组件各有其优势。这些在Lightning Experience开发模块中进行了讨论,您可以在这里找到关于每个模块适当使用的长篇答案。在这里,让我们去中等。

首先知道这个:Visualforce不会消失。您的Visualforce代码将在很长一段时间内在Salesforce上运行。您无需转换现有的Visualforce应用程序,也无需停止使用Visualforce创建应用程序。

但是,至少在某些情况下,您可能会想要。例如,Visualforce是在手机上的移动应用成为事物之前创建的。虽然您可以使用Visualforce开发移动应用程序,但是没有任何内置组件是精通移动的。这意味着你写更多的代码。另一方面,Lightning组件专门针对移动设备进行了优化。

再次,我们在Lightning Experience模块的开发中介绍了很多具体内容。如果您仍然对Visualforce和Lightning组件有疑问,那么接下来就是一个好的选择。

关于AngularJS,React和其他JavaScript框架呢?

另一个经常出现的问题是:“Lightning组件如何与MyFavoriteFramework进行比较?”这个最喜欢的框架是另一个现代的JavaScript Web应用框架,比如AngularJS,React或者Ember。

这些都是很好的框架!很多人都认识他们,有很多资源可以学习。您可能会惊讶地发现,我们认为这些框架是构建Force.com应用程序的好方法!

我们建议使用Visualforce,使用我们所谓的容器页面,并将您选择的框架和应用程序代码打包到静态资源中。通过使用空的容器页面,Visualforce可以自由使用,并让您使用所选框架的全部功能。

尽管可以在Lightning组件中使用第三方JavaScript框架,但这有点麻烦。 Lightning组件没有空白页面的概念,并且对于如何执行数据访问以及一些相当具体的安全需求有一些特定的意见。

坦率地说,Lightning组件和大多数现代框架的功能重叠了很多。尽管样式或细节可能不同,但所提供的功能在概念上相似,足以使您有效地运行重复代码。这既不有效也不容易。

另一件需要考虑的事情是:像AngularJS这样的通用框架被设计成与他们在特定数据服务上运行的平台无关。另一方面,Lightning Components设计用于本地连接Salesforce和Force.com平台提供的服务。你认为哪种方法可以帮助你更快地构建应用程序?

注意

我们只是在这里讨论应用程序框架。如果您有一个最喜欢的JavaScript图表或映射库或其他特殊用途的工具包,则受到某些安全要求的限制,现代JavaScript库通常可以正常工作。

好吧,足够的话语单词!让我们快速浏览一下您可以部署Lightning组件应用程序的许多地方。然后让我们深入了解有趣的东西:代码。

你可以在哪里使用闪电元件

您可以使用Lightning组件以多种不同的方式自定义您的Salesforce组织。但是,这不是全部!您可以使用Lightning组件创建托管在Salesforce上的独立应用程序。您甚至可以创建托管在其他平台上的应用程序,包括将这些应用程序从这些平台嵌入到应用程序中。

将应用添加到Lightning Experience应用启动器

您的Lightning组件应用程序和自定义选项卡位于应用程序启动器中,您可以通过单击标题中的“应用程序启动器App Launcher icon”图标进行操作。

Add component to the App Launcher

点击一个自定义的应用程序(1)来激活它。导航栏中显示的应用程序中的项目,包括您添加到应用程序的任何Lightning组件选项卡。请注意,您需要将组件添加到选项卡,以便可以在应用启动器中访问它们。所有项目(2)中均可找到不在应用程序中的闪电组件选项卡。

将应用添加到Lightning Experience和Salesforce App Navigation

如上例所述,您可以将Lightning组件选项卡添加到应用程序,并在应用程序的导航栏中显示为项目。

Add built-in components to the main navigation

为Lightning App Builder和社区生成器创建拖放组件

使用您自己的Lightning组件或从AppExchange安装的桌面和移动设备构建自定义用户界面。

Create Drag-and-Drop Components for Lightning App and Community Builder

将闪电组件添加到闪电页面

Lightning Page是一种自定义布局,可让您设计在Salesforce移动应用程序或Lightning Experience中使用的页面。您可以使用Lightning Page来创建应用程序主页,并将您最喜爱的Lightning组件(如我们将在此模块中创建的Expenses应用程序)添加到该主页中。

添加闪电组件到闪电体验记录页面

正如标题所示,您可以通过添加Lightning组件来自定义Lightning Experience记录页面。

Just as the title suggests, customize Lightning Experience Record Pages by adding a Lightning Component

启动闪电组件作为 Quick Action

使用Lightning组件创建动作,然后将动作添加到对象的页面布局,使其可以从记录页面即时访问。

Lightning componet quick action on record page

用闪电组件覆盖标准操作

用一个Lightning组件覆盖一个动作,这个动作与Visualforce页面重叠。

Override actions with Lightning components

创建独立的应用程序

独立应用程序包含使用Salesforce数据的组件,可以独立于标准Salesforce环境使用。

standalone apps are components that use Salesforce data and can be used independent of the Salesforce app

在Visualforce页面中运行Lightning组件应用程序

将Lightning组件添加到您的Visualforce页面,以结合使用这两种解决方案构建的功能。 使用Lightning组件实现新功能,然后将其用于现有的Visualforce页面。

使用闪电在其他平台上运行Lightning组件应用程序

闪电是一个延伸Lightning应用程序的功能。 它在任何远程Web容器中充当闪电组件的桥梁。 这意味着您可以在外部站点(例如Sharepoint或SAP)内使用Lightning组件,在使用Mobile SDK构建的混合应用程序中,甚至在Heroku平台上的其他位置使用Lightning组件。

Lightning Out on Heroku dialog

Lightning-组件(1)开始之前

学习目标

完成本单元后,您将能够:

  • 确定你是否有能力完成这个模块。
  • 为Developer Edition组织配置我的域。
  • 创建一个必需的自定义对象

开始本模块之前

我们知道。你真是开始了。远离我们的是挫伤任何人对Trailhead的热情!但是在你完成这个模块之前,我们有一些你应该做的事情。我们建议你在开始下一个单位之前先做。这些步骤可能需要一些时间,而更改会渗透到您的组织中,而这些步骤甚至可能会让您离开另一个方向。所以,在你承诺完整的模块之前,首先需要完成这个简单的单元。

我们要做的第一件事就是在Developer Edition中启用“我的域”,或者您正在使用您的挑战。我的域名需要使用Lightning组件进行开发,并且可能需要一点时间才能在30秒到30分钟的任意位置激活。我们不愿吃掉你的Trailhead Time,让你坐下来等着。我们还将在您的组织中创建必要的自定义对象,费用对象。

然后,当我们等待我的域名时,我们可以聊一下你是否想要打开这个模块。没有人喜欢被排除,但真的,这个模块并不适合每个人。所以我们想花一点时间,谈谈这个模块的用途以及你需要完成的技能。

我们知道这听起来像是我们在激动你。我们讨厌和你一样。但我们要尊重你的时间。如果这不是适合你的模块,那么让我们来指点一下Trailhead的另一部分,所以你和我们在一起的时间是有趣而富有挑战性的,而不是令人沮丧的。

注意

如果您的DE组织已经启用了“我的域”,或者您使用了Trailhead Playground组织,请跳过此部分。您已经设置了“我的域名”。

使用我的域名向您的组织添加自定义域名

要使用Lightning组件,您的组织需要使用“我的域”配置自定义域。

那么什么是自定义域名,为什么你需要有一个使用Lightning组件?首先,一个自定义域名是一种拥有自己的Salesforce服务器的方法。您可以通过自己的自定义URL(而不是通用的Salesforce实例URL)使用Salesforce。也就是说,一旦您拥有一个自定义域名,您将使用https://yourDomain.my.salesforce.com/上的Salesforce,该域名仅供贵组织使用。让其他人继续使用和分享https://na30.salesforce.com/。您的自定义域将您置于您自己的私人互联网岛上。

建立一个自定义的域名除了给你一个很酷的URL之外还有很多好处。除此之外,自定义域允许您:

  • 使用唯一的网域网址突出显示您的商家身份
  • 品牌您的登录屏幕和自定义右帧内容
  • 阻止或重定向不使用新域名的页面请求
  • 同时在多个Salesforce组织中工作
  • 设置自定义登录策略以确定用户如何进行身份验证
  • 让用户使用登录页面上的社交帐户(如Google和Facebook)登录
  • 允许用户登录一次以访问外部服务

一个自定义的域也提高了你的组织的安全性,以太复杂的方式进入现在。在这里,我们来谈谈Lightning组件需要的原因。为了为应用程序提供世界级的安全性,我们要求Lightning组件的所有用户使用My Domain,就像我们为其他高级功能(如Salesforce Identity)所做的一样。如果您要使用Lightning组件,则必须在您的组织中启用“我的域”。

在您的组织中启用我的域

在我们开始创建Lightning组件之前,让我们使用Salesforce My Domain来设置一个子域。设置我的域名是一个要求吗?是的,如果您想在Lightning标签,Lightning页面或独立应用程序中使用Lightning组件。 Salesforce需要我的域作为安全措施来帮助防止恶意攻击,以防万一安全漏洞隐藏在第三方或自定义组件中。
如果您的DE组织已经启用了“我的域”,或者使用了Trailhead Playground组织,请跳过本节和下一节。您已经设置了“我的域名”。

如果你还没有一个子域名,很容易设置一个子域名。

每个Salesforce组织都使用像https://na30.salesforce.com这样的URL在salesforce.com域中设置。通过我的域名,您可以在salesforce.com域中定义自己的域名或子域名。您的新网址如下所示:https://yourDomain.my.salesforce.com。

使用“我的域”向导创建一个子域。

My Domain wizard

  1. 从设置中,在快速查找框中输入我的域名,然后选择我的域名。
  2. 在https://之后输入您的子域的名称,然后单击“检查可用性”。通常情况下,一个子域名是你的公司名称,但只要它是唯一的,你可以使用任何名称。如果这个名字已经被使用,请选择另一个。
  3. 点击注册域名。

Salesforce使用您的新子域更新其域注册表。完成之后,您会收到一封电子邮件,其中包含“您的开发人员版本域准备好进行测试”这个主题。只需几分钟。

重要

你是否抓住了最后一部分?可能需要几分钟时间才能使用您的域名。在获得激活邮件之前,您无法进入下一步。

将我的域名发布到您的组织

你有没有收到你的激活邮件?从电子邮件中,单击链接返回到“我的域”向导。它会将您带到第3步,在此步骤中,您可以在将子域推出到您的组织之前测试指向您的子域URL的链接。即使您没有用户将其部署到您的DE组织中,仍然必须部署“我的域”以使您的Lightning页面,Lightning App Builder中以及独立应用程序都可以使用您的自定义Lightning组件。
My Domain Wizard
  1. 点击激活电子邮件中的链接以登录到您的Salesforce子域。它会将您带到您的Salesforce组织。
    请注意,浏览器地址栏中的网址显示新的子域名。现在,你是唯一拥有这个URL的人。URL of subdomain
  2. 点击您的组织,确保链接指向您的新域名。您可能还没有在您的DE组织中创建链接,所以我们可以继续。 (在生产组织中创建域时,这个重要步骤很容易被忽略。)
  3. 在“我的域”页面上,单击“部署到用户”,然后单击“确定”。部署子域在整个组织中推出新的子域URL。现在,所有用户都可以在浏览器地址栏中看到子域名网址。
  4. 向导的第4步显示配置选项,我们现在可以忽略它。
恭喜,你已经建立了我的域名!在生产组织中设置“我的域”时,您还需要执行一些步骤。通过完成“用户验证”模块的“我的域”单元了解更多信息。现在,您已经对子域的组织进行了保护并将其品牌化,接下来让我们继续。

定义费用自定义对象

我们将在这个模块中使用的许多示例依赖于一个自定义的Expense对象。如果您将这些样本添加到您的DE组织,并自己进行实验,您将从这个模块中获得最大收益。对sObjects的引用在保存时进行验证,如果有任何对象未定义,则该组件是无效的。 Lightning组件不会让你保存一个它认为无效的组件。让我们先创建Expense对象,这样就不会遇到编译和保存依赖于它的代码的任何问题。
虽然我们假设您已经知道如何创建自定义对象,但下面是简要说明以及Expense对象及其字段的具体信息。
  1. 转到对象管理器。
    从页面顶部的安装程序中,单击对象管理器。
  2. 创建自定义对象。
    选择 Create | Custom Object.
  3. 定义费用对象。

    为对象的定义输入以下值。

    字段
    标签 Expense
    Plural 标签 Expenses
    从检查元音 checked
    API名称 Expense__c

    接受对象定义其余部分的默认值。

  4. 将自定义字段添加到费用对象。

    滚动到对象详情页面的字段和关系部分。对于以下每个字段,请单击“新建”并使用以下详细信息定义该字段。

    字段标签 API名称 字段类型
    Amount Amount__c Number(16,2)
    Client Client__c Text(50)
    Date Date__c Date
    Reimbursed Reimbursed__c Checkbox

你需要完成这个模块的技能

Salesforce的优点之一是您可以使用应用程序对其进行自定义。自定义对象和字段,公式,流程,报告,批准甚至用户界面本身 – 您可以在安装程序中完成所有这些工作,而无需编写一行代码,并让用户非常开心。

但Salesforce的某些功能需要代码,而Lightning组件就是其中之一。关于这一点,没有两种方法:要成功使用Lightning组件,您需要能够读取和写入代码。我们将在整个模块中查看大量代码,并且您必须自己写一些相应的代码才能通过这些挑战。

具体来说,我们认为:

  • 你应该舒适地阅读和编写JavaScript。尽管Lightning组件也使用HTML风格的标记,但除了“hello world”以外的任何操作都需要JavaScript。
    有大量的资源,免费的,否则,学习JavaScript。我们建议您以正确的方式开始使用JavaScript。但是,如果你的朋友或同事有一个建议,或一本书,他们可以借给你,去为它! 
  • 如果你知道Apex,那将会很棒。从Salesforce读取和写入数据通常使用Apex,这就是我们在这个模块中学到的东西。你可以通过这个模块的挑战,而不是一个Apex的专家,但是当你去写真实的应用程序,你会写很多Apex。
    Apex基础和数据库模块是开始使用Apex的好方法,并且会为您提供该模块所需的一切。

如果这不能描述你,我们不想把你拒之门外。 没有先前的技能,完成这个模块并不是不可能的。 但我们确实认为这将是令人沮丧的。 虽然你可能获得徽章 – 这绝对是很酷! – 你不会真的准备好使用Lightning组件来编写应用程序。

我们希望Trailhead变得有趣,我们希望它能够帮助人们更完整,更自信地使用Salesforce。 有经验的程序员会从这个模块中获得很多。 但是在没有必要的编程背景的情况下研究它可能不是您的Trailhead时间的最佳使用。

好。 就这样,让我们潜入并开始学习吧!

Salesforce Lightning 开发(5)

学习目标

完成本单元后,您将能够:

  • 描述Lightning Experience如何影响您的开发工具,包括:
    • 安装包管理
    • API和Apex
    • 身份验证和安全
    • 画布
    • Salesforce移动开发
    • Salesforce Mobile SDK

了解其他开发工具的变化

最后一个单位是一个抓包。我们已经涵盖了所有的“硬”的东西,所以在这一点上,你在家里。你能感觉到吗?当你靠近一个新的徽章时,这就是你的痒。我们开工吧。

在闪电体验中安装的软件包

在Lightning Experience中管理已安装的软件包与以前一样。 “安装的软件包”登录页面位于Lightning Experience安装区域。它的外观和工作方式与Salesforce Classic中的相同。

当然,查找和使用这个页面并不是你想的唯一的东西。您也想知道从AppExchange安装的软件包是否仍然可以在Lightning Experience中使用。

也许我们可以给出最好的答案。如果AppExchange上列出的应用程序与Lightning Experience完全兼容,则会标记为“Lightning Ready”。查看列表以查看应用是否为Lightning Ready。如果不是,您仍然可以尝试在Lightning Experience中使用它,但是我们建议您坚持使用Salesforce Classic来防止意外的行为。

闪电体验中的API和Apex

作为开发人员,任何平台上最重要的工具之一就是API。作为Salesforce开发人员,Apex对您的成功同样重要。

我们保证我们的承诺,我们不会做任何违反我们的API的依赖。无论您是使用Lightning Experience还是Salesforce Classic,您的Apex代码和查询都可以按预期继续工作。这真的很简单。呼吸一口气。

闪电体验的认证与安全

无论您正在开发的用户体验如何,安全性仍然是Salesforce的首要任务。闪电体验并不符合我们保证组织数据安全的承诺。

继续像开发Salesforce Classic时一样处理身份验证和安全性。 Salesforce Classic和Lightning Experience之间访问控制的唯一区别在于App Launcher。应用程序启动器默认情况下可用于组织中的所有用户。虽然这种变化大多数是管理员关心的,但与Salesforce管理员一起工作是非常重要的,以确保您的开发工作只能被看到的人看到。

画布闪电的经验

Force.com Canvas允许您轻松地将第三方应用程序集成到Salesforce中。 Lightning Experience中的画布功能与Salesforce Classic中的相同。您仍然可以在Visualforce页面,Salesforce应用程序以及他们所支持的其他任何地方嵌入Canvas应用程序 – 还可以在Lightning组件中集成Canvas应用程序!

Salesforce Mobile闪电体验

Lightning Experience和Salesforce mobile就像花生酱和果冻。他们是为对方制造的。您在Lightning Experience中的移动开发实践与Salesforce Classic中的相同。

当我们说这两个是为了彼此而制定的时候,我们就是这个意思。您可能熟悉sforce.one JavaScript对象。在过去,它被用作Salesforce移动开发中的导航事件机制。现在,您也可以在Lightning Experience中使用它进行导航。有关更多信息,请参阅“Salesforce Mobile应用程序开发者指南”。

移动SDK闪电体验

到目前为止,您可能已经厌倦了阅读概述信息,并准备好深入了解细节技术细节。我们不会让你更久。从字面上看,只有两个句子!

作为自己的客户端或前端,对于Salesforce而言,Mobile SDK不受Lightning Experience的影响。如果您使用移动SDK开发移动应用程序,您可以轻松休息。

Salesforce Lightning 开发(4)

学习目标

完成本单元后,您将能够:

  • 列出Lightning Experience中不可用的合作伙伴工具。
  • 描述Lightning Experience中的包装过程。
  • 了解Lightning Experience如何影响AppExchange。
  • 描述如何使您的产品闪电准备就绪。

Salesforce合作伙伴,打包和AppExchange

如果您是Salesforce AppExchange合作伙伴(ISV),您可能想知道Lightning Experience如何影响您的开发和发布流程。你现有的产品是否仍然有效?你必须对现有的程序做出重大改变吗?未来版本呢?

这是有效的担忧,但是我们有好消息。 Lightning Experience提供许多用于构建,测试和分发产品的工具。我们也有资源来指导您更新您的产品,使其成为Lightning Ready。

闪电体验中的合作伙伴工具

首先,让我们谈谈工具。这个谈话是苦乐参半。您使用的一些工具在Lightning Experience中可用,而其他一些工具在那里还不被支持。以下是对目前支持的内容的概述。

特征 支持
  • 环境枢纽
  • 许可证管理应用程序(LMA)
  • 结帐管理应用程序(CMA)
Salesforce Classic和Lightning Experience。
  • Trialforce
  • 渠道订单应用(COA)
  • 用法度量可视化应用程序
仅限Salesforce Classic。

这意味着你可以去闪电体验,如果你想:

  • 为开发,测试和演示创建组织
  • 从一个地方管理你所有的组织
  • 在AppExchange上发布的许可和支持应用程序
  • 查看并报告使用AppExchange Checkout销售的产品的订阅数据

要配置试用单位或管理订单,您应该留在Salesforce Classic中。随着闪电体验的不断成熟,将有更多的工具可用。

在Lightning Experience中打包应用程序

当您准备分发应用程序,Lightning组件或其他产品时,Lightning Experience即可完成任务。包管理器允许您从安装程序创建和管理包,就像在Salesforce Classic中一样。无论您是在Developer Edition中创建托管软件包,还是在Enterprise Edition中创建非托管软件包,新的打包体验都可以在您的开发过程中感觉良好。

AppExchange和闪电体验

如果您在AppExchange上提供产品,则可能有关于获得Lightning Ready的问题。当所有最终用户使用案例在Lightning Experience中按预期工作时,我们将产品视为Lightning Ready产品。

那么,您需要多长时间才能获得Lightning Ready?答案取决于产品的类型以及与Salesforce的分销协议。使用AppExchange Checkout和新免费产品销售的新产品在安全审查之前必须是Lightning Ready。其他协议类型可能需要根据您签署协议时的闪电体验准备情况。对于现有的产品,我们鼓励您尽快获得Lightning Ready。有关更多信息和资源,请转至Salesforce合作伙伴社区的Lightning Ready页面。

如果您是AppExchange客户,请查看产品列表上的Lightning Ready认证,以确认其与Lightning Experience兼容。您可以使用Lightning Experience中未获得Lightning Ready认证的产品,但不能保证它们按预期工作。最好在Salesforce Classic中使用它们。

Salesforce Lightning 开发(3)

学习目标

完成本单元后,您将能够:

  • 描述闪电组件对闪电体验的重要性。
  • 列出使用Lightning组件而不是Visualforce的一些重要注意事项。
  • 确定三个可以使用Lightning组件的地方。

闪电体验中的闪电组件

现在,你已经读了很多次“闪电”这个词,可能失去了所有的意义。更糟糕的是,我们一直在谈论“闪电体验”和“闪电组件”,这两个术语可能会模糊在一起。让我们来澄清两者之间的关系。

还记得关于以页面为中心还是以应用为中心的模型开发的所有信息? Salesforce Classic使用以页面为中心的模型,但Lightning Experience使用以应用程序为中心的模型。它由 – 你猜对 – 组件组成。

你大概可以看到这是怎么回事。闪电组件设计时考虑到了闪电体验。随着Salesforce核心应用程序转向以应用程序为中心的框架,我们希望您与我们一起转移。我们希望您以全新的方式思考在平台上开发。

您可能已经在Salesforce Classic中开发了一些Lightning组件。您仍然可以将旧接口与Lightning组件一起使用,并将您现有的所有组件功能无缝转换为Lightning Experience。

如果您还没有使用Lightning组件,请不要担心。有一个Trailhead模块,一个快速入门指南和一个完整的开发人员指南,以便您可以立即开始开发。在深入了解技术细节之前,让我们花点时间回顾一下Lightning组件的一些基本优势:

开箱即用的组件集
Salesforce提供了许多组件来引导您的应用程序开发。
性能
组件框架利用有状态的客户端(使用JavaScript)和无状态的服务器(使用Apex)。这种结构允许客户只有在绝对必要时才调用服务器。通过调用服务器的次数更少,您的应用程序响应更快,效率更高。
事件驱动的体系结构
事件是Lightning组件框架的关键。组件监听应用程序和组件事件并作出相应的响应。
快速开发
简单的标记和预制组件意味着您可以比以往更快地获得应用程序。特别是如果您对Visualforce标记感到满意,学习组件标记是一件轻而易举的事情。
设备感知和跨浏览器兼容性
Lightning组件的一个巨大优势是您不必担心跨设备和浏览器的兼容性。组件框架为您处理这个工作。

使用注意事项

我们已经介绍了使用Lightning组件的一些注意事项。您可能不想使用正在进行的Visualforce项目切换到Lightning组件。如果您需要执行诸如从页面呈现PDF之类的东西,则还需要坚持使用Visualforce。 Visualforce还没有消失,而且仍然是在Salesforce平台上开发的基础部分。

相对来说,闪电组件框架就是这个块上的新手,但是这个新手却有技巧。尽管Lightning组件有一些特定的限制,但大部分已经准备好了。在许多情况下,您应该考虑使用Lightning组件进行开发。例如,Salesforce移动开发是使用Lightning组件的好地方。对于新项目和任何涉及高度交互式应用程序的项目,也使用Lightning组件。

我们来做个清单吧!哪里可以使用Lightning组件?你有很多选择。

闪电的经验
我们早些时候说过,但是不要让你把这个错误的想法留在这个名单上。闪电体验和闪电组合是两个伟大的品味,共同品味。
Salesforce应用程序
我们经常重复这一点,因为这很重要:使用Lightning组件来进行移动开发。当您使用移动设备时,每次用户按下按钮时都不需要拨打服务器电话。使用Lightning组件大大提高了移动应用的性能。
独立的应用程序
如果您在Salesforce Classic中使用Lightning组件,则可能至少创建了一个独立的Lightning应用程序。 Lightning App Builder允许您以标准组件的形式创建应用程序,从按钮到Canvas应用程序。或者,使用开发者控制台创建由标准和自定义Lightning组件组成的应用程序。有关更多信息,请参阅Lightning组件开发者指南。
Visualforce页面
对于Visualforce退伍军人的Salesforce开发人员来说,此功能非常完美。如果您还没有完全准备好完成Lightning应用程序,请将组件整合到Visualforce页面中来平滑过渡。这个任务只需要几行标记,给你一个巨大的灵活性。有关用于Visualforce的Lightning组件的更多信息,请参阅Lightning组件开发者指南。
任何地方!
Lightning Out目前提供beta版,可让您运行Lightning组件和应用程序,几乎可以在任何地方为网页提供服务。无论是在Heroku上运行的Node.js应用程序,防火墙内的部门服务器,还是SharePoint(是,SharePoint),都可以使用Lightning组件构建自定义应用程序,并在用户身处运行。
尽管我们已经将Lightning组件作为一个框架用于创建未来十年的应用程序,但我们还没有完成。还有一些地方可以使用Visualforce来自定义Salesforce,但是您还不能使用Lightning组件。请继续关注此频道。

Salesforce Lightning 开发(2)

学习目标

完成本单元后,您将能够:

  • 列出至少五个在Lightning Experience中保持不变的Visualforce功能。
  • 在您的Visualforce代码中描述至少两个您需要查看的Visualforce功能。
  • 列出至少两个在Lightning Experience中不起作用的Visualforce功能。
  • 描述Lightning Experience如何影响现有Visualforce页面的视觉设计。

Visualforce和闪电体验

闪电体验是一个全新的世界,我们希望你认为这是令人兴奋的。 Lightning Experience用户界面背后是一种交付Salesforce应用程序的新方法,它会对Visualforce应用程序的运行方式进行重大更改。在大多数情况下,您的Visualforce应用程序应该“只是工作”,但在跳转到Lightning Experience之前,您应该知道一些事情。
Lightning Experience如何建立以及如何运行Visualforce应用程序的技术细节非常酷,对于实际开发工作非常重要。当您准备好了解这些细节时,Visualforce&Lightning Experience模块将为您提供方法。但是在这里我们要保持高水平,把事情分成有效和无效,你想要更新什么,以及其他问题,这些问题将帮助你规划你的Lightning Experience迁移开发工作。

什么工作

Visualforce在Lightning Experience中工作的部分列表相当长。这几乎与整个Visualforce功能列表一样长。所以,在我们找到不在名单上的东西之前,让我们积极地思考一下,并且检查一下你能指望的许多事情。
首先,Visualforce工作的基本机制是一样的。无论您的网页是使用标准控制器,自定义控制器,JavaScript远程处理还是远程对象,与Salesforce的连接工作原理都是一样的。

注意

如果您广泛使用JavaScript,或者如果您使用其他API来访问Salesforce,则可能需要执行一些工作。我们会做到这一点。

其次,Visualforce标记保持不变。 Lightning Experience中有一些标签和属性的表现方式不同,我们建议不要使用这些标签和属性,否则这些属性不起作用。但是,除此之外,您为Visualforce页面和组件编写代码的方式不变。

第三,您可以使用Visualforce自定义您的组织的大多数方式在Lightning Experience中都可以正常工作 – 尽管您无疑可以想象,使用全新的用户界面,这些自定义已移至不同的位置。

让我们稍微介绍一下这些定制的细节。在Lightning Experience中,以下所有工作都很好,只需移动到用户界面的新位置即可。

  • 使用Visualforce页面创建自定义选项卡和应用程序。
  • 创建导向Visualforce页面的自定义按钮和链接。
  • 创建使用Visualforce页面打开的自定义操作。
  • 使用Visualforce页面覆盖标准操作(有一个例外,我们稍后会介绍)。
  • 创建使用Visualforce页面的流程。
  • 打包Visualforce页面和组件。

用户界面的变化从小到大有所不同。使用Visualforce自定义的功能会在用户在Lightning Experience和Salesforce Classic之间切换时自动移动。你可能需要给你的用户一个初始的方向,但在那之后,他们会像蛤蜊一样快乐。
还有其他一些功能,如Visualforce电子邮件模板,在幕后使用Visualforce代码。这些不直接在用户界面中出现,因此它们保持不变。

有关各种功能已移至其中的屏幕截图的详细视图,请参阅Visualforce&Lightning Experience模块中的使用Lightning Experience中的Visualforce单元。

什么工作,但需要更新和测试

Lightning Experience启用时Visualforce页面运行的环境与标准Visualforce请求不同。技术细节变得相当复杂,但简单的版本是在Lightning Experience中,Visualforce页面嵌入在Lightning Experience应用程序内部显示的HTML iframe中。
这种改变有很多后果,主要是JavaScript和访问外部应用程序。在验证您的Visualforce页面以用于Lightning Experience之前,您需要查看您的代码并验证一些内容。我们正在保存Visualforce&Lightning Experience模块的细节。现在,我们只需要进行高级检查,以便开始审查范围。

对于初学者来说,如果您有使用JavaScript的页面或应用程序,则需要查看代码的行为。特别是,你的代码不能直接访问窗口的全局对象。如果您确实需要更改代码,您仍然可以稍微更改代码,但是使用Lightning Experience应用程序API可能有更好的方法来完成这些任务。特别是直接设置window.location的代码,一定要修改才能与Lightning Experience导航栈集成。

同样,假设它能够访问整个环境的代码是一个粗暴的惊喜。它仍然可以访问文档的Visualforce部分,但不能访问完整的Lightning Experience应用程序。对于许多应用程序来说,这样做会很好,但是对于那些想要完全负责的人来说,还是会有一些工作要做。

如果您的页面自己使用iframe,或者使用<apex:iframe>或静态HTML,则嵌入到另一个iframe中可能会导致一些问题。在很多情况下,“海龟一路下来”都很好。只要确保你在这里做额外的测试。

如果您的页面嵌入了Force.com Canvas应用程序,特别是如果您使用Canvas API将应用程序集成到Salesforce中,则还需要分配时间进行彻底测试。画布应用程序使用iframe,而正确的行为代码应该正常工作,我们都知道如何在现实世界中普遍的完美代码。

使用远程对象和JavaScript远程处理的页面不需要更新认证码。但是,如果您的网页使用其他Salesforce API,则可能需要调整您的身份验证代码以提出正确的跨域请求,或者调整到新的环境。

以上所有内容听起来都很模糊而且难以实现,但实际上,您可能需要更改的代码量很小。再次,Visualforce&Lightning Experience模块提供开发人员的详细信息。

什么不行

所以我们来谈谈我们的谈话中不那么愉快的部分。幸运的是,Visualforce for Lightning Experience不起作用的列表很短,我们可以快速完成。
对于可能难以解决的事情,Visualforce覆盖标准操作的最显着的变化可能与Lightning Experience相比略有不同。 Lightning Experience中将无法访问对象列表操作的任何覆盖。
具体而言,您可以在Salesforce Classic中为对象覆盖六个标准操作:

  • Object tab
  • Object list
  • Record view
  • Record edit
  • Record create
  • Record delete

在闪电体验中,前两个动作合并为一个页面,将对象归入主页。对象首页与对象列表类似,添加了对象选项卡的一些元素,例如最近的项目。其他的,如报告或工具,已经转移到用户界面的其他部分。
无论组织中的用户界面设置如何,“对象”选项卡和对象列表都可在“设置”中被覆盖。按照预期,覆盖对象选项卡操作将覆盖Lightning Experience中的对象主页。

但是,在Lightning Experience中,对象列表操作在用户界面中无法访问,因此无法将其解除。如果您的组织已经重写了任何对象的对象列表操作,那么当用户使用Lightning Experience时,该功能将不可用。如果在重写中有必要的功能,则需要找到其他方法使其可用。

在比较小的比例中,当显示在Lightning Experience中时,<apex:page>的showHeader和sidebar属性对Visualforce页面没有影响。标准的Salesforce Classic标题和侧边栏始终处于禁用状态,并且无法取消Lightning Experience标题和侧边栏。

Salesforce Classic中的许多相关列表在Lightning Experience中不受支持。 <apex:relatedList>组件不是解决此限制的方法。不错,尽管!

而且,真正的小问题是,将Visualforce页面呈现为PDF,其工作原理与Salesforce Classic完全一样,没有任何Lightning Experience视觉设计。这可能是你想要的,但是如果你想把页面渲染成包含Lightning Experience设计的PDF文件,那今天是不可能的。

那个外观和感觉的东西

你注意到的关于Lightning Experience的第一件事就是全新的视觉设计。如果您一直在开发Visualforce页面,您的下一个想法可能是,我的Visualforce页面将如何在Lightning Experience中查看。简短的回答是…好吧,让我们坐下来,好吗?
简短的回答是,除了抑制Salesforce Classic标题和边栏以及被Lightning Experience用户界面框住外,Visualforce页面在Lightning Experience中显示不变。

具体而言,当页面显示在Lightning Experience中时,由内置的Visualforce组件呈现的HTML不会更改,并且这些组件使用的Salesforce Classic样式表默认情况下由页面加载。其效果是,使用<apex:inputField>,<apex:outputField>,<apex:pageBlock>组件以及与Salesforce Classic可视化设计相匹配的其他粗糙和精细组件的页面仍然与该可视化设计相匹配。您在Lightning Experience中获得一小部分Salesforce Classic。

但是,如果您使用的是相对没有风格的Visualforce组件,或者使用了自己的组件和标记,并且开发了自己的样式表,而不是使用默认的Salesforce样式,那么页面也显示为不变,保留了您很难开发的样式。

换句话说,在Visualforce for Lightning Experience中,我们倾向于在现有页面的视觉设计中保持稳定性,而不是试图将其动态调整为Lightning Experience。

也就是说,如果你对于新的视觉设计和我们一样兴奋,那么根据你想要投入多少工作,你可以采用这种方式来减小或者减小这个设计。我们不会介绍它在这里,但是有一个完整的单元,理解重要的视觉设计考虑事项,它显示了可能性的范围和用来实现它们的技术。