在 Lightning 框架中糖驴,如果我們想要使用第三方的組件,可以將它們包含在 Lightning Container 模塊中佛致。
Lightning Container 的工作原理
Lightning Container 會(huì)將內(nèi)部的組件包含在一個(gè) iframe 中贮缕,并且提供了若干函數(shù)讓其內(nèi)部的組件和外部的 Lightning 應(yīng)用進(jìn)行通信。
它要求內(nèi)部的組件是作為“靜態(tài)資源(static resource)”上傳到 Salesforce 中俺榆。
它的語法本質(zhì)上是調(diào)用靜態(tài)資源的 URL 路徑感昼。
舉個(gè)例子,我們已經(jīng)有了一個(gè) Vue 應(yīng)用罐脊,它的入口文件是 index.html定嗓,我們將它上傳到 Salesforce 的靜態(tài)資源,名字叫 “testApp”萍桌,那么調(diào)用它的方式如下:
<lightning:container src="{!$Resource.testApp + '/index.html'}" />
Lightning Container NPM 包和使用實(shí)例
Lightning Container 提供了 NPM 包宵溅,可以讓第三方組件調(diào)用 API,從而和 Lightning 組件進(jìn)行通信梗夸。
我們以兩個(gè) Vue-cli 例子程序來說明:
- 如何和 Lightning 組件進(jìn)行通信
- 如何從第三方組件中調(diào)用 Apex 函數(shù)
設(shè)置 Lightning Container
初始化 Vue-cli 項(xiàng)目层玲,然后安裝 NPM 包:
npm install lightning-container --save
在 main.js 文件中加入以下兩行:
import LCC from 'lightning-container'
Vue.prototype.$LCC = LCC
這樣号醉,我們就可以在其他的組件中引用模塊了反症,語法如下:
this.$LCC
編譯 Vue 應(yīng)用
在命令行中運(yùn)行以下命令即可將 Vue 的應(yīng)用編譯到 “dist” 文件夾下:
npm run build
然后我們將 “dist” 文件夾下的內(nèi)容打包成 zip 文件,上傳到 Salesforce 中作為靜態(tài)資源畔派。
Vue-cli 的應(yīng)用默認(rèn)的入口是 index.html 文件铅碍。
和 Lightning 組件的通信演示
在這個(gè)通信的演示程序中,我們要達(dá)到的目標(biāo)是把文字在 Lightning 組件和 Vue 應(yīng)用中相互發(fā)送线椰。
在 Vue 項(xiàng)目中胞谈,在 “src/components” 文件夾中新建 Vue 組件,名為 “Messaging.vue”憨愉,代碼如下:
<template>
<div>
<h3>通信演示</h3>
<div>
發(fā)送給 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">發(fā)送到 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() 函數(shù)定義如何接收從 Lightning 組件中傳來的數(shù)據(jù)
},
methods: {
receiveMessage: function(message) {
this.msgFromLC = message.value;
},
sendMessage: function() {
// 使用 sendMessage() 函數(shù)發(fā)送信息給 Lightning 組件
this.$LCC.sendMessage({name: "Message To LC", value: this.msgToLC})
}
}
}
</script>
在 Vue 項(xiàng)目的 “src/router” 文件夾下烦绳,修改 “index.js” 文件,將剛才建立的 Vue 組件定義為默認(rèn)的路徑:
import Messaging from '@/components/Messaging'
export default new Router({
routes: [
{
path: '/',
name: 'Messaging',
component: Messaging
},
]
})
編譯 Vue 應(yīng)用配紫,然后上傳到 Salesforce 中径密,作為靜態(tài)資源,名為 “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="發(fā)送給 Vue 應(yīng)用: "/>
<lightning:button label="Send" onclick="{!c.sendMessage}"/>
<br/>
<lightning:input value="{!v.messageReceived}" label="接收自 Vue 應(yīng)用: "/>
<br/>
<!-- 使用 lightning:container 來調(diào)用靜態(tài)資源中的 Vue 應(yīng)用享扔,并定義在收到它的信息時(shí)使用的函數(shù) -->
<lightning:container aura:id="vueApp"
src="{!$Resource.vueApplication + '/index.html'}"
onmessage="{!c.handleMessage}"/>
</div>
</aura:component>
定義控制器:
({
/*
* 從 Lightning 組件中發(fā)送信息
*/
sendMessage : function(component, event, helper) {
var msg = {
name: "Message From LC",
value: component.get("v.messageToSend")
};
component.find("vueApp").message(msg);
},
/*
* 接收從 Vue 應(yīng)用中發(fā)送的信息
*/
handleMessage: function(component, event, helper) {
var value = event.getParams().payload.value;
component.set("v.messageReceived", value);
},
})
當(dāng)我們使用這個(gè) Lightning 組件時(shí)底桂,它會(huì)自動(dòng)調(diào)用 Vue 應(yīng)用,然后可以將文字在兩個(gè)應(yīng)用之間發(fā)送和接收惧眠。
當(dāng)我們查看頁面的源代碼時(shí)籽懦,可以看到,lightning:container 中的內(nèi)容被放在了一個(gè) iframe 中氛魁,所以我們的 Vue 應(yīng)用其實(shí)是封裝起來的暮顺。
調(diào)用 Apex 函數(shù)
在接下來的應(yīng)用中,我們要從 Vue 應(yīng)用中調(diào)用 Apex 函數(shù)秀存。
在 Salesforce 中建立 Apex 函數(shù):
global without sharing class VueController {
@RemoteAction
global static Account[] getAccounts(String searchString) {
return [SELECT Id, Name, Phone, Type, NumberOfEmployees FROM Account Limit 10];
}
}
為了調(diào)用 Apex 函數(shù)拖云,我們?cè)?Vue 應(yīng)用中需要一個(gè)特殊的設(shè)置。在 “dist” 文件夾下建立一個(gè)名為 “manifest.json” 的文件应又,內(nèi)容如下:
{
"landing-pages" : [
{
"path": "index.html",
"apex-controller": "VueController"
}
]
}
在 Vue 應(yīng)用中建立一個(gè)名為 “AccountList” 的組件:
<template>
<div>
<h3>接收到的數(shù)據(jù):</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() 函數(shù)來調(diào)用相應(yīng)的函數(shù)
this.$LCC.callApex("VueController.getAccounts",
{
searchString: ''
},
this.handleResult,
{});
},
handleResult: function(result) {
this.accounts = result;
},
}
}
</script>
這樣宙项,在用 lightning:container 在 Lightning 組件中執(zhí)行 Vue 應(yīng)用時(shí),Vue 應(yīng)用會(huì)直接調(diào)用 Apex 函數(shù)株扛,然后給出結(jié)果尤筐。
與 Locker Service 的比較
Lightning Container 機(jī)制和 Locker Service 機(jī)制都是對(duì) Lightning 組件的安全進(jìn)行提高,將不同來源(命名空間等)的組件分別封裝洞就。
Lightning Container 是基于 iframe 的盆繁,它將第三方的組件或應(yīng)用封裝在 iframe 中,而 Locker Service 則不需要這樣旬蟋,它是將不同的組件放在同一個(gè) DOM 樹中油昂,將不同的 DOM 元素封裝起來。這是兩者最大的不同倾贰,從而也決定了它們不同的特性:
- Locker Service 可以利用 Lightning 框架的各種本地功能冕碟,而 Lightning Container 中的內(nèi)容則受到限制,比如只能通過其 NPM 包中提供的 API 函數(shù)來進(jìn)行通信
- Lightning Container 支持的第三方框架比 Locker Service 更多
- Locker Service 中的組件執(zhí)行速度比 Lightning Container 中的要快
- Locker Service 中的組件和整個(gè) Lightning 框架的外觀是一致的匆浙,而 Lightning Container 中的內(nèi)容由于被封裝在 iframe 中安寺,在特殊的情況下可能會(huì)出現(xiàn)問題