资讯专栏INFORMATION COLUMN

Weex系列(5) —— 封装原生组件和模块

娣辩孩 / 1952人阅读

摘要:官网的所有组件和模块的截图在官网扩展版块,是可以找到封装的方法步骤的。封装组件的版块,我把里面的组件代码拿出来了,也是为了后面章节做铺垫吧。

目录

Weex系列(序) —— 总要知道原生的一点东东(iOS)

Weex系列(序) —— 总要知道原生的一点东东(Android)

Weex系列(1) —— Hello World项目

Weex系列(2) —— 页面跳转和通信

Weex系列(3) —— 单页面还是多页面

Weex系列(4) —— 老生常谈的三端统一

Weex系列(5) —— 封装原生组件和模块

[Weex系列(6) —— css相关小结]

[Weex系列(7) —— web组件和webview]

[Weex系列(8) —— 是时候简析一下流程原理了]

[Weex系列(9) —— 踩坑填坑的集锦]

[Weex系列(10) —— 先这么多吧想到再写。。。]

哇,2019年了,时间总是那么快,快过新年了,忙点了也懒点了,还有点想家了,先祝大家新年快乐吧。

这一章官网上有介绍,但还是多带带拎出来讲一讲,因为后期这块用的还是挺多的。

官网的所有组件和模块的截图:

在官网 扩展版块,是可以找到封装的方法步骤的。

自定义模块

iOS:

第一步:

新建 myModule.h

</>复制代码

  1. #import
  2. #import
  3. @interface myModule : NSObject
  4. @end

新建 myModule.m

</>复制代码

  1. #import "myModule.h"
  2. @implementation myModule
  3. WX_EXPORT_METHOD(@selector(log:))
  4. - (void)log:(NSString *)inputParam
  5. {
  6. NSLog(@"%@",inputParam);
  7. }
  8. @end

第二步:

AppDelegate.m里面注册module

</>复制代码

  1. [WXSDKEngine registerModule:@"myModule" withClass:[myModule class]];

Android:

第一步:

新建myModule.java

</>复制代码

  1. public class MyModule extends WXModule {
  2. //run JS thread
  3. @JSMethod (uiThread = false)
  4. public void log(String inputParam) {
  5. Log.d("自定义模块:", inputParam);
  6. }
  7. }

第二步:

WXApplication.java里面注册module

</>复制代码

  1. WXSDKEngine.registerModule("MyModule", MyModule.class);

最后:

在上层vue里面,我们可以require我们自己封装的module,就能够调用原生的log方法,分别在xcode和Android Studio的控制台,看到hello weex的消息了。

这里需要强调一点的是:iOS和Android的module的名字方法要一致,这样在vue里面才能统一的。

</>复制代码

  1. weex.requireModule("myModule").log("hello weex")
自定义组件

组件封装起来比模块是麻烦许多的,一开始也是摸不着头脑,后来就找到weexsdk里面封装的组件,依样画葫芦的开始了。

iOS:

第一步:

新建myComponent.h

</>复制代码

  1. #import "WXComponent.h"
  2. @interface myComponent : WXComponent
  3. - (void)notifyWebview:(NSDictionary *) data;
  4. - (void)reload;
  5. - (void)goBack;
  6. - (void)goForward;
  7. @end

新建myComponent.m

