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时间的最佳使用。

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

Visualforce和闪电体验 – 了解闪电体验中应避免使用的功能

 

学习目标

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

  • 列出至少两个组件以避免在Lightning Experience中使用的页面上使用。
  • 确定三个Lightning Experience功能,您无法使用Visualforce页面或组件。

了解在闪电体验中要避免哪些特征

我们建议您避免在Lightning Experience中使用的页面上存在有限数量的Visualforce组件。此外,在Lightning Experience中使用Visualforce的一些功能时会有不同的表现。最后,Lightning Experience中有几个地方不能使用Visualforce页面或应用程序,或者它们可能无法正常工作。
闪电体验还在不断发展和壮大,安全港警报! – 我们希望随着时间的推移缩小这个名单。

闪电体验标题和导航菜单不能被抑制

在Lightning Experience中运行时,Visualforce页面始终显示标准的Lightning Experience用户界面。没有办法抑制或改变Lightning Experience标题或边栏。特别是,在“Lightning Experience”中显示时,<apex:page>的showHeader和sidebar属性对Visualforce页面没有影响。
这种行为是有意的。在Lightning Experience中显示的应用程序是Lightning Experience应用程序。如果您需要为您的应用程序提供完全自定义的界面,则需要在Salesforce Classic中运行它。

Salesforce Classic标题和边栏始终被抑制

在Lightning Experience中显示时,标准Salesforce Classic标题和侧边栏始终会被隐藏。特别是,在“Lightning Experience”中显示时,<apex:page>的showHeader和sidebar属性对Visualforce页面没有影响。
页面的行为就好像<apex:page>的showHeader和sidebar属性都设置为false。

注意

确定是否包含或取消标准Salesforce Classic样式表的<apex:page>的standardStylesheets属性不受Lightning Experience的影响。也就是说,在Lightning Experience中它默认为true,但是你可以改变它。

<apex:relatedList>和黑名单相关列表

有许多相关的列表在Lightning Experience中不被支持。这些相关的名单是“黑名单”,这意味着他们被明确阻止使用。正如您所期望的那样,这些相同的相关列表在Visualforce中使用<apex:relatedList>标记列入黑名单。
有关Lightning Experience不支持哪些相关列表的详细信息,请参阅联机帮助中的“数据访问和视图:闪电体验中的不同或不可用”。

避免 <apex:iframe>

尽管在Lightning Experience的Visualforce页面上使用<apex:iframe>并非不可能,但我们建议避免使用它。
在Lightning Experience中显示时,Visualforce页面将封装在各自的iframe中。正如在探索Visualforce应用程序容器中详细讨论的那样,这对页面的行为有很多重要的影响。向iframe堆栈添加额外的级别会增加环境的复杂性。

如果您真的了解iframe以及它们如何影响DOM和JavaScript,则可以管理这种复杂性。但是除非你已经在使用嵌套的iframe,否则很难调试问题。出于这个原因,我们建议您避免在Lightning Experience中使用的页面上使用此标签。

不,真的,不要直接设置window.location

在这一点上,我们可能听起来像一个破碎的记录,但这很重要。如果你的页面的JavaScript代码直接设置了window.location变量,当页面显示在Lightning Experience中时,这个功能将不起作用。您必须修改此代码才能使页面在Lightning Experience中运行。
有关详情,请参阅管理导航单元。

sforce.one不是Salesforce Mobile-Only

sforce.one JavaScript实用程序对象可用于Salesforce应用程序和Lightning Experience中的Visualforce页面。如果您一直在使用sforce.one对象作为判断您的页面是否在移动或桌面环境中运行的方式,则需要更新代码。
使用其中一种记录的方法来区分Salesforce Classic,Salesforce应用程序和Lightning Experience环境。 Visualforce,Apex和JavaScript中提供了支持的技术。

有关完整的详细信息,请参阅在Classic和Lightning Experience之间共享Visualforce页面单元。

动作重写的更改

对于可能难以解决的事情,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时,该功能将不可用。如果在重写中有必要的功能,则需要找到其他方法使其可用。

此表列出了您可以在安装程序中替代对象的标准操作,以及三种不同用户体验中覆盖的操作。

在设置中覆盖 Salesforce Classic 闪电的经验 Salesforce应用程序
选项卡 对象选项卡 对象主页 搜索
列表 对象列表 n/a 对象主页
视图 记录视图 记录主页 记录主页
编辑 记录编辑 记录编辑 记录编辑
创建 纪录创建 纪录创建 纪录创建
删除 记录删除 记录删除 记录删除

注意

“n/a”并不意味着您不能访问标准行为,也并不意味着您不能覆盖标准行为。 这意味着你不能访问覆盖。 这是覆盖的功能,不可用。

Visualforce和闪电体验 – 了解重要的视觉设计注意事项

学习目标

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

  • 描述改变内置Visualforce组件样式的两种方法。
  • 描述可以使用CSS样式表进行更改的Salesforce Classic和Lightning Experience样式之间的差异。
  • 描述将Salesforce Lightning设计系统应用于Visualforce页面的两种方法。

了解重要的视觉设计注意事项

无论是在Salesforce Classic还是Lightning Experience中运行,Visualforce页面都是一样的,除非您重新修改它们以适应适当的用户界面上下文。显示用户界面元素的内置Visualforce组件不容易重新配置,以与Lightning Experience外观相匹配。
具体而言,当页面显示在Lightning Experience中时,由内置的Visualforce组件呈现的HTML不会更改,并且这些组件使用的Salesforce Classic样式表默认情况下由页面加载。其效果是,使用<apex:inputField>,<apex:outputField>,<apex:pageBlock>组件以及与Salesforce Classic可视化设计相匹配的其他粗糙和精细组件的页面仍然与该可视化设计相匹配。您在Lightning Experience中获得一小部分Salesforce Classic。

这是我们的一般建议,现在,对于现有的网页,你不要试图去适应闪电体验的视觉设计。闪电体验仍在不断发展,自己的造型搭配意味着你正在追逐一个移动的目标。这是工作。

不过,在某些情况下,您会希望某些页面与Lightning Experience的视觉效果更加匹配。对于新的页面,或者如果你愿意做一些工作,有一些很棒的工具可以用来创建完全符合Lightning Experience的页面。

影响标准件的样式

Visualforce为调整或覆盖标准组件的样式提供了一系列选项。如果您的目标是对这些组件的外观进行适度的更改,则使用这些选项的努力也是同样适度的。我们来看看可用于影响样式的一些工具。

个别组件样式

生成HTML的Visualforce组件具有传递样式和styleClass属性。这些属性允许您使用自己的样式和样式类来控制生成的HTML的外观和风格。样式允许您直接在组件上设置样式,而styleClass则允许您为别处定义的样式附加类。例如,以下代码设置<apex:outputText>的类并应用样式。

<apex:page>

    <style type="text/css">
        .asideText { font-style: italic; }
    </style>

    <apex:outputText style="font-weight: bold;" 
        value="This text is styled directly."/>

    <apex:outputText styleClass="asideText" 
        value="This text is styled via a stylesheet class."/>

</apex:page>

添加一个自定义样式表

您可以使用静态资源和<apex:stylesheet>标记将自己的自定义样式表添加到任何Visualforce页面。例如,要添加一个样式表作为名为“AppStylesheet”的静态资源上传,请在页面中添加以下内容。

<apex:stylesheet value="{!$Resource.AppStylesheet}"/>

然后,您可以引用样式表中包含的任何样式,并在Visualforce标记styleClass属性中引用它们,就像我们之前使用asideText样式所做的那样。
这是将CSS样式定义添加到Visualforce页面的推荐方法,因为它共享页面之间的样式表,并最小化您需要添加到每个页面的标记。

Salesforce Lightning设计系统是用于添加样式表的这种方法的例外。闪电设计系统是一个梦幻般的全新的网页造型工具,我们将在不久后详细讨论。

