Weex 從無到有開發(fā)一款上線應(yīng)用 3

iOS調(diào)試Demo
WeexDemo
本篇將開始跟大家探討如何進行Weex頁面跟原生的交互,即Weex調(diào)原生方法窃爷,原生方法調(diào)取Weex方法姓蜂。
-------------2017.05.25 今晚寫 敲了一天了--------
-------------2017.05.26 胳膊疼 家里電腦什么環(huán)境也沒弄逮京,今晚就寫了------------
像Weex提供的navigator,animate等擴展都是通過兩者交互實現(xiàn)的造虏。
接第二篇的頁面實現(xiàn)麦箍。

"我"界面完整UI.jpeg

從Weex的擴展開始

如何實現(xiàn),點擊Push新的頁面陶珠?Weex提供了navigator擴展挟裂。
來看WXNavigatorModule源碼。
首先他遵守WXModuleProtocol協(xié)議

@protocol WXModuleProtocol <NSObject>
/*多用于 Module 回調(diào)結(jié)果給 js揍诽,回調(diào)類型分為下面兩種:

WXModuleCallback 為了性能考慮诀蓉,該回調(diào)只能回調(diào)通知js一次,之后會被釋放暑脆,多用于一次結(jié)果

WXModuleKeepAliveCallback 該回調(diào)可以設(shè)置是否為多次回調(diào)類型渠啤,多次回調(diào)的場景如持續(xù)監(jiān)聽位置的變化,并返回給 js
*/
/**
這個是聲明了一個通用的Native回調(diào)JS的block 這個會在使用完之后被釋放以來節(jié)約內(nèi)存 */
typedef void (^WXModuleCallback)(id result);
/**
這個是聲明了一個通用的Native回調(diào)JS的block 這個會通過keepAlive參數(shù)來決定 使用完之后被釋放以來節(jié)約內(nèi)存
 */
typedef void (^WXModuleKeepAliveCallback)(id result, BOOL keepAlive);
/**
該Moudule綁定的Instance添吗。我們可以通過他在xxxModule.m來調(diào)用方法和屬性
 */
@property (nonatomic, weak) WXSDKInstance *weexInstance;
@end

上述協(xié)議當我們要擴展一個Module時僵腺,我們需要遵守這個協(xié)議。在xxxxModule.m中需要@synthesize weexInstance生成成員變量。
那么我們?nèi)绾螌⒃椒ū┞督oJS呢呕童?通過WX_EXPORT_METHOD(@selector(xxxxx))這個宏來實現(xiàn)往声。
WXNavigatorModule有一個方法:

- (void)open:(NSDictionary *)param success:(WXModuleCallback)success failure:(WXModuleCallback)failure
{ 
}

那么就可以通過

WX_EXPORT_METHOD(@selector(open:success:failure:))

暴露給JS慢洋。
那么WX_EXPORT_METHOD是如何實現(xiàn)的呢隘马?

#define WX_EXPORT_METHOD(method) WX_EXPORT_METHOD_INTERNAL(method,wx_export_method_)
#define WX_EXPORT_METHOD_INTERNAL(method, token) \
+ (NSString *)WX_CONCAT_WRAPPER(token, __LINE__) { \
    return NSStringFromSelector(method); \
}
#define WX_CONCAT_WRAPPER(a, b)    WX_CONCAT(a, b)
#define WX_CONCAT(a, b)   a ## b

如上,首先會傳遞過來一個SEL參數(shù),然后將wx_export_method_當前代碼行數(shù)拼接成一個方法名如改宏寫在第69行:wx_export_method_69
具體方法為:

+ (NSString *)wx_export_method_69 { 
    return NSStringFromSelector(method); 
}
實現(xiàn)一個簡單需求

了解了如何擴展Module叛氨,那我們現(xiàn)在就從最簡單的需求開始仁连,點擊某一行Cell Push一個新的界面昌抠。
再來看WXNavigatorModule

- (id<WXNavigationProtocol>)navigator
{
    id<WXNavigationProtocol> navigator = [WXHandlerFactory handlerForProtocol:@protocol(WXNavigationProtocol)];
    return navigator;
}
- (void)open:(NSDictionary *)param success:(WXModuleCallback)success failure:(WXModuleCallback)failure
{
//這里 Weex源碼中 使用了一個有默認實現(xiàn)WXNavigationProtocol的協(xié)議類冰沙,
//并將它注冊到WXHandlerFactory實例的handlers(這是一個線程安全字典:WXThreadSafeMutableDictionary 繼承自NSMutableDictionary 目的是為了達到讀寫都在同一個并發(fā)隊列)
    id<WXNavigationProtocol> navigator = [self navigator];
    UIViewController *container = self.weexInstance.viewController;
    if (navigator && [navigator respondsToSelector:@selector(open:success:failure:withContainer:)]) {
//這樣通過注冊的默認實現(xiàn)來響應(yīng)這個方法 這里我們可以不去考慮他的內(nèi)部實現(xiàn),依照我們平時Push的方法書寫下面代碼就可以
        [navigator open:param success:success failure:failure withContainer:container];
    }
}