</>复制代码

  1. #import "myComponent.h"
  2. #import
  3. #import
  4. #import "WXUtility.h"
  5. #import "WXURLRewriteProtocol.h"
  6. #import "WXSDKEngine.h"
  7. #import
  8. @interface WXWebView : UIWebView
  9. @end
  10. @implementation WXWebView
  11. - (void)dealloc
  12. {
  13. if (self) {
  14. // self.delegate = nil;
  15. }
  16. }
  17. @end
  18. @interface myComponent ()
  19. @property (nonatomic, strong) JSContext *jsContext;
  20. @property (nonatomic, strong) WXWebView *webview;
  21. @property (nonatomic, strong) NSString *url;
  22. @property (nonatomic, assign) BOOL startLoadEvent;
  23. @property (nonatomic, assign) BOOL finishLoadEvent;
  24. @property (nonatomic, assign) BOOL failLoadEvent;
  25. @property (nonatomic, assign) BOOL notifyEvent;
  26. @end
  27. @implementation myComponent
  28. WX_EXPORT_METHOD(@selector(goBack))
  29. WX_EXPORT_METHOD(@selector(reload))
  30. WX_EXPORT_METHOD(@selector(goForward))
  31. - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance
  32. {
  33. if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
  34. self.url = attributes[@"src"];
  35. }
  36. return self;
  37. }
  38. - (UIView *)loadView
  39. {
  40. return [[WXWebView alloc] init];
  41. }
  42. - (void)viewDidLoad
  43. {
  44. _webview = (WXWebView *)self.view;
  45. _webview.delegate = self;
  46. _webview.allowsInlineMediaPlayback = YES;
  47. _webview.scalesPageToFit = YES;
  48. [_webview setBackgroundColor:[UIColor clearColor]];
  49. _webview.opaque = NO;
  50. _jsContext = [_webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
  51. __weak typeof(self) weakSelf = self;
  52. _jsContext[@"$notifyWeex"] = ^(JSValue *data) {
  53. if (weakSelf.notifyEvent) {
  54. [weakSelf fireEvent:@"notify" params:[data toDictionary]];
  55. }
  56. };
  57. if (_url) {
  58. [self loadURL:_url];
  59. }
  60. }
  61. - (void)updateAttributes:(NSDictionary *)attributes
  62. {
  63. if (attributes[@"src"]) {
  64. self.url = attributes[@"src"];
  65. }
  66. }
  67. - (void)addEvent:(NSString *)eventName
  68. {
  69. if ([eventName isEqualToString:@"pagestart"]) {
  70. _startLoadEvent = YES;
  71. }
  72. else if ([eventName isEqualToString:@"pagefinish"]) {
  73. _finishLoadEvent = YES;
  74. }
  75. else if ([eventName isEqualToString:@"error"]) {
  76. _failLoadEvent = YES;
  77. }
  78. }
  79. - (void)setUrl:(NSString *)url
  80. {
  81. NSString* newURL = [url copy];
  82. WX_REWRITE_URL(url, WXResourceTypeLink, self.weexInstance)
  83. if (!newURL) {
  84. return;
  85. }
  86. if (![newURL isEqualToString:_url]) {
  87. _url = newURL;
  88. if (_url) {
  89. [self loadURL:_url];
  90. }
  91. }
  92. }
  93. - (void)loadURL:(NSString *)url
  94. {
  95. if (self.webview) {
  96. NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:url]];
  97. [self.webview loadRequest:request];
  98. }
  99. }
  100. - (void)reload
  101. {
  102. [self.webview reload];
  103. }
  104. - (void)goBack
  105. {
  106. if ([self.webview canGoBack]) {
  107. [self.webview goBack];
  108. }
  109. }
  110. - (void)goForward
  111. {
  112. if ([self.webview canGoForward]) {
  113. [self.webview goForward];
  114. }
  115. }
  116. - (void)notifyWebview:(NSDictionary *) data
  117. {
  118. NSString *json = [WXUtility JSONString:data];
  119. NSString *code = [NSString stringWithFormat:@"(function(){var evt=null;var data=%@;if(typeof CustomEvent==="function"){evt=new CustomEvent("notify",{detail:data})}else{evt=document.createEvent("CustomEvent");evt.initCustomEvent("notify",true,true,data)}document.dispatchEvent(evt)}())", json];
  120. [_jsContext evaluateScript:code];
  121. }
  122. #pragma mark Webview Delegate
  123. - (NSMutableDictionary *)baseInfo
  124. {
  125. NSMutableDictionary *info = [NSMutableDictionary new];
  126. [info setObject:self.webview.request.URL.absoluteString ?: @"" forKey:@"url"];
  127. [info setObject:[self.webview stringByEvaluatingJavaScriptFromString:@"document.title"] ?: @"" forKey:@"title"];
  128. [info setObject:@(self.webview.canGoBack) forKey:@"canGoBack"];
  129. [info setObject:@(self.webview.canGoForward) forKey:@"canGoForward"];
  130. return info;
  131. }
  132. - (void)webViewDidStartLoad:(UIWebView *)webView
  133. {
  134. }
  135. - (void)webViewDidFinishLoad:(UIWebView *)webView
  136. {
  137. if (_finishLoadEvent) {
  138. NSDictionary *data = [self baseInfo];
  139. [self fireEvent:@"pagefinish" params:data domChanges:@{@"attrs": @{@"src":self.webview.request.URL.absoluteString}}];
  140. }
  141. }
  142. - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
  143. {
  144. if (_failLoadEvent) {
  145. NSMutableDictionary *data = [self baseInfo];
  146. [data setObject:[error localizedDescription] forKey:@"errorMsg"];
  147. [data setObject:[NSString stringWithFormat:@"%ld", (long)error.code] forKey:@"errorCode"];
  148. NSString * urlString = error.userInfo[NSURLErrorFailingURLStringErrorKey];
  149. if (urlString) {
  150. // webview.request may not be the real error URL, must get from error.userInfo
  151. [data setObject:urlString forKey:@"url"];
  152. if (![urlString hasPrefix:@"http"]) {
  153. return;
  154. }
  155. }
  156. [self fireEvent:@"error" params:data];
  157. }
  158. }
  159. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
  160. {
  161. if (_startLoadEvent) {
  162. NSMutableDictionary *data = [NSMutableDictionary new];
  163. [data setObject:request.URL.absoluteString ?:@"" forKey:@"url"];
  164. [self fireEvent:@"pagestart" params:data];
  165. }
  166. return YES;
  167. }
  168. @end