尽管您可以将Lightning设计系统作为静态资源上传,并使用<apex:stylesheet>进行引用,但还有一种更简单的方法:只需在页面标记中的任意位置包含<apex:slds />即可。

闪电体验中的不同风格

仅当您的页面在Lightning Experience中运行时才加载自定义样式表,请使用以下标记。这与在经典和闪电体验之间共享Visualforce页面中的Visualforce标记示例类似。

<apex:page standardController="Account">

    <!-- 基础样式 -->
    <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 'app-styles.css')}" />
    
    <!-- 闪电桌面额外的样式 -->
    <apex:variable var="uiTheme" value="lightningDesktop" 
        rendered="{!$User.UIThemeDisplayed == 'Theme4d'}">
        <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 'lightning-styling.css')}" />
    </apex:variable>

    <!-- 其余的页面 -->
    
</apex:page>
好的,这些都是工具。让我们看看接下来使用它们的一些技巧。

样式的策略和建议

要创建与Lightning Experience可视化设计相匹配的Visualforce页面,请使用Lightning Design System创建新页面。在Visualforce页面中使用Lightning Design System有两种方法。
在详细讨论之前,我们先考虑一下更高的层次,并考虑将闪电体验风格应用于网页的不同策略。具体来说,我们来谈谈你现有的页面。

有两种方法可以影响现有页面的样式,使其看起来更像闪电体验。

  • 更改标记以在页面中应用新的样式更改。
  • 更改样式表中现有标记更改的样式规则。

这些都不是/或。您可以单独使用或组合使用它们。

正确使用Lightning Design System意味着使用Lightning Design System样式表和全新的标记来显示Visualforce页面。同样,这是匹配Lightning Experience可视化设计的唯一支持的方法。

要做到这一点,您可以从他们的网站下载Lightning Design System样式表,并像使用其他样式表一样使用它们,也可以将<apex:slds>组件添加到Visualforce页面的标记中。 <apex:slds>组件允许您引用Lightning Design System样式表,而无需将其上载为静态资源,从而简化了页面的语法并防止您达到250 MB的静态资源限制。

使用<apex:slds>带有自己的一套准则和注意事项。如果您想了解更多信息,请参阅Lightning Design System徽章或查看参考资料部分的Visualforce Developer Guide链接。

也可以添加Lightning Design System样式表,并修改您的页面以使用它们。这是多少工作取决于你想如何紧密匹配Lightning Experience以及代码中的特定标记和组件。虽然以这种方式取得体面的结果是可能的,但是,这不是我们推荐的方法。闪电设计系统被设计用于特定的标记,这根本不是Visualforce发出的。有一个“阻抗不匹配”,虽然不是致命的,但当你走这条路时,肯定是你的鞋子里的一块严重的石头。

最后,还有另外一种方法:为现有的(或新的)样式表添加新的规则和样式,使现有的标记看起来更像Lightning Experience。如果您的页面已经大部分使用自己的样式表,那么这种方法可能适合您。相反,如果您主要使用内置的Visualforce组件和Salesforce Classic样式,则需要覆盖Salesforce Classic样式表中的样式。

尽管这在技术上是可行的,但我们希望阻止您采取这种方法。它将依赖关系引入到您不想拥有的标记和样式中。这些依赖关系位于由内置的Visualforce组件呈现的HTML的结构,ID和类中。我们希望在这里真正清楚:由内置的Visualforce组件呈现的HTML是内部实现细节,如有更改,恕不另行通知。如果您在自己的样式表中有依赖关系,那么您的样式将最终中断。

Salesforce闪电设计系统

闪电设计系统是用于构建类似闪电体验的企业应用程序的设计框架。它包含一个复杂的CSS框架,一组图形资产和Salesforce Sans字体。您可以使用闪电设计系统构建看起来非常华丽的页面和应用程序,并与Lightning Experience用户界面完美匹配。
闪电设计系统旨在使客户和合作伙伴轻松匹配闪电体验的外观和感觉。它还包括可以自定义外观和风格以匹配自己品牌颜色等的工具,同时仍然与整体Lightning Experience设计保持一致。

闪电设计系统如此之大,如此令人兴奋……我们不打算详细介绍在这里使用闪电设计系统。因为我们已经写了一个关于使用它的整个模块,Lightning Design System。它解释了如何获得Lightning Design System,使用它来设计页面的基本概念,以及如何将这些概念应用于使用Visualforce构建Lightning Experience应用程序。

闪电设计系统是一个很大的模块,你必须努力获得这个徽章。虽然我们希望保存这个模块的细节,但是我们不想让你完全挂在这里。那么,让我们介绍一下如何在Visualforce中使用Lightning Design System。

首先要知道的是,闪电设计系统采用了新的标记结构和样式类。出于这个原因,最好使用新的页面和应用程序。它建立在现代浏览器功能的基础上,并利用最新的标记和样式最佳实践。尽管我们都喜欢它,Visualforce已经有一段时间了。在它生成的HTML和客户页面中的静态代码之间,大多数组织将发现将Lightning设计系统应用于现有页面具有挑战性。

闪电设计系统模块专注于创建新的页面和应用程序,并且对该徽章进行评分是了解它的最佳方式。完成该模块后,您将了解如何使用Lightning设计系统,以及如何计划周围的开发。

Visualforce和闪电体验 – 管理导航

学习目标

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

  • 描述用于控制从一个页面到另一个页面的三种“经典”Visualforce机制。
  • 描述哪些技术在Lightning Experience中不起作用。
  • 列出至少三个闪电体验导航事件,以及如何发送。

管理导航

应用程序流和导航在许多方面是应用程序设计的核心。 Visualforce提供了多种添加导航元素和指导应用程序流的方法。 Lightning Experience添加了自己的应用程序流程,导航元素和机制,以影响用户在使用Salesforce时的位置。
好消息是,“经典”的Visualforce导航继续工作。更好的消息是您的Visualforce页面也可以利用新的Lightning Experience机制。

导航闪电的经验

在我们谈论Visualforce导航的细节之前,以及如何创建它以使其在Salesforce Classic和Lightning Experience中起作用之前,我们先谈谈导航。 “导航”我们究竟意味着什么?
我们可能通过导航的第一件事是屏幕上的用户界面元素。你点击一下,发生什么事情。例如,您可以单击导航菜单中的“帐户”项目,然后转到“帐户”对象主页。您单击新建按钮,并出现记录条目窗体。您从快速操作菜单中选择自定义操作,然后启动自定义过程。等等。这些按钮和菜单项是导航元素。

导航系统(Lightning Experience中的用户界面)的设计与Salesforce Classic有很大不同。我们不打算在这里谈论这些差异,但是当您在两种用户体验之间切换时,您会希望熟悉所有事情的动向。您可以在Trailhead的导航闪电体验和设置单元中了解更多关于此的信息。

另一种较不明显的导航类型是上述“发生了什么”部分。在幕后,Salesforce决定在菜单中选择某个项目时发生的情况,或者单击链接或按钮。大部分导航已经内置到Salesforce中,而其他方面则是可定制的 – 例如,使用Visualforce页面覆盖操作。但是,所有这些导航都是由Salesforce编写的代码管理的。

然后在自己的应用程序中导航 – 使用您的代码来控制应用程序流的应用程序。当你的自定义操作打开一个表单,用户点击保存,你去哪里?当你的运行代码决定下一个用户应该去哪里,并在那里发送它们。这就是我们要在这个单元里讨论的内容。

经典的Visualforce导航
“经典”Visualforce导航可以归结为“在操作方法结束时会发生什么”。操作方法返回PageReference对象,其中包含用户要导航到的位置的详细信息,然后Visualforce框架将处理将正确的响应发送回用户的浏览器。而且,好消息,这一切仍然有效。
还要记住标准控制器从其操作方法中返回一个PageReference。因此,无论您使用的是标准控制器还是您自己的自定义控制器代码,您的现有导航都可以按照您的预期继续工作。