weex 幫我們實現(xiàn)了一個常用的配置導(dǎo)航欄的接口:

Weex導(dǎo)航欄接口.png

到這里我們已經(jīng)看到了Weex的WXNavigatorModule是如何開放接口給JS,現(xiàn)在我們就可以自己寫一個Module
現(xiàn)在我們自己擴展一個Module才睹,以iOS調(diào)試Demo中的XMWXModule為例,我們自己實現(xiàn)一個Push新頁面的方法。

WX_EXPORT_METHOD(@selector(openURL:options:completionHandler:))
-(void)openURL:(NSString *)url options:(NSDictionary<NSString *,id> *)options completionHandler:(WXCallback)completion
{
    NSString *newURL = url;
    if ([url hasPrefix:@"http://"]) {
        newURL = [NSString stringWithFormat:@"http:%@", url];
    } else if (![url hasPrefix:@"http"]) {
        newURL = [NSURL URLWithString:url relativeToURL:self.weexInstance.scriptURL].absoluteString;
    }
    XMWXViewController * controller = [[XMWXViewController alloc] init];
    controller.renderURL = [NSURL URLWithString:newURL];
//從option參數(shù)中去取出navigtionBarInfo的數(shù)據(jù)
    if ([options objectForKey:@"navigtionBarInfo"]) {
        controller.renderInfo = [XMWXNavigationItem infoWithDict:[options objectForKey:@"navigtionBarInfo"]];
    }

    [self.weexInstance.viewController showViewController:controller sender:nil];
    completion(@{@"result":@"success"});
}

到這第一步的擴展Module已經(jīng)可以了忍啤,現(xiàn)在就去注冊我們的Module,在Weex配置方法中加入

[WXSDKEngine registerModule:@"XMWXModule" withClass:NSClassFromString(@"XMWXModule")];
如何使用擴展Module

以個人主頁的ViewController為例FifthViewController.vue
Weex 從無到有開發(fā)一款上線應(yīng)用 2中已經(jīng)說了如何做一個Cell,現(xiàn)在我們就為Cell加上點擊事件,調(diào)取我們的方法
實現(xiàn)如下:

<script>

//如何實現(xiàn)點擊事件冤狡,
//1. 首先引入我們在原生注冊的Module名字
    let appBasicModule = weex.requireModule('XMWXModule')
    export default {
        props: {
//        cell的Model數(shù)據(jù)
            item: {
                type: Object,
                default: 'null'
            },
//        因為點贊和余額的DetailTextLabel的顏色不一樣,需要給其一個判斷條件
            isMark: {//這個cell是不是點贊Cell
                type: Boolean,
                default: false
            }
        },
        data () {
            return {}
        },
        methods: {
//      2.實現(xiàn)點擊事件方法
            goPage()
            {
//      3.配置導(dǎo)航欄信息
                var navigtionBarInfo = {
                    title: this.item.navigaitonBarTitle,
                    clearTitleColor:'333333',
                    blurTitleColor:'333333',
                    clearNavigationBar:true,
                    hiddenNavgitionBar:false,
                    navigationBarBackgroundColor:'',
                    navgationBarBackgroundImage:'',
                    customTitleViewURL:'',
                };
//    4.調(diào)用原生方法
                appBasicModule.openURL(this.item.actionUrl,{//這里的actionUrl就是我們每一個ViewController對應(yīng)的JSBundle文件地址
                    navigtionBarInfo:navigtionBarInfo,
                },function (result) {
                    
                })
            }
        }
    }
</script>