第二步:

AppDelegate.m里面注册component

</>复制代码

  1. [WXSDKEngine registerComponent:@"myComponent" withClass:[myComponent class]];

这里需要说明:上面基本上是照着weexsdk里面的webview组件改的,而且就是改了一下名字,方法什么的大家就可以自由发挥了。

Android:

第一步:

新建myComponent.java

</>复制代码

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package com.taobao.weex.ui.component;
  20. import android.content.Context;
  21. import android.net.Uri;
  22. import android.support.annotation.NonNull;
  23. import android.text.TextUtils;
  24. import android.view.View;
  25. import com.taobao.weex.WXSDKInstance;
  26. import com.taobao.weex.annotation.Component;
  27. import com.taobao.weex.adapter.URIAdapter;
  28. import com.taobao.weex.common.Constants;
  29. import com.taobao.weex.dom.WXDomObject;
  30. import com.taobao.weex.ui.view.IWebView;
  31. import com.taobao.weex.ui.view.WXWebView;
  32. import com.taobao.weex.utils.WXUtils;
  33. import java.util.HashMap;
  34. import java.util.Map;
  35. @Component(lazyload = false)
  36. public class myComponent extends WXComponent {
  37. public static final String GO_BACK = "goBack";
  38. public static final String GO_FORWARD = "goForward";
  39. public static final String RELOAD = "reload";
  40. protected IWebView mWebView;
  41. @Deprecated
  42. public myComponent(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, String instanceId, boolean isLazy) {
  43. this(instance,dom,parent,isLazy);
  44. }
  45. public myComponent(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, boolean isLazy) {
  46. super(instance, dom, parent, isLazy);
  47. createWebView();
  48. }
  49. protected void createWebView(){
  50. mWebView = new WXWebView(getContext());
  51. }
  52. @Override
  53. protected View initComponentHostView(@NonNull Context context) {
  54. mWebView.setOnErrorListener(new IWebView.OnErrorListener() {
  55. @Override
  56. public void onError(String type, Object message) {
  57. fireEvent(type, message);
  58. }
  59. });
  60. mWebView.setOnPageListener(new IWebView.OnPageListener() {
  61. @Override
  62. public void onReceivedTitle(String title) {
  63. if (getDomObject().getEvents().contains(Constants.Event.RECEIVEDTITLE)) {
  64. Map params = new HashMap<>();
  65. params.put("title", title);
  66. fireEvent(Constants.Event.RECEIVEDTITLE, params);
  67. }
  68. }
  69. @Override
  70. public void onPageStart(String url) {
  71. if ( getDomObject().getEvents().contains(Constants.Event.PAGESTART)) {
  72. Map params = new HashMap<>();
  73. params.put("url", url);
  74. fireEvent(Constants.Event.PAGESTART, params);
  75. }
  76. }
  77. @Override
  78. public void onPageFinish(String url, boolean canGoBack, boolean canGoForward) {
  79. if ( getDomObject().getEvents().contains(Constants.Event.PAGEFINISH)) {
  80. Map params = new HashMap<>();
  81. params.put("url", url);
  82. params.put("canGoBack", canGoBack);
  83. params.put("canGoForward", canGoForward);
  84. fireEvent(Constants.Event.PAGEFINISH, params);
  85. }
  86. }
  87. });
  88. return mWebView.getView();
  89. }
  90. @Override
  91. public void destroy() {
  92. super.destroy();
  93. getWebView().destroy();
  94. }
  95. @Override
  96. protected boolean setProperty(String key, Object param) {
  97. switch (key) {
  98. case Constants.Name.SHOW_LOADING:
  99. Boolean result = WXUtils.getBoolean(param,null);
  100. if (result != null)
  101. setShowLoading(result);
  102. return true;
  103. case Constants.Name.SRC:
  104. String src = WXUtils.getString(param,null);
  105. if (src != null)
  106. setUrl(src);
  107. return true;
  108. }
  109. return super.setProperty(key,param);
  110. }
  111. @WXComponentProp(name = Constants.Name.SHOW_LOADING)
  112. public void setShowLoading(boolean showLoading) {
  113. getWebView().setShowLoading(showLoading);
  114. }
  115. @WXComponentProp(name = Constants.Name.SRC)
  116. public void setUrl(String url) {
  117. if (TextUtils.isEmpty(url) || getHostView() == null) {
  118. return;
  119. }
  120. if (!TextUtils.isEmpty(url)) {
  121. loadUrl(getInstance().rewriteUri(Uri.parse(url), URIAdapter.WEB).toString());
  122. }
  123. }
  124. public void setAction(String action) {
  125. if (!TextUtils.isEmpty(action)) {
  126. if (action.equals(GO_BACK)) {
  127. goBack();
  128. } else if (action.equals(GO_FORWARD)) {
  129. goForward();
  130. } else if (action.equals(RELOAD)) {
  131. reload();
  132. }
  133. }
  134. }
  135. private void fireEvent(String type, Object message) {
  136. if (getDomObject().getEvents().contains(Constants.Event.ERROR)) {
  137. Map params = new HashMap<>();
  138. params.put("type", type);
  139. params.put("errorMsg", message);
  140. fireEvent(Constants.Event.ERROR, params);
  141. }
  142. }
  143. private void loadUrl(String url) {
  144. getWebView().loadUrl(url);
  145. }
  146. private void reload() {
  147. getWebView().reload();
  148. }
  149. private void goForward() {
  150. getWebView().goForward();
  151. }
  152. private void goBack() {
  153. getWebView().goBack();
  154. }
  155. private IWebView getWebView() {
  156. return mWebView;
  157. }
  158. }