经典Visualforce导航

“经典”Visualforce导航可以归结为“在操作方法结束时会发生什么”。操作方法返回PageReference对象,其中包含用户要导航到的位置的详细信息,然后Visualforce框架将处理将正确的响应发送回用户的浏览器。而且,好消息,这一切仍然有效。
还要记住标准控制器从其操作方法中返回一个PageReference。因此,无论您使用的是标准控制器还是您自己的自定义控制器代码,您的现有导航都可以按照您的预期继续工作。

现代Visualforce导航

所以,如果经典的Visualforce导航工作,为什么我们仍然在谈论这个?我们甚至在谈论什么?我们只想对你说一个字。只是一个字。你在听么? …“JavaScript”。
JavaScript有一个很好的未来,而今天就在这里。许多Visualforce开发人员在他们的应用程序中大量使用JavaScript,并且这种使用持续增长。经典的Visualforce工作,并将继续工作很长一段时间。但是,随着开发人员采用远程对象和JavaScript远程等Visualforce功能,他们更多的应用程序的行为从服务器端迁移到浏览器和JavaScript,在那里没有PageReference这样的事情。

在Lightning Experience(和Salesforce应用程序)世界中,有一些用于在JavaScript中构建导航的规则和工具。我们将会介绍一些规则,主要是关于不该做的事情。先谈谈正确的做事方式吧。

Lightning Experience使用事件管理导航。导航事件框架作为一个JavaScript实用程序对象提供,该对象提供了许多可以直接创建程序化导航的功能。在运行Lightning Experience时,sforce.one对象会自动添加到Visualforce页面。这个对象提供了一些函数调用函数时触发导航事件。要使用这些功能,您可以直接从页面的JavaScript代码中调用它们,也可以将调用作为单击(或其他)处理程序附加到页面上的元素。

重要

sforce.one对象在Salesforce Classic中不可用。任何使用它的代码都应该首先测试sforce.one的存在。

sforce.one对象提供以下功能。引用来自sforce.one对象的使用虚线符号的函数。例如:sforce.one.navigateToSObject(…)。

功能 描述
back(​[refresh]) 导航到sforce.one历史中保存的以前的状态。这相当于单击浏览器的“后退”按钮。
navigateToSObject(​recordId​[, view]) 导航到由recordId指定的sObject记录。
navigateToURL(​url​[, isredirect]) 浏览到指定的网址。
navigateToFeed(​subjectIdtype) 导航到指定类型的供稿,其范围为subjectId。
navigateToFeedItemDetail(​feedItemId) 导航到特定的feed项目,feedItemId和任何关联的注释。
navigateToRelatedList(​relatedListIdparentRecordId) 导航到parentRecordId的相关列表。
navigateToList(​listViewId​, listViewNamescope) 导航到listViewId指定的列表视图,listViewId是要显示的列表视图的ID。
createRecord(​entityName​[, recordTypeId]) 打开页面为指定的entityName创建新记录,例如“Account”或 “MyObject__c”。
editRecord(​recordId) 打开页面以编辑由recordId指定的记录。

有关使用这些函数的更多详细信息及其接受的参数,请参阅本机资源中的使用sforce.one对象的导航。

导航问题,以及如何解决这些问题

在JavaScript中构建Visualforce导航的第一条规则是:不要直接设置window.location。在JavaScript中构建Visualforce导航的第二个规则是:不要直接设置window.location。

不要直接设置window.location

好的,无偿的重复和电影的参考,这里有什么大不了的?这很简单。当在闪电体验您的网页没有window.location设置!还记得之前关于Visualforce“容器”的讨论,还有一个关于iframe的内容,Lightning Experience是某种健康俱乐部? (SPA单页申请。)这是其中的一个东西。 Visualforce iframe不能直接访问window.location的值,所以你不能设置它。如果你的代码依赖于设置,它会中断。也就是说,通过设置window.location来触发导航的动作将停止导航到您期望的任何位置。

实际上有一个解决这个限制的方法,但是你不应该使用它。原因是,如果绕过sforce.one中的导航功能,您的导航事件将不会在Lightning Experience导航堆栈中进行跟踪。该堆栈提供了有用的功能,例如说明重定向等的后退按钮。 Lightning Experience(特别是Salesforce应用程序)中的许多功能都依赖于包含所有导航事件的堆栈。确保您正确使用它是值得的。

Salesforce Classic问题

所以,是的,这是一个…的东西。不幸的是,当您的页面在Salesforce Classic中运行时,sforce.one实用程序对象不可用。在这种情况下,你必须使用window.location。好消息是,在Salesforce Classic中,window.location可用。坏消息是,这个限制意味着你将不得不添加一个丑陋的if块给你的代码。考虑将导航功能包装在处理这种复杂性的实用程序方法中,以便您的主要导航逻辑可以很简单。

静态网址

不要将静态URL用于Salesforce资源。也就是说,如果要添加一个链接来编辑联系人记录,请不要使用link =’/’+ accountId +’/ e’等静态模式创建链接。在某些情况下,这是有效的,但在其他情况下则不行。相反,尝试以下方法之一:

  • 在Visualforce标记中,使用 {!URLFOR($Action.Contact.Edit, recordId)}
  • 在JavaScript中,使用 navigateToSObject(recordId)

有查看,创建,编辑等操作和功能。使用它们,而不是URL字符串。

Visualforce和闪电体验 – 在经典体验和闪电体验之间共享Visualforce页面

学习目标

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

  • 列出Salesforce Classic和Lightning Experience共享页面的两个好处。
  • 描述用户所请求的用户界面上下文与用户实际所在的用户界面上下文之间的区别。
  • 描述测试和确定当前用户的用户界面上下文的三种不同方式。

在经典和闪电体验之间共享Visualforce页面

我们建议尽可能创建Visualforce页面,无论这些页面是在Salesforce Classic还是Lightning Experience中运行。降低组织代码和配置复杂性的好处是显而易见的。还有一些上下文,例如Visualforce替代标准操作,你没有选择的地方。无论您是在Salesforce Classic,Lightning Experience还是Salesforce应用程序中运行,操作覆盖总是使用相同的页面。
然而,这是完全合理的,希望基于用户体验上下文在其中运行的行为或样式稍微或明显不同。在本单元中,我们将介绍各种创建可在所有用户体验中正常工作的页面的方法,以及代码如何检测特定上下文并对其进行更改。

在Visualforce标记中检测和响应用户体验上下文

使用$ User.UITheme和$ User.UIThemeDisplayed全局变量来确定当前的用户体验上下文。您可以在Visualforce表达式中使用这些变量,使页面适应Lightning Experience,Salesforce Classic和Salesforce应用程序。
这些全局变量返回一个唯一标识当前用户界面上下文的字符串。 $ User.UITheme和$ User.UIThemeDisplayed的可能值是相同的:
  • Theme1 – 已过时的Salesforce主题
  • Theme2-Salesforce Classic 2005用户界面主题
  • Theme3-Salesforce Classic 2010用户界面主题
  • Theme4d – 现代“闪电体验”Salesforce主题
  • Theme4t-Salesforce移动应用程序Salesforce主题
  • PortalDefault-Salesforce客户门户主题
  • Webstore-Salesforce AppExchange主题

两个变量的区别在于$ User.UITheme返回用户应该看到的外观,而$ User.UIThemeDisplayed返回用户实际看到的外观。例如,用户可能有首选项和权限来查看Lightning Experience外观,但是如果他们使用的浏览器不支持该外观(例如,旧版本的Internet Explorer),则$ User.UIThemeDisplayed返回一个不同的值。一般来说,你的代码应该使用$ User.UIThemeDisplayed。
使用这些主题全局变量的最简单的方法是在布尔表达式中使用一个,如{! $ User.UIThemeDisplayed ==“Theme3”},在组件的呈现属性。只有页面出现在所需的用户界面上下文中时,组件才会显示。

