佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > flex與js通信與彼此之間的互調(diào)整理(二)

flex與js通信與彼此之間的互調(diào)整理(二)

熱門(mén)標(biāo)簽:服務(wù)器配置 美圖手機(jī) 銀行業(yè)務(wù) 檢查注冊(cè)表項(xiàng) 智能手機(jī) 網(wǎng)站文章發(fā)布 鐵路電話系統(tǒng) 呼叫中心市場(chǎng)需求

之前寫(xiě)了一篇flex和js之間的通信,還記得最開(kāi)始研究這兩門(mén)語(yǔ)言如何交互,一晃我的任務(wù)也快做完了,公司的realspace產(chǎn)品之開(kāi)了js的API,但是現(xiàn)在使用flex產(chǎn)品的人也比較多,要求開(kāi)設(shè)flex的三維API,已經(jīng)過(guò)去幾個(gè)月了,產(chǎn)品也上線了,有興趣的可以在https://github.com/SuperMap/Flex-Realspace下載,這是一個(gè)利用as與js交互放在了一個(gè)完整的產(chǎn)品里。

網(wǎng)上也有很多關(guān)于flex和js通信的文章,不過(guò)不知道大家有沒(méi)有注意到好像都需要把js文件放在固定的文件下(flex調(diào)用js),并且需要在index.template.html文件里面動(dòng)手腳,而且你把源代碼考給團(tuán)隊(duì)的其他人,發(fā)現(xiàn)flash builder導(dǎo)進(jìn)去后重新生成了index.template.html,又得自己修改一下,不是很麻煩嗎?如果你是需要此技術(shù)做自己的產(chǎn)品的話我建議你一定要看一下我想出的辦法,也許會(huì)幫了不少人哦!

一個(gè)大項(xiàng)目或者產(chǎn)品,在js代碼里面估計(jì)都會(huì)有很多用原型建的類,在flex端估計(jì)也有很多功能。我們的假設(shè)場(chǎng)景是你正在使用flex制作項(xiàng)目,不過(guò)有一些功能只能通過(guò)js來(lái)實(shí)現(xiàn),所以你將部分功能使用js封裝成了一些js的文件,希望通過(guò)as與js之間的通信來(lái)使用as語(yǔ)言調(diào)用js里面的功能。js文件基本已經(jīng)寫(xiě)好了,但是因?yàn)樾枰诓簧俚胤蕉帜_團(tuán)隊(duì)協(xié)作起來(lái)不方便,我這篇文章就是用來(lái)解決這個(gè)問(wèn)題的。

一、設(shè)計(jì)好代碼

首先我們需要明白的是:js文件在啟動(dòng)之后被加載到html頁(yè)面里面,我們可以通過(guò)ExternalInterface.call("js的方法",參數(shù));在flex端調(diào)用js端的方法,我們可以通過(guò)ExternalInterface.addCallback("對(duì)外公開(kāi)的方法名",具體實(shí)現(xiàn)的方法);來(lái)解決在js端調(diào)用flex端的方法。

現(xiàn)在我們需要思考:js里面有很多功能,我們每次調(diào)用js功能都得去調(diào)用相關(guān)的方法嗎?那樣as和js之間的耦合不是太高了,不符合設(shè)計(jì)模式,并且很麻煩。同樣js這邊需要回調(diào)(常用在事件回調(diào)上)flex的方法時(shí),方法很多,我們是不是也要在flex端動(dòng)態(tài)注冊(cè)那么多個(gè)方法名稱呢?那樣不怕名稱沖突嗎?所以這樣的實(shí)現(xiàn)都是不可取的。

為了達(dá)到低耦合,我將as和js之間的通信設(shè)定為只有兩座橋,as調(diào)用js功能永遠(yuǎn)只會(huì)通過(guò)調(diào)用js里面的固定方法,js回調(diào)flex的功能也只能調(diào)用在程序初始化flex端動(dòng)態(tài)創(chuàng)建的唯一的一個(gè)方法。這樣as和js之間的通信永遠(yuǎn)只通過(guò)這兩個(gè)方法來(lái)交互,就不會(huì)出現(xiàn)之前的很多問(wèn)題。但是大家肯定想問(wèn)如何知道我這一次調(diào)用的功能和我下一次調(diào)用的有什么區(qū)別怎么辦?那就是在參數(shù)上面做手腳了。說(shuō)白了就是通過(guò)參數(shù)來(lái)判斷你的行為。

在我們flex realspace產(chǎn)品面as調(diào)用js的功能都是通過(guò)var result:Object=ExternalInterface.call("SuperMap.Web.Util.ApplicationManager.initBridgeFlexToJs",object);這一局來(lái)的,SuperMap.Web.Util.ApplicationManager.initBridgeFlexToJs是在js端的一個(gè)文件里面的方法,唯一的as訪問(wèn)js的通道,特殊的是object,這是一個(gè)鍵值對(duì),形如:

復(fù)制代碼 代碼如下:

var realArgument:Array=[strServerUrl.toString()+"$String"];
var array:Object={
action:"FUNCTION",
key:this.KEY,
functionName:"checkPluginUpdate",
isReturn:true,
realArgument:realArgument
};

上面的array就是我說(shuō)的object,里面的action:"FUNCTION"代表我需要調(diào)用的是方法,調(diào)用的對(duì)象的key(唯一標(biāo)示)是this.KEY,方法名稱是checkPluginUpdate,有返回值,方法的參數(shù)是realArgument(一個(gè)特殊數(shù)組)。

其實(shí)這些有點(diǎn)類似json,用來(lái)傳遞數(shù)據(jù)的,而我自定義的一個(gè)格式是用來(lái)傳遞行為操作的,這個(gè)你們可以自己定義,反正核心就是通過(guò)參數(shù)來(lái)判斷你的行為,方法永遠(yuǎn)調(diào)用同一個(gè),這點(diǎn)明白了就是自己設(shè)計(jì)上的事情,不過(guò)在解析的時(shí)候有點(diǎn)麻煩哈!

二、打包js代碼

如果你的代碼符合我這樣的邏輯,交互通過(guò)兩座橋來(lái)通信,那么我們就開(kāi)始下一步,其實(shí)這樣設(shè)計(jì)后已經(jīng)可以使得自己的產(chǎn)品交互起來(lái)很方便了,我當(dāng)時(shí)花了一個(gè)月就是這么做的,都做的差不多了,上面交代說(shuō)js代碼不能開(kāi)放出來(lái),而且每次都需要修改index.template.html文件,太麻煩,希望flex端的開(kāi)放人員完全看不到j(luò)s的任何東西,要求需要把js文件打包成為swc文件,通過(guò)去調(diào)用swc文件里面的js來(lái)實(shí)現(xiàn)功能,我當(dāng)時(shí)一聽(tīng)這簡(jiǎn)直就是不可能的嘛!不過(guò)后來(lái)研究了好久,發(fā)現(xiàn)這樣可以實(shí)現(xiàn),并且還有它的優(yōu)勢(shì)。

首先我們需要知道如何把js文件打包成為swc文件,新建一個(gè)庫(kù)項(xiàng)目,將你的js文件都放進(jìn)去,如下圖:

我建的項(xiàng)目叫bridge,里面有我所有的js文件,還有不少as文件,細(xì)心的發(fā)現(xiàn)每一個(gè)js文件旁邊都有一個(gè)...Stream.as文件,這里就是重點(diǎn)了,我們?nèi)绾尾拍馨裫s文件打包到swc里面呢,flex提供了一種流的方式,例如上面的ApplicationManager.js文件,我們創(chuàng)建一個(gè)類ApplicationManagerStream繼承于flash.utils.ByteArray,代碼如下:

復(fù)制代碼 代碼如下:

package SuperMap.Js
{
import flash.utils.ByteArray;
/**
* 制定js文件以及打包方式
*/
[Embed(source="ApplicationManager.js", mimeType="application/octet-stream")]
public class ApplicationManagerStream extends ByteArray
{
public function ApplicationManagerStream()
{
super();
}
}
}

寫(xiě)好你對(duì)應(yīng)的js文件,一定要和此類放在一個(gè)文件夾下,配上打包的類型application/octet-stream,每一個(gè)js文件都配置一個(gè)相應(yīng)的as類,這樣在

里面會(huì)自動(dòng)生成好打包好的swc文件

現(xiàn)在問(wèn)題又來(lái)了,里面是二進(jìn)制的東西,我們?nèi)绾问褂冒?,不是我們平時(shí)寫(xiě)的as類,寫(xiě)了什么方法引用這個(gè)包直接使用就行。

所以我們還需要一個(gè)as類。這里我創(chuàng)建IncludeStream.as,代碼如下:

復(fù)制代碼 代碼如下:

package SuperMap
{
import SuperMap.Js.ApplicationManagerStream;
import SuperMap.Js.HashTableStream;
import SuperMap.Js.SceneDivStream;
import SuperMap.lib_Ajax.IServerJava6RStream;
import SuperMap.lib_Ajax.JsStream;
import SuperMap.lib_Ajax.MicrosoftAjaxStream;
import SuperMap.lib_Realspace.RealspaceStream;
/**
* 此類主要用于以字符串形式獲取二進(jìn)制形式的js代碼
*/
public class IncludeStream
{
/**
* 構(gòu)造函數(shù)
*/
public function IncludeStream()
{
}
/**
* 返回js文件里面代碼的字符串形式
*/
public function toString():String
{
var microsoftAjaxStream:MicrosoftAjaxStream=new MicrosoftAjaxStream();
var jsStream:JsStream=new JsStream();
var iServerJava6RStream:IServerJava6RStream=new IServerJava6RStream();
var realspaceStream:RealspaceStream=new RealspaceStream();
var hashTableStream:HashTableStream=new HashTableStream();
var applicationManagerStream:ApplicationManagerStream=new ApplicationManagerStream();
var sceneDivStream:SceneDivStream=new SceneDivStream();
return microsoftAjaxStream.toString()+jsStream.toString()+iServerJava6RStream.toString()+realspaceStream.toString()+hashTableStream.toString()+applicationManagerStream.toString()+sceneDivStream.toString();
}
}
}