現(xiàn)在我們的個人主頁翅阵,可以點擊然后Push 到新的頁面滥崩。效果如下:
![個人頁面.jpeg](http://upload-images.jian

Native 調(diào)取JS

先聊需求,假設(shè)我們iOS有一個比較好的下拉加載控件茸时,但是安卓的同事沒能實現(xiàn)出來旋炒,那么我們無法將這個擴展成Component(因為兩端不通用),那我們該如何操作這部分邏輯呢?首先睁壁,考慮到我們當前的頁面一定是Weex實現(xiàn)的,那么網(wǎng)絡(luò)請求也一定是在Vue文件中。所以當原生的刷新控件要調(diào)用beginRefresh是就需要調(diào)用JS的refresh方法盐杂。
先暴露JS方法給Native.

<script>
// 1 獲取全局響應(yīng)Module
    let globalEvent = weex.requireModule('globalEvent');
        created () {
            let self = this;
            self.day = new Date().getDate();
            this.host=this.getHost().replace('8081','8083')
            try {
                appBasicModule.accessKeyWithCallback(function (accessKey) {
                    self.accessKey = accessKey;
                });
                appBasicModule.userIdWithCallback(function (userId) {
                    self.userId = userId
                    self.getAllData();
                })
            }
            catch (e) {
                self.getAllData();
            }
        },
        mounted(){
            let self = this;
// 監(jiān)聽調(diào)取JS的信號名,類似于通知中心 這個地方就是注冊原生發(fā)送的refresh通知 
// refresh就是原生的通知名眉尸,后邊跟著的就是需要收到通知需要做的事情
            globalEvent.addEventListener("refresh", function (e) {
//            刷新頁面 重新請求數(shù)據(jù)等
            });
        }
</script>

原生端需要使用這些方法:

/**
  * @abstract Fire an event to the component and tell Javascript which value has been changed. 
  * @param eventName 事件名稱慢宗,可以在weex文件某個標簽組件監(jiān)聽嘴脾,命名規(guī)范為 onXXX
  * @param params 數(shù)據(jù)
  * @param domChanges 發(fā)生改變的數(shù)據(jù)
  **/
- (void)fireEvent:(NSString *)eventName params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges

/**
 * fire module event;
 */
- (void)fireModuleEvent:(Class)module eventName:(NSString *)eventName params:(NSDictionary*)params;

/**
 * fire global event
 */
- (void)fireGlobalEvent:(NSString *)eventName params:(NSDictionary *)params;

Weex文檔有這方面描述结澄。
這里補充的是用實例InstanceglobalEvent來操作旅赢。

//添加刷新
if (!scrollView.mj_header) {
    scrollView.mj_header = [HLCustomRefreshHeader headerWithRefreshingBlock:^{
        //調(diào)取JS刷新方法
        if (self.segmentedControl.selectedSegmentIndex == 0) {
            [self.guanzhuInstance fireGlobalEvent:@"refresh" params:nil];
        }else
        {
            [self.guangchangInstance fireGlobalEvent:@"refresh" params:nil];
        }
        resetScrollViewSomePro(scrollView);
    }];
    indestance.endRefreshBlock = ^{
        @strongify(scrollView);
        if (scrollView.mj_header.state != MJRefreshStateIdle) {
            
            [scrollView.mj_header setState:MJRefreshStateIdle];
            resetScrollViewSomePro(scrollView);
        }
    };

這樣就達到了Native調(diào)用JS的目的(Demo中沒有使用這種方式悠就,這是我們公司應(yīng)用針對需求寫的邏輯,可以下載App看一下:Applestore 搜索:葫蘆知識)妈嘹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市序愚,隨后出現(xiàn)的幾起案子埂软,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異的止,居然都是意外死亡赂乐,警方通過查閱死者的電腦和手機挨措,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門担租,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尝艘,“玉大人寄锐,你說我怎么就攤上這事【呶拢” “怎么了蚕涤?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铣猩。 經(jīng)常有香客問我揖铜,道長,這世上最難降的妖魔是什么达皿? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任天吓,我火速辦了婚禮,結(jié)果婚禮上峦椰,老公的妹妹穿的比我還像新娘龄寞。我一直安慰自己,他們只是感情好汤功,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布物邑。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪色解。 梳的紋絲不亂的頭發(fā)上茂嗓,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機與錄音科阎,去河邊找鬼述吸。 笑死,一個胖子當著我的面吹牛锣笨,可吹牛的內(nèi)容都是我干的蝌矛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼票唆,長吁一口氣:“原來是場噩夢啊……” “哼朴读!你這毒婦竟也來了屹徘?” 一聲冷哼從身側(cè)響起走趋,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎噪伊,沒想到半個月后簿煌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡鉴吹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年姨伟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豆励。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡夺荒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出良蒸,到底是詐尸還是另有隱情技扼,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布嫩痰,位于F島的核電站剿吻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏串纺。R本人自食惡果不足惜丽旅,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纺棺。 院中可真熱鬧榄笙,春花似錦、人聲如沸祷蝌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乡翅,卻和暖如春鳞疲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蠕蚜。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工尚洽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人靶累。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓腺毫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挣柬。 傳聞我的和親對象是個殘疾皇子潮酒,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容