<apex:outputText value="This is Salesforce Classic." 
    rendered="{! $User.UIThemeDisplayed == 'Theme3' }"/>
虽然您可以在单独的用户界面元素上使用此技术,但是如果将较大的标记块包装到<apex:outputPanel>或类似的块级别组件中,则通常会更有效,然后为每个想要呈现的不同UI创建单独的块。然后将主题测试放置在块的呈现属性上,而不是单个组件。这不仅应该表现得更好,你的代码将不那么复杂。
<apex:outputPanel rendered="{! $User.UIThemeDisplayed == 'Theme3' }">
    <apex:outputText value="This is Salesforce Classic."/>
    <apex:outputText value="These are multiple components wrapped by an outputPanel."/>
</apex:outputPanel>
<apex:outputPanel rendered="{! $User.UIThemeDisplayed == 'Theme4d' }">
    <apex:outputText value="Everything is simpler in Lightning Experience."/>
</apex:outputPanel>
您可以使用的另一个策略是动态选择要包含在页面上的样式表,并为每个主题提供不同的样式表。这比您想象的要复杂一些,因为<apex:stylesheet>标记没有自己的渲染属性。在这种情况下,您必须将样式表组件包装在具有渲染属性的另一个组件中。以下是如何为Salesforce支持的三个现代主题中的每一个提供不同样式表的示例。
<apex:page standardController="Account">

    <!-- Salesforce Classic "Aloha" theme -->
    <apex:variable var="uiTheme" value="classic2010Theme" 
        rendered="{!$User.UIThemeDisplayed == 'Theme3'}">
        <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 
                                         'classic-styling.css')}" />
    </apex:variable>
    
    <!-- Lightning Desktop theme -->
    <apex:variable var="uiTheme" value="lightningDesktop" 
        rendered="{!$User.UIThemeDisplayed == 'Theme4d'}">
        <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 
                                         'lightning-styling.css')}" />
    </apex:variable>
    
    <!-- Salesforce mobile theme -->
    <apex:variable var="uiTheme" value="Salesforce1" 
        rendered="{!$User.UIThemeDisplayed == 'Theme4t'}">
        <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 
                                         'mobile-styling.css')}" />
    </apex:variable>

    <!-- Rest of your page -->
    
    <p>
        Value of $User.UIThemeDisplayed: {! $User.UIThemeDisplayed }
    </p>
</apex:page>

超越基础

这是使用<apex:variable>的一种不寻常的方法,因为我们实际上并不关心创建的变量的值。相反,我们只需要一个组件,它不会自己提供任何输出来包装<apex:stylesheet>组件。您可以将其视为<apex:variable>“借出”其呈现的属性到包装的<apex:stylesheet>组件。

我们并不关心变量本身,这是一件好事,因为另外一个不寻常的方面就是变量不是真正创建的!功能或错误?我们称之为…未定义的行为,并避免在其他地方使用uiTheme变量。

在JavaScript中检测和响应用户体验上下文

在JavaScript代码中检测当前用户体验上下文非常重要,如果您在页面和应用程序中使用JavaScript。使用正确的技术来管理JavaScript代码中的导航特别重要。在您的JavaScript代码中处理UX上下文检测的最佳方法是使用可在任何地方使用的实用函数库。
起初,这看起来很简单,只需测试Visualforce标记中提供的相同全局变量即可。也许这样的事情
function isLightningDesktop() {
    return( "{! $User.UIThemeDisplayed }" == "Theme4d");
}

如果您将此代码添加到Visualforce页面,则它可以工作。
这是问题。只要将此代码移动到静态资源中(这是代码组织的最佳实践,提高性能和其他原因),它就会停止工作,因为全局变量在静态资源中不可用。不会为标记或表达式或全局处理静态资源,或者根本不处理静态资源。他们只是服务。这就是为什么我们称之为静态资源。 😉

那么,我们如何做到这一点,而不是在每个需要测试用户体验上下文的页面中添加重复的JavaScript代码呢?通过创建一个非常简单的页面,只需将$ User.UIThemeDisplayed值插入到正确的JavaScript上下文中,然后使用<apex:include>将其添加到页面。然后我们可以在我们的实际工具代码中测试注入的值。

下面是我们用于将$ User.UIThemeDisplayed全局变量注入到JavaScript上下文中的“shim”Visualforce页面,以及包含使用它的JavaScript实用程序静态资源。

<apex:page docType="html-5.0" applyBodyTag="false" applyHtmlTag="false"
           showHeader="false" standardStylesheets="false">

<!-- UIUTILS SCRIPT -->
<apex:includeScript value="{!URLFOR($Resource.ForceUI)}"/>
<!-- UIUTILS SCRIPT -->

<!-- UITHEME INJECTOR -->
<script type="text/javascript">
    (function(myContext){
        // 如果我们已经存在,不要覆盖自己。
        myContext.ForceUI = myContext.ForceUI || {};
        
        // 因为这是Visualforce,不是一个静态资源,
        // 我们可以在表达式中访问一个全局变量。
        myContext.ForceUI.UserUITheme = '{! $User.UIThemeDisplayed }';
    })(this);
</script>
<!-- UITHEME INJECTOR -->

</apex:page>

这个页面有两件事。首先,它抽取包含实际工具方法代码的JavaScript静态资源。 (其中,我承诺,我们将继续讨论)。其次,它有一个内联JavaScript,因为它在Visualforce页面中运行,而不是静态资源,因此可以使用全局主题评估表达式。此脚本在ForceUI实用程序对象内设置一个变量。这会将Visualforce的主题值复制到JavaScript中,以便可以通过静态资源中的JavaScript代码进行引用。