有了這個(gè)類,我們可以通過(guò)實(shí)例化一個(gè)此對(duì)象,然后通過(guò)方法toString()獲取到字符串形式的js的所有代碼。這又是一個(gè)問(wèn)題,我們還是不能使用,沒(méi)法調(diào)用。不過(guò)先這樣打包好,引用到你的flex項(xiàng)目里面再說(shuō)。

三、調(diào)用js文件

首先我們要知道as調(diào)用js的方法只能調(diào)用js形式的方法,也就是嵌入到了html頁(yè)面的js,而現(xiàn)在我們只有字符串形式的js源代碼,所以需要想辦法將它轉(zhuǎn)化為標(biāo)準(zhǔn)的js代碼,嵌入到html頁(yè)面里面。

在你的flex項(xiàng)目啟動(dòng)的最開(kāi)始的地方恰如如下代碼:

復(fù)制代碼 代碼如下:

//初始化一個(gè)字符串形式的方法parseStringToJs,用于將字符串轉(zhuǎn)換為js語(yǔ)言
var str:String = "function parseStringToJs(str){var oHead = document.getElementsByTagName('HEAD').item(0);";
str+="var oScript = document.createElement(\"script\");";
str+="oScript.language = \"javascript\";";
str+="oScript.type = \"text/javascript\";";
str+="oScript.id = \"test\";";
str+="oScript.defer = true;";
str+="oScript.text = str;";
str+="oHead.appendChild(oScript);}";
//調(diào)用window.eval方法
ExternalInterface.call("eval",str);
var includeStream:IncludeStream=new IncludeStream();
//獲取js的字符串形式的源代碼
var strey:String=includeStream.toString();
//使用正則表達(dá)式修改字符串
var char:RegExp = /\\/g;
strey = strey.replace(char,"\\\\");
//生成js的API
ExternalInterface.call("parseStringToJs",strey);
//初始化js調(diào)用as的入口方法initBridgeJsToFlex,最終飯方法的實(shí)現(xiàn)轉(zhuǎn)給方法ApplicationManager.initBridgeJsToFlex
ExternalInterface.addCallback("initBridgeJsToFlex",ApplicationManager.initBridgeJsToFlex);

注釋已經(jīng)寫(xiě)的很清楚了,不過(guò)正則表達(dá)式這一步可以不要,我這里是因?yàn)槲业拇a里出現(xiàn)了反斜杠的東西,所以我這樣是為了轉(zhuǎn)義一下,這里的思路就是先使用ExternalInterface.call去調(diào)用window對(duì)象的方法eval在window下創(chuàng)建一個(gè)將字符串轉(zhuǎn)化為js代碼的方法parseStringToJs,然后再調(diào)用此方法將我們的字符串的源代碼進(jìn)行轉(zhuǎn)化,這樣html中就存在js的代碼了,就不用再去修改index.template.html文件添加引用和添加入口了。并且在其他地方你可以通過(guò)ExternalInterface.call直接調(diào)用js端公開(kāi)的橋,并且通過(guò)ApplicationManager.initBridgeJsToFlex來(lái)接收js的回調(diào)函數(shù),這樣我們只需要添加swc這個(gè)包就可以使用js的所用功能。

其實(shí)我也不想使用eval的,eval是很消耗性能的,我的源代碼長(zhǎng)度大概是8萬(wàn)多,還好,沒(méi)見(jiàn)卡,我也只會(huì)這種方法,不要拿板磚拍我哦!有其他辦法的朋友告訴我哦!期望對(duì)某些人有幫助吧!

標(biāo)簽:滄州 長(zhǎng)治 新疆 上海 沈陽(yáng) 樂(lè)山 河南 紅河

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《flex與js通信與彼此之間的互調(diào)整理(二)》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    广东省| 安达市| 阆中市| 常州市| 新干县| 池州市| 玉屏| 垫江县| 大田县| 准格尔旗| 清新县| 鄂托克前旗| 莱西市| 弥渡县| 维西| 横峰县| 嘉禾县| 清水县| 保德县| 襄城县| 独山县| 新兴县| 永平县| 礼泉县| 弥勒县| 永川市| 海安县| 巴彦县| 双柏县| 大悟县| 玉田县| 蓬安县| 如东县| 长武县| 郓城县| 孟连| 吴江市| 陆河县| 会东县| 蓬溪县| 昌吉市|