Lightning Container 简介

在 Lightning 框架中,如果我们想要使用第三方的组件,可以将它们包含在 Lightning Container 模块中。

Lightning Container 的工作原理

Lightning Container 会将内部的组件包含在一个 iframe 中,并且提供了若干函数让其内部的组件和外部的 Lightning 应用进行通信。

它要求内部的组件是作为“静态资源(static resource)”上传到 Salesforce 中。

它的语法本质上是调用静态资源的 URL 路径。

举个例子,我们已经有了一个 Vue 应用,它的入口文件是 index.html,我们将它上传到 Salesforce 的静态资源,名字叫 “testApp”,那么调用它的方式如下:

<lightning:container src="{!$Resource.testApp + '/index.html'}" />

Lightning Container NPM 包和使用实例

Lightning Container 提供了 NPM 包,可以让第三方组件调用 API,从而和 Lightning 组件进行通信。

我们以两个 Vue-cli 例子程序来说明:

  • 如何和 Lightning 组件进行通信
  • 如何从第三方组件中调用 Apex 函数

设置 Lightning Container

初始化 Vue-cli 项目,然后安装 NPM 包:

npm install lightning-container --save

在 main.js 文件中加入以下两行:

import LCC from 'lightning-container'

Vue.prototype.$LCC = LCC

这样,我们就可以在其他的组件中引用模块了,语法如下:

this.$LCC

编译 Vue 应用

在命令行中运行以下命令即可将 Vue 的应用编译到 “dist” 文件夹下:

npm run build

然后我们将 “dist” 文件夹下的内容打包成 zip 文件,上传到 Salesforce 中作为静态资源。

Vue-cli 的应用默认的入口是 index.html 文件。

和 Lightning 组件的通信演示

在这个通信的演示程序中,我们要达到的目标是把文字在 Lightning 组件和 Vue 应用中相互发送。

在 Vue 项目中,在 “src/components” 文件夹中新建 Vue 组件,名为 “Messaging.vue”,代码如下:

<template>
  <div>
    <h3>通信演示</h3>
    
    <div>
      发送给 Lightning Component:
      <input type="text" id="text-input-to-Lc" class="slds-input" v-model="msgToLC" />
      <button id="sendBtn" class="slds-button slds-button--neutral" v-on:click="sendMessage">发送到 Lightning Component</button>
    </div>
    
    <div>
      从 Lightning Component 接收的信息:
      <input type="text" id="text-input-from-Lc" class="slds-input" v-model="msgFromLC" />
    </div>
  </div>
</template>

<script>
export default {
    data () {
        return {
        msgToLC: '',
        msgFromLC: ''
        }
    },
    mounted: function() {
        this.$LCC.addMessageHandler(this.receiveMessage); // 使用 addMessageHandler() 函数定义如何接收从 Lightning 组件中传来的数据
    },
    methods: {
        receiveMessage: function(message) {
            this.msgFromLC = message.value;
        },

        sendMessage: function() {
            // 使用 sendMessage() 函数发送信息给 Lightning 组件
            this.$LCC.sendMessage({name: "Message To LC", value: this.msgToLC})
        }
    }
}
</script>

在 Vue 项目的 “src/router” 文件夹下,修改 “index.js” 文件,将刚才建立的 Vue 组件定义为默认的路径:

import Messaging from '@/components/Messaging'

export default new Router({
    routes: [
    {
        path: '/',
        name: 'Messaging',
        component: Messaging
    },
    ]
})

编译 Vue 应用,然后上传到 Salesforce 中,作为静态资源,名为 “VueApplication”。

在 Salesforce 中新建 Lightning 组件:

<aura:component access="global">
    <aura:attribute access="private" name="messageToSend" type="String" default=""/>
    <aura:attribute access="private" name="messageReceived" type="String" default=""/>
    
    <div>
        <lightning:input name="messageToSend" value="{!v.messageToSend}" label="发送给 Vue 应用: "/>
        <lightning:button label="Send" onclick="{!c.sendMessage}"/>
        <br/>

        <lightning:input value="{!v.messageReceived}" label="接收自 Vue 应用: "/>
        <br/>
    
        <!-- 使用 lightning:container 来调用静态资源中的 Vue 应用,并定义在收到它的信息时使用的函数 -->
        <lightning:container aura:id="vueApp"
                             src="{!$Resource.vueApplication + '/index.html'}"
                             onmessage="{!c.handleMessage}"/>
    </div>
</aura:component>

定义控制器:

({
    /*
     * 从 Lightning 组件中发送信息
     */
    sendMessage : function(component, event, helper) {
        var msg = {
            name: "Message From LC",
            value: component.get("v.messageToSend")
        };
      
        component.find("vueApp").message(msg);
    },
    
    /*
     * 接收从 Vue 应用中发送的信息
     */ 
    handleMessage: function(component, event, helper) {
        var value = event.getParams().payload.value;
   
        component.set("v.messageReceived", value);        
    },
})

当我们使用这个 Lightning 组件时,它会自动调用 Vue 应用,然后可以将文字在两个应用之间发送和接收。

当我们查看页面的源代码时,可以看到,lightning:container 中的内容被放在了一个 iframe 中,所以我们的 Vue 应用其实是封装起来的。

调用 Apex 函数

在接下来的应用中,我们要从 Vue 应用中调用 Apex 函数。

在 Salesforce 中建立 Apex 函数:

global without sharing class VueController {
    @RemoteAction
    global static Account[] getAccounts(String searchString) {
        return [SELECT Id, Name, Phone, Type, NumberOfEmployees FROM Account Limit 10];
    }
}

为了调用 Apex 函数,我们在 Vue 应用中需要一个特殊的设置。在 “dist” 文件夹下建立一个名为 “manifest.json” 的文件,内容如下:

{
    "landing-pages" : [
        {
            "path": "index.html",
            "apex-controller": "VueController"
        }
    ]
}

在 Vue 应用中建立一个名为 “AccountList” 的组件:

<template>
  <div>
    <h3>接收到的数据:</h3>
    
    <ul>
      <li v-for="item in accounts">
        {{ item.Name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
    data () {
        return {
            accounts: [],
        }
    },
    mounted: function() {
        this.getAccounts();
    },
    methods: {
        getAccounts: function() {
            // 使用 callApex() 函数来调用相应的函数
            this.$LCC.callApex("VueController.getAccounts", 
            {
            searchString: ''
            }, 
            this.handleResult, 
            {});
        },

        handleResult: function(result) {
            this.accounts = result;
        },
    }
}
</script>

这样,在用 lightning:container 在 Lightning 组件中执行 Vue 应用时,Vue 应用会直接调用 Apex 函数,然后给出结果。

与 Locker Service 的比较

Lightning Container 机制和 Locker Service 机制都是对 Lightning 组件的安全进行提高,将不同来源(命名空间等)的组件分别封装。

Lightning Container 是基于 iframe 的,它将第三方的组件或应用封装在 iframe 中,而 Locker Service 则不需要这样,它是将不同的组件放在同一个 DOM 树中,将不同的 DOM 元素封装起来。这是两者最大的不同,从而也决定了它们不同的特性:

  • Locker Service 可以利用 Lightning 框架的各种本地功能,而 Lightning Container 中的内容则受到限制,比如只能通过其 NPM 包中提供的 API 函数来进行通信
  • Lightning Container 支持的第三方框架比 Locker Service 更多
  • Locker Service 中的组件执行速度比 Lightning Container 中的要快
  • Locker Service 中的组件和整个 Lightning 框架的外观是一致的,而 Lightning Container 中的内容由于被封装在 iframe 中,在特殊的情况下可能会出现问题
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容