这个“页面”不是直接访问,而是包含在你的真实页面中。这使得在这些页面中添加JavaScript实用程序方法成为单行的工作。 (如果你记得#include不是你在社交媒体上做的事情,那么举起你的手,就在那儿,现在让我们把那些孩子从那个草坪上拿走吧!)

我们来看看如何使用它。这是一个非常简单的页面,展示了如何使用<head>块中的<apex:include>组件将JavaScript实用程序方法添加到页面中。在页面底部是一小段JavaScript,演示了如何使用JavaScript中的实用工具方法。我们在代码中加入了重点来突出这些元素。

<apex:page standardController="Account" extensions="ForceUIExtension"
           showHeader="false" standardStylesheets="false"
           applyHtmlTag="false" applyBodyTag="false"
           docType="html-5.0" title="ForceUI Utilities">

<html lang="en">
  <head>
    <title>ForceUI Utilities</title>
    <apex:include pageName="UIThemeUtilsInclude"/>
  </head>

  <body>
      
    <h1>ForceUI Utilities</h1>
    
    <p>This is a page used for testing different ways of determining 
       the user interface context in which it's being displayed.</p>
    
    <h2>$User.UITheme Global Variable</h2>
    
    <p><label>$User.UITheme</label>: {! $User.UITheme }</p>
    <p><label>$User.UIThemeDisplayed</label>: {! $User.UIThemeDisplayed }</p>
    
    
    <h2>UIUtils JavaScript</h2>
    
    <p><label>ForceUI.UserUITheme</label>: 
       <span id="UserUIThemeJS">(loading...)</span></p>
      
    <p><label>isSalesforce1()</label>: 
       <span id="isSalesforce1JS">(loading...)</span></p>
      
    <p><label>isLightningExperience()</label>: 
       <span id="isLightningExperienceJS">(loading...)</span></p>
      
    <p><label>isSalesforceClassic()</label>: 
       <span id="isSalesforceClassicJS">(loading...)</span></p>

    <script type="text/javascript">
      document.addEventListener('DOMContentLoaded', function(event){
          // 仅诊断 - 不要直接使用此值
          document.getElementById('UserUIThemeJS').innerHTML = ForceUI.UserUITheme;
          // 而是使用这些实用方法
          document.getElementById('isSalesforce1JS').innerHTML = 
              ForceUI.isSalesforce1();
          document.getElementById('isLightningExperienceJS').innerHTML = 
              ForceUI.isLightningExperience();
          document.getElementById('isSalesforceClassicJS').innerHTML = 
              ForceUI.isSalesforceClassic();
      });
    </script>
  </body>
</html>
</apex:page>
在您的组织,Lightning Experience,Salesforce Classic甚至Salesforce应用程序中查看此页面,以确认这些值取决于环境而变化。
最后(#finally),这里是包含JavaScript实用程序函数的实用程序库,它允许您创建表达式,以根据运行的用户界面上下文有条件地影响应用程序JavaScript代码的结果。
// 这是一个匿名的自动执行的函数关闭thingie,
// 像所有这些天凉爽的孩子一样
(function(myContext){

    // 处理可能的执行顺序问题。
    // 如果我们已经存在,不要覆盖自己。
    myContext.ForceUI = myContext.ForceUI || {};

    // 根据本地UserUITheme值进行简单字符串比较的实用程序方法。
    // 该值从Visualforce页面注入,
    // 以允许$ User.UIThemeDisplayed全局的表达式评估。
    myContext.ForceUI.isSalesforceClassic = function() {
        return (this.UserUITheme == 'Theme3');
    }
    myContext.ForceUI.isLightningExperience = function() {
        return (this.UserUITheme == 'Theme4d');
    }
    myContext.ForceUI.isSalesforce1 = function() {
        return (this.UserUITheme == 'Theme4t');
    }
})(this);

除了自执行函数可能不熟悉的语法之外,这里的代码是非常简单的。代码执行的结果是一个实用程序对象ForceUI,添加到您的页面的全局范围。该对象从早期的Visualforce填充页面中的JavaScript注入器接收$ User.UIThemeDisplayed全局变量的值。该值保存在一个名为UserUITheme的本地变量中,您应该将其视为一个私有的实现细节。切勿直接访问它!

该对象的公共API被暴露为一系列的函数,isLightningExperience()等等,你在代码的其余部分中使用,如上图所示。您甚至可以添加自己的附加功能,例如,从桌面或从简单的Visualforce中分配one.app。

确定Apex中的用户体验环境

使用UserInfo.getUiTheme()和UserInfo.getUiThemeDisplayed()系统方法确定Apex代码中的当前用户体验上下文。当你的控制器动作方法或属性需要在不同的上下文中表现不同时,你可以使用它们。
以下示例说明了如何通过在控制器扩展中通过getter方法使用这些方法来使用这些方法。
public with sharing class ForceUIExtension {

    // Empty constructor, required for Visualforce controller extension
    public ForceUIExtension(ApexPages.StandardController controller) { }
    
    // Simple accessors for the System.UserInfo theme methods
    public String getContextUserUiTheme() {
        return UserInfo.getUiTheme();
    }    
    public String getContextUserUiThemeDisplayed() {
        return UserInfo.getUiThemeDisplayed();
    }    

}
您当然可以使用Apex代码中的值,而不是直接返回方法调用结果。
这些Apex系统方法返回一个唯一标识当前用户界面上下文的字符串。这些方法返回的可能值与$ User.UITheme和$ User.UIThemeDisplayed全局变量返回的值相同。
Theme1 – 已过时的Salesforce主题
  • Theme1 – 已过时的Salesforce主题
  • Theme2-Salesforce Classic 2005用户界面主题
  • Theme3-Salesforce Classic 2010用户界面主题
  • Theme4d – 现代“闪电体验”Salesforce主题
  • Theme4t-Salesforce移动应用程序Salesforce主题
  • PortalDefault-Salesforce客户门户主题
  • Webstore-Salesforce AppExchange主题

在服务器端控制器代码中使用这些方法应该很少,至少与提供不同的Visualforce标记或JavaScript代码相比。对于您的控制器和控制器扩展代码来说,在UX上下文中是最好的做法。让您的前端代码(无论是Visualforce还是JavaScript)处理用户界面差异。

通过SOQL和API访问查询闪电体验

虽然我们不推荐这种技术,但您可以直接使用SOQL查询当前用户的首选用户体验。
基本的SOQL查询如下。
SELECT UserPreferencesLightningExperiencePreferred FROM User WHERE Id = 'CurrentUserId'
结果是一个原始的偏好值,你需要转换成可用的东西。
以下是运行上述SOQL查询的最简单的Visualforce页面,并在页面上显示结果。
<apex:page>

<script src="/soap/ajax/36.0/connection.js" type="text/javascript"></script>
<script type="text/javascript">

    // 查询偏好值
    sforce.connection.sessionId = '{! $Api.Session_ID }';
    var uiPrefQuery = "SELECT Id, UserPreferencesLightningExperiencePreferred " +
                      "FROM User WHERE Id = '{! $User.Id }'";
    var userThemePreferenceResult = sforce.connection.query(uiPrefQuery);
    
    // 在页面上显示返回的结果
    document.addEventListener('DOMContentLoaded', function(event){
        document.getElementById('userThemePreferenceResult').innerHTML = 
            userThemePreferenceResult;
    });
</script>

<h1>userThemePreferenceResult (JSON)</h1>

<pre><span id="userThemePreferenceResult"/></pre>

</apex:page>
不鼓励直接查询用户的Lightning Experience偏好。结果将告诉您用户当前的首选项设置是什么,而不是用户的实际体验。有几种使用情况下,首选项值可能不会反映实际交付的用户体验。要确定当前请求中传递的实际用户体验,请使用$ User.UIThemeDisplayed或UserInfo.getUiThemeDisplayed()。

Visualforce和闪电体验 – 探索Visualforce应用容器

学习目标

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

  • 描述在Salesforce Classic中运行的Visualforce页面与在Lightning Experience中运行的相同页面之间的三个区别。
  • 描述需要更新才能在Lightning Experience中工作的两种常见代码模式。
  • 在Lightning Experience中运行时,列出对Visualforce页面默认值的两个更改。

探索Visualforce应用程序容器

Lightning Experience中的Visualforce与Salesforce Classic中的Visualforce最大的区别在于它运行的环境。在Salesforce Classic中,Visualforce“拥有”页面,请求和环境。 Visualforce是应用程序容器。但是在Lightning Experience中,Visualforce在包含在较大的Lightning Experience容器内的iframe中运行。
这种对执行上下文的更改对Visualforce页面可能影响整个Salesforce应用程序的方式有很多影响。我们将在这个单元中讨论这些变化,但是为他们自己的单位保存其中一些的全部细节。

注意

这个单位比其他的“在建”还要多一点。原因很简单:这里描述的问题的影响高度依赖于你的代码。我们非常努力地为你们“做好工作”,而且在大多数情况下,这里一点或者什么都不会显示出来。但我们无法预测您使用Visualforce的各种方式。这里我们概述Lightning Experience如何影响Visualforce的一般方面。当你和我们交谈时,当我们从你那里得到更多关于实际影响的信息时,我们可以提供关于如何解决具体问题的更多细节的解释。

外部闪电体验容器

我们从外部容器Lightning Experience应用程序开始。 Lightning Experience容器是一个“单页面应用程序”或SPA,可以在/one/one.app URL访问。 one.app页面加载,代码启动,应用程序代码接管环境。
单页面应用程序加载资源的过程(通常是静态的HTML shell和大量的JavaScript)既有趣又复杂。如果你已经使用了AngularJS或者React之类的JavaScript框架,那么你就非常熟悉以one.app的形式启动Lightning Experience的基础知识。说实话,完整的细节并不重要。你没有任何控制权,并且实现继续发展。

以下是重要的知识:Lightning Experience或one.app负责请求。您的Visualforce页面不是。您的页面需要在Lightning Experience强加给它的限制内工作。 Lightning Experience是父级环境,而Visualforce页面是子级环境。孩子需要服从父母。

其中一些约束条件(例如显示Visualforce页面的框架的大小)直接由Lightning Experience强制实施。他们更容易理解和使用,我们将在一分钟内讨论他们。

其他限制是隐含的,并不是由Lightning Experience实施,而是由运行它的浏览器实施。这些主要是安全性和JavaScript执行的限制。大多数页面不受这些安全约束的影响,而且那些通常会提前失败并带有明确的错误消息。 JavaScript错误很难发现和诊断,但是有一些通用的规则,我们稍后会介绍。

Visualforce iframe

当您的Visualforce页面在Lightning Experience中运行时,它将显示在HTML iframe中。一个iframe创建一个嵌入式浏览上下文,这个浏览上下文实际上是一个独立于主Lightning Experience浏览上下文的浏览器“窗口”。 iframe在Visualforce页面与其父项Lightning Experience应用程序之间创建一个边界。
在iframe中运行Visualforce页面的优点是,对于不需要访问或更改顶级浏览上下文的页面,在iframe中运行看起来几乎与Salesforce Classic中的页面一样运行。这就是为什么您不需要修改所有Visualforce页面以适应Lightning Experience的大量不同的幕后请求环境。这是支持Visualforce的“正常工作”策略的重要组成部分。

当然,另一方面是那些需要访问顶层浏览上下文的页面,还有一些需要改变的地方。我们将在下一节介绍一些细节。

如果您的页面与Salesforce之外的服务进行通信,则iframe边界也可能导致您需要更新组织的CORS设置,远程站点设置,clickjack设置或内容安全策略。由于这些依赖于Salesforce之外的安全策略和设置,因此我们无法提供特定更改的配方。我们在这里简单地提醒你注意。

新容器的影响

新的Visualforce容器 – 将Lightforce页面嵌入到Lightning Experience应用程序的iframe中 – 可以大致分为两类,我们将其称为安全性和范围。
再一次,我们要强调的是:很多,甚至是大多数Visualforce页面都不会受到这些问题的影响。但是对于那些,我们认为“预先警告已经被警告”。如果我们已经一起讨论过,你会更快地发现问题的根源。

安全影响

可能受到影响的安全要素包括以下内容。

  • 会话维护和更新
  • 认证
  • 跨域请求
  • 嵌入限制

我们已经简要地讨论了一些这些涉及跨域请求的项目。也就是说,当完整的浏览器窗口中的内容来自对不同服务器和服务的请求时,这些请求中的任何一个都可能会妨碍在没有准备好的情况下显示。如果有需要,您的任务就是准备这些服务,以处理在闪电体验范围内的要求。正如我们之前所说,细节有所不同,所以我们不能在这里提供具体的答案。

有一件事我们特别要提的是会话维护。我们这里所说的“会话”基本上就是您的浏览器从请求到请求重用的一种令牌,这样您就不必为每个请求输入用户名和密码。您经常需要使用全局变量$ Api.Session_ID访问当前会话。

这是要记住的事情。 $ Api.Session_ID根据请求的域返回不同的值。这是因为每当您跨越主机名边界(例如.salesforce.com到.visual.force.com)时,会话ID都会在会话期间发生变化。通常情况下,Salesforce会透明地处理域之间的会话切换,但是如果您要传递会话ID,请注意,您可能需要从正确的域重新访问$ Api.Session_ID以确保有效的会话ID。

Lightning Experience和Visualforce页面不仅保存在不同的浏览器上下文中,而且也来自不同的域。因此,尽管它全部显示在一个浏览器窗口中,但Visualforce iframe中的会话ID将不同于iframe之外的会话ID,而在Lightning Experience的另一部分中。 Salesforce和Lightning Experience在正常使用情况下处理此透明。但是如果你在派对上通过会议ID(通常不是一个好主意),你可能需要回顾一下你是如何处理它的。

范围影响

当我们谈论范围时,我们主要谈论以下几种事情。

  • DOM访问和修改
  • JavaScript范围,可见性和访问
  • JavaScript全局变量,如window.location

如果这个列表听起来很复杂或者令人困惑,不要担心,我们可以把它归结为简单易记的东西:不要碰别人的东西。具体而言,您的JavaScript代码(以及样式表规则)可能会影响页面浏览上下文中的元素(DOM节点,JavaScript变量等),但无法访问任何其他浏览上下文中的元素,闪电体验上下文。不要触摸其他上下文的东西!

实际上,你想要做这种事情的最常见的代码模式是操纵window.location导航到另一个页面。这是一个很常见的事情,我们已经写了关于这个特定问题的细节……当你完成这个模块的时候,你会厌倦听到这个问题,我们保证。

最后一个音符如果您是一位经验丰富的JavaScript开发人员,您可能已经在考虑通过使用contentWindow,window.parent等来了解如何处理“我无权访问父浏览上下文”问题。请不要。你可能会遇到同源策略(Visualforce和Lightning Experience来自不同的领域,请记住?)。即使你不这样做,你可能会用明显的,间歇性的错误代替显而易见的错误。你想在哪里花时间:做正确的事情,还是调试?

做正确的事情意味着调用我们在Visualforce页面中提供的API,主要用于导航。如果您确实需要跨越边界影响事物,请使用window.postMessage将消息发送到另一个帧中的接收代码。

Visualforce默认值和闪电体验的环境变化

当您的Visualforce页面在Lightning Experience中运行时,幕后会发生许多低级别更改。这些改变使得大多数页面在Lightning Experience容器中“正常工作”,有时你可以为他们在那里感到高兴。但是你仍然想知道他们正在发生,特别是当你在处理高级应用程序流时,或者解决一个棘手的问题时。
其中一些变化很简单,一旦你想到它们,就很明显。例如,在Lightning Experience中运行的Visualforce页面始终具有标准的Salesforce Classic标题和侧栏。其他变化并不明显,但同样有很大的影响。

<apex:page> showHeader和侧栏属性始终为false

这些属性会影响Visualforce页面上的Salesforce Classic标题和侧边栏。在Lightning Experience中运行页面时,Salesforce Classic标题和侧栏会始终被抑制,以支持Lightning Experience导航元素。没有相应的属性可以影响Lightning Experience标题或侧边栏,因为它们不能被抑制。
如果您的页面在Salesforce Classic和Lightning Experience之间共享,则仍然可以将这些属性设置为在Salesforce Classic中运行页面时要使用的值。

注意

确定是否包含或取消标准Salesforce Classic样式表的<apex:page>的standardStylesheets属性不受Lightning Experience的影响。也就是说,在Lightning Experience中它默认为true,但是你可以改变它。

sforce.one JavaScript工具对象

尽管sforce.one听起来像一个在Salesforce cantina中工作的机器人,但它实际上是一个实用程序对象,它提供了许多有用的功能,您可以在自己的JavaScript代码中使用这些功能。
在Lightning Experience或Salesforce应用程序中运行时,sforce.one会自动注入您的页面。您将在您的JavaScript调试器控制台和Web开发人员资源列表中看到它。没有什么需要添加的,也没办法压制它。 (可惜的是,在Salesforce Classic的Visualforce页面中无法获取sforce.one。)

sforce.one主要用于消除导航事件。完整的细节在即将到来的单位,管理导航。

____________________

*没有Salesforce酒吧。唉。

Visualforce和闪电体验 – 开发Visualforce页面以获得闪电体验

学习目标

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

  • 完成Lightning Experience开发环境的设置。
  • 描述在开发过程中查看Lightning Experience中Visualforce页面的两种不同方式。
  • 描述在开发过程中预览Visualforce页面和正式测试该页面的区别。
  • 创建一个测试矩阵,描述在对Visualforce页面进行正式测试时需要包含和测试的不同因素。

为闪电体验开发Visualforce页面

为Lightning Experience创建Visualforce页面和应用程序的开发过程在某些方面与Salesforce Classic的开发有很大的不同。在其他人中,你会发现它是一样的。主要区别在于您在开发过程中如何查看和测试您的页面。
在本单元中,我们将介绍设置开发环境的细节,然后介绍在构建过程中测试页面的“正确”方式的细节。好消息是,您需要使用Lightning Experience进行开发的过程与用于开发Salesforce移动页面的过程相同。

设置您的编辑器

您要设置的第一件事就是您将用于编写代码的编辑工具。无论您是为Lightning Experience,Salesforce Classic还是Salesforce应用程序创建页面,以及是否使用Developer Console,Force.com IDE或旧的安装编辑器,此过程都保持不变。
如果您已经有了首选的Visualforce编辑工具,则无需在此处执行任何操作。编写和保存您的Visualforce标记仍然完全相同。开发者控制台拥有自己的用户界面,在Lightning Experience和Salesforce Classic之间不会改变。安装程序中的编辑器也保持不变,在所有用户界面上下文中保留Salesforce Classic用户界面。当然,如果您使用的是本地工具(如Force.com IDE或许多第三方工具中的一种),则这些工具都有自己的用户界面。

一个例外是Visualforce开发模式页脚中的编辑器。如果您已经在用户设置中启用了开发模式,并且正在使用Salesforce Classic,那么使用开发模式页脚查看和编辑Visualforce页面的方式与您所期望的相同。如果您切换到Lightning Experience,然后使用传统的https://yourInstance.salesforce.com/apex/PageName URL模式访问页面,则可能会惊讶于在Salesforce Classic中找回自己。

这是预期的,当我们查看和测试您的Visualforce页面时,我们会进一步讨论它。现在,请了解Visualforce的开发模式仅适用于Salesforce Classic。

在开发过程中查看Visualforce页面

在开发Visualforce页面的同时查看是一个常见任务。虽然它不是正式意义上的“测试”,但是您当然希望能够与您所建立的功能进行交互,以确保正确的行为正在取得进展。这通常通过使用https://yourInstance.salesforce.com/apex/PageName URL模式访问页面来完成。虽然这仍然适用于审阅Salesforce Classic中的页面,但它不适用于检查Lightning Experience中的行为。
无论您的用户界面设置如何,您使用直接URL访问查看的页面都始终显示在Salesforce Classic中,也就是说,“经典”Visualforce容器。如果您创建具有Lightning Experience特定行为的Visualforce页面,则仅使用通常的直接URL访问权限就无法查看该行为。

超越基础

幕后造成这种情况的是什么?这很简单,真的。为了在Lightning Experience中查看您的页面,您需要访问Lightning Experience容器应用程序。这意味着访问/one/one.app。如果您正在访问,则无法访问/ apex / PageName。他们只是两个不重复的网址。

那么开发人员要做什么?您需要从Lightning Experience应用程序本身查看您的页面,以便它在Lightning Experience容器内运行。这意味着您需要导航到Lightning Experience中的页面,并且有多种方法可以做到这一点。

获取特定Visualforce页面的最简单方法是为其创建一个选项卡,然后通过应用程序启动器中的所有项目部分导航到该选项卡。一个更长远的方法是创建一个“In Development”应用程序,并在您处理它们时添加Visualforce标签,并在它们转入生产时移动或移除它们。由于这样做的控制已经移动了一下,下面是简短的说明。

  1. 从设置中,在快速查找框中输入应用程序,然后选择应用程序管理器。
    您应该看到Lightning Experience App Manager设置页面。
  2. 点击New Lightning App,然后在开发中为您的页面创建一个自定义的应用程序。
    考虑限制您的应用程序仅限于系统管理员,或者您为组织中的开发人员创建的配置文件。Assign app to limited profiles to control access

    您不需要用户在用户界面中将其添加到永久位置之前查看您的页面。

  3. 从设置中,在快速查找框中输入应用程序菜单,然后选择应用程序菜单。

    你应该看到应用程序菜单设置页面。

  4. 确保您的In Development应用程序在应用程序启动器中设置为可见。

    当你在这个时候,你可能想重新排列项目,甚至隐藏你不使用的应用程序。

    App Launcher app visiblity and order
  5. 从设置中,在快速查找框中输入标签,然后选择标签。

    您应该看到自定义选项卡设置页面。

  6. 在“Visualforce选项卡”部分中单击“新建”,然后为当前正在开发的页面创建一个自定义选项卡。

    使该选项卡仅可见于您的开发用户配置文件,并将该选项卡仅添加到您的In Development应用程序中。

    Make in development tabs only visible to developers
    Add tab to In Development app
  7. 对要添加到In Development应用程序中的每个页面重复上一步骤。为了将来添加新的页面,这是唯一需要的步骤。

尽管如此,在您处理页面的过程中,您可以轻松查看自己的页面,但与仅将网页名称输入到URL中并不相同。对于在Lightning Experience中测试页面的开销相似的方式,您可以在JavaScript控制台中键入以下内容:

$A.get("e.force:navigateToURL").setParams(
    {"url": "/apex/pageName"}).fire();
这个JavaScript触发了Lightning Experience的navigateToURL事件,相当于输入了经典的/ apex / PageName的URL – 你甚至可以在代码中看到这个URL模式。

注意

您目前需要使用Lightning Experience才能使用此技术。如果您使用的是Salesforce Classic,则JavaScript代码将失败。

为了使用起来更方便一些,请将以下小书签添加到浏览器的菜单或工具栏中。 (为了便于阅读,我们封装了这些代码。)

javascript:(function(){ 
    var pageName = prompt('Visualforce page name:'); 
    $A.get("e.force:navigateToURL").setParams(
        {"url": "/apex/" + pageName}).fire();})();
这个小书签提示您输入页面名称,然后触发事件直接导航到它。有用!
导航到正在处理的页面后,只需使用浏览器的重新加载命令即可在进行更改时刷新页面。

在多个环境中查看Visualforce页面

如果您正在创建将在Lightning Experience,Salesforce Classic和Salesforce应用程序中使用的页面,那么您需要在所有环境中查看这些页面。为此,您需要在多个浏览器和多个设备上打开该页面。
将在不同的Salesforce用户界面上下文中使用的Visualforce页面和外观因素在开发过程中很难进行审阅。您可以使用配置文件菜单中的环境选择器在Salesforce Classic和Lightning Experience之间来回切换,但这种情况会很快变老。您也可以使用浏览器的用户代理设置来模拟Salesforce移动环境,但这更麻烦。

相反,您将要使用多个浏览器甚至多个设备来查看您的页面。而且您还希望至少可以访问另外一个测试用户。以下是如何设置开发环境的示例。

主要发展环境
此环境是您在安装程序中对组织进行更改的位置,例如添加自定义对象和字段,也可能是编写实际代码的位置(如果使用开发人员控制台)。

  • 浏览器: Chrome
  • 用户:您的开发人员用户
  • 用户界面设置:Salesforce Classic
在此环境中查看您的页面在Salesforce Classic中的设计和行为。
闪电体验评论环境
这个环境是你在Lightning Experience中检查你的页面设计和行为的地方。

  • 浏览器:Safari或Firefox
  • 用户:您的测试用户
  • 用户界面设置:闪电体验
Salesforce移动审查环境
此环境用于检查您的页面在Salesforce应用程序中的设计和行为。

  • 设备:iOS或Android手机或平板电脑
  • 浏览器:Salesforce应用程序
  • 用户:您的测试用户
  • 用户界面设置:闪电体验

注意

这只是一个示例设置,您可以使用Salesforce Classic和Lightning Experience中的任何现代浏览器或移动设备。关键是要使用两种不同的浏览器,以便您可以同时访问Salesforce Classic和Lightning Experience,并使用实际设备来测试Salesforce应用程序。

这可能听起来相当复杂,初始设置起来有点麻烦,特别是如果你正在寻找编码的话。但请记住两件事。首先,一旦你成立,就完成了。其次,这个工作区不仅为您提供了一个很好的开发环境,还为您提供了正式测试页面所需的环境。因为你不会梦想在没有经过正式测试的情况下将网页投入生产,对吗?

测试您的Visualforce页面

这只是一个示例设置,您可以使用Salesforce Classic和Lightning Experience中的任何现代浏览器或移动设备。关键是要使用两种不同的浏览器,以便您可以同时访问Salesforce Classic和Lightning Experience,并使用实际设备来测试Salesforce应用程序。

这可能听起来相当复杂,初始设置起来有点麻烦,特别是如果你正在寻找编码的话。但请记住两件事。首先,一旦你成立,就完成了。其次,这个工作区不仅为您提供了一个很好的开发环境,还为您提供了正式测试页面所需的环境。因为你不会梦想在没有经过正式测试的情况下将网页投入生产,对吗?

测试您的Visualforce页面
测试您的Visualforce页面,然后将其部署到生产环境中是一项重要的开发任务。当您的组织采用Lightning Experience时,测试页面的过程变得更加复杂。
我们刚刚讨论了在开发页面时需要设置的环境,以进行快速,非正式的测试。这些环境的需求也适用于正式测试您的网页和应用程序。让我们来谈谈为什么你需要这些不同的环境,而不是重复它们。

在Lightning Experience和Salesforce Classic中测试页面的需求相当明显,但为什么不能在同一个浏览器中使用相同的用户来测试?事实上,你可以,你应该。您的用户可以在不同的用户界面之间来回切换,并且您应该确认您的页面在这些用户界面中工作。

但是,您也希望以更加独立和系统的方式来测试页面,以确保您正在测试的是页面的基本功能,尽可能与其他代码的效果分离,不管代码是否属于您,我们的,浏览器的,或者设备的。

这突出了另一个测试问题。在过去,我们建议您在台式机或笔记本电脑上进行Salesforce移动开发以及导航到Salesforce应用使用的/one/one.app URL是合理的。此方法不再有效,因为/one/one.app由Salesforce应用程序和Lightning Experience共享,具体取决于连接到它的设备。虽然你可以通过更改浏览器的用户代理来欺骗/one/one.app,但这是一个坏主意,反模式。原因是,即使是来自同一供应商的台式机和移动浏览器的行为也有所不同,有时甚至会有所不同。除非您正在测试每个设备和您计划支持的每个浏览器,否则无法进行严格的正式测试。

如果你正在开发一个单独的页面,或者一个基本的应用程序相同的设备,你的“矩阵”的不同因素可能很简单。但对于更有雄心的项目,如果您正在开发需要在各种可能性范围内支持的功能,那么您的测试计划应该考虑跨越测试的需求:

  • 每个不同的支持设备。
  • 每个不同的支持的操作系统
  • 每种不同的支持浏览器 – 包括嵌入自己的Salesforce应用程序。
  • 每个不同的受支持的用户界面上下文(Lightning Experience,Salesforce Classic和Salesforce应用程序)。

幸运的是,为了您的理智,其中一些因素一起崩溃,减少了组合爆炸。例如,大多数的苹果移动设备可以指望更新到最新版本的iOS。这意味着设备,操作系统和浏览器实际上只是一个组合。因此,您的测试计划可能会选择仅测试一个iPhone和一个iPad,并更新到最新的iOS和Salesforce应用程序。

关于测试的最后一句话。我们强烈建议您的开发和测试环境相似的另一个原因是,您可以在开发过程的早期开始测试和全面测试。我们发现,直到项目后期才开始对辅助设备进行测试。当发生这种情况时,发现问题时不可避免地会受到挫折。

提前测试,经常测试,测试一切。

Visualforce和闪电体验 – 在Lightning Experience中使用Visualforce

学习目标

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

  • 在Lightning Experience中使用它们之前,确定两个关于Visualforce页面的高级事项。
  • 在Lightning Experience中列出至少五个可以使用Visualforce的地方。

在Lightning Experience中使用Visualforce

Lightning Experience为您的Salesforce组织带来全新的用户界面,但这并不意味着您的Visualforce应用程序停止工作。 Visualforce页面在Lightning Experience中工作,许多没有任何修改。事情已经移动了,而且还有一些琐事需要完成,以确保您的Visualforce页面以您期望的方式工作,因为您的用户可以在Lightning Experience和Salesforce Classic之间切换。而且有很少的功能,唉,在闪电体验中不起作用。我们会在这个模块中把它分类到所有的东西上。
我们从几个基本的细节开始。这些是我们稍后会深入讨论的主题,但是我们先来处理一些重要的项目。
  • 除了一些重要的例外情况,Visualforce在Lightning Experience中“正常工作”。如果您已经为您的组织编写了Visualforce应用程序,则无论您的用户是在Lightning Experience还是Salesforce Classic中访问这些应用程序,都可以期待它们的正常工作。
  • 如果您的Visualforce页面使用内置的标准组件,则其外观与Salesforce Classic相匹配,无论您的用户是在Lightning Experience还是Salesforce Classic中访问它们。如果您希望自己的页面与Lightning Experience风格相匹配,则需要完成一些工作。
    如果您的Visualforce页面使用JavaScript,则需要检查一些内容。在Lightning
  • Experience中显示时,Visualforce不会“拥有”整个页面,因为您的JavaScript代码需要按照一些新规则进行播放。
  • 在Lightning Experience内部运行时,Visualforce的运行方式还有一些变化。在大多数情况下,这些都是转向“正常工作”的曲柄,但是你会想要知道它们都是一样的。

最后,我们提到有些事情已经移动了吗?他们曾经! Lightning Experience是一个对如何使用Salesforce的完整反思,虽然这项工作还没有完成,但是我们对我们要去的地方感到非常兴奋。为了让您的Visualforce在新环境中的位置得到定位,我们来快速浏览一下在Lightning Experience中可以使用Visualforce的地方。

你可以在Lightning Experience中使用Visualforce

与Salesforce Classic一样,您可以使用自定义的Visualforce页面和应用程序来扩展Lightning Experience。但是,如果你发现它们已经改变,并且还有一些地方你不能把Visualforce。
以下是您可以将Visualforce添加到Lightning Experience组织的一些方法。不过,这只是一个快速浏览。有关如何使用Visualforce页面自定义组织的更多详细信息,请参阅本机末尾的资源。

从应用启动器打开一个Visualforce页面

您的Visualforce应用程序和自定义选项卡均可从应用程序启动器获得,您可以通过单击标题中的应用程序启动器图标App Launcher icon来访问该应用程序。
App Launcher apps and tabs

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

将一个Visualforce页面添加到导航栏

(嘿,“ForceUI”实用程序页面听起来有趣吗?请继续阅读本模块!)

在标准页面布局中显示Visualforce页面

通过在其上嵌入Visualforce页面来扩展页面布局,以在标准页面上显示完全自定义的内容。除了您需要查看记录的详细信息以查看页面布局之外,此处的行为与Salesforce Classic相同。

Visualforce on a Lightning Experience page layout

在Lightning App Builder中添加Visualforce页面作为组件

在Lightning App Builder中创建自定义应用程序页面时,可以使用Visualforce组件将Visualforce页面添加到页面。

Add a Visualforce page to a Lightning App Builder page

注意

您必须为“闪电体验”,“Salesforce应用”和“闪电社区”启用Visualforce页面才能使其在Lightning App Builder中可用。

启动Visualforce页面作为Quick Action

Global action in Lighning Experience
虽然他们在Lightning Experience用户界面中的位置与Salesforce Classic大不相同,但添加快速操作的过程大致相同。将它们添加到对象页面布局上的相应发布者区域。
将快速操作添加到页面布局

Adding quick actions to a page layout

通过覆盖标准按钮或链接来显示Visualforce页面

您可以使用Visualforce页面覆盖对象上可用的操作。 当用户单击已被覆盖的按钮或链接时,将显示页面而不是标准页面。 设置这个与Salesforce Classic非常相似。 事实上,在定义一个动作覆盖的时候,你很难说出你正在使用Lightning Experience。

Override the Edit action on Contact object