第二步:

WXApplication.java里面注册component

</>复制代码

  1. WXSDKEngine.registerComponent("myComponent", myComponent.class);

最后:

在上层vue里面,我们就可以直接使用封装好的组件。

这里需要强调一点的是:iOS和Android的组件名字一定要一致,这样在vue里面才能统一的。

</>复制代码

小结

1、从上面可以看出不管是组件还是模块,都是要iOS和Android各封装一套的,而且名字还要一致,如果兼容web端,还要做web的扩展,这样才能三端统一的。
2、封装组件的版块,我把weex sdk里面的web组件代码拿出来了,也是为了后面webview章节做铺垫吧。
3、建议大家可以多看看weex sdk的源码,(这里请忘掉我只是一个前端,我干嘛还要学习oc、java的这些想法吧)其实也还好,也可能是目前我们的项目没有太复杂,封装的还不是很多,也还算简单,谷歌上一搜基本都能解决吧。

最后祝大家新的一年,少点bug,多点money,越来越好吧。

如果喜欢就请点个赞收藏一下啦~~~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100842.html

相关文章

  • Weex系列(5) —— 封装原生组件模块

    摘要:官网的所有组件和模块的截图在官网扩展版块,是可以找到封装的方法步骤的。封装组件的版块,我把里面的组件代码拿出来了,也是为了后面章节做铺垫吧。 目录 Weex系列(序) —— 总要知道原生的一点东东(iOS) Weex系列(序) —— 总要知道原生的一点东东(Android) Weex系列(1) —— Hello World项目 Weex系列(2) —— 页面跳转和通信 Weex系列(...

    Rindia 评论0 收藏0
  • Weex系列(4) —— 老生常谈的三端统一

    摘要:刚看到这仨页面的时候,我就想着可以用路由,做成三端统一。样式这部分真的三端基本是高度统一的,部分微调一下就可以了,也正是这样,我们后续才能迅速解决和。终于不是谈谈三端统一了,也是真的体验了一次,虽然最后有点出入,但是下次基本是没问题了。 目录 Weex系列(序) —— 总要知道原生的一点东东(iOS) Weex系列(序) —— 总要知道原生的一点东东(Android) Weex系列(...

    wzyplus 评论0 收藏0
  • Weex系列(1) ——Hello World项目

    摘要:由于最开始没有一点点原生开发的经验,所以我就直接用的脚手架初始化项目。那下面我们就从最最原始的项目开始吧,序篇太枯燥,自由发挥时间开始啦。执行如下代码,最后会得到如图的项目结构。入口文件等简析进行了初始化。 目录 Weex系列(序) —— 总要知道原生的一点东东(iOS) Weex系列(序) —— 总要知道原生的一点东东(Android) Weex系列(1) —— Hello Wor...

    xiaowugui666 评论0 收藏0
  • Weex系列(6) —— web组件webview

    摘要:安卓要麻烦许多,网上大多也都是安卓的讲解,我也是遇到了好多坑。我是在里面重新绘制了一下,在适配的时候会用到,安卓倒是没有怎么处理。 目录 Weex系列(序) —— 总要知道原生的一点东东(iOS) Weex系列(序) —— 总要知道原生的一点东东(Android) Weex系列(1) —— Hello World项目 Weex系列(2) —— 页面跳转和通信 Weex系列(3) ——...

    LucasTwilight 评论0 收藏0

发表评论

0条评论

娣辩孩

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<