Weex系列(9) —— Weex和安卓升级兼容

目录Weex系列(序) —— 总要知道原生的一点东东(iOS)Weex系列(序) —— 总要知道原生的一点东东(Android)Weex系列(1) —— Hello World项目Weex系列(2) —— 页面跳转和通信Weex系列(3) —— 单页面还是多页面Weex系列(4) —— 老生常谈的三端统一Weex系列(5) —— 封装原生组件和模块Weex系列(6) —— webview和web组件Weex系列(7) —— 踩坑填坑的总总[Weex系列(8) —— 原理流程简析]Weex系列(9) —— Weex和安卓升级兼容最近刚升级,先新开一章记录一下吧,怕忘了(doge)。1、Weex升级相关iOS:pod ‘WeexSDK’, ‘0.20.1’目前来看倒是没有什么问题,后续再说。Android:compile ‘com.taobao.android:weex_sdk:0.20.0.2’Android就有问题喽,一堆如下的问题。方法接口什么的直接移除,真是个狠人啊,这个只能大家一个个文件去改喽,官网链接:https://weex.apache.org/zh/gu…比如我这边是把public GifImage(WXSDKInstance instance, WXDomObject dom, WXVContainer parent) { super(instance, dom, parent); }换成:@Deprecated public GifImage(WXSDKInstance instance, WXVContainer parent, String instanceId, boolean isLazy, BasicComponentData basicComponentData) { this(instance, parent, basicComponentData); } public GifImage(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) { super(instance, parent, basicComponentData); }2、安卓升级相关升级之前先来解释3个sdk吧:原文章:https://medium.com/androiddev…compileSdkVersioncompileSdkVersion是告诉Gradle用哪个版本Android SDK编译应用程序。使用新API的时候,就需要升级对应版本的Android SDK了。应该强调的是,更改compileSdkVersion不会改变运行时行为。虽然更改compileSdkVersion时可能存在新的编译器警告/错误,但您的compileSdkVersion不包含在您的APK中:它纯粹在编译时使用。 (你应该确实修复这些警告 - 它们是因为某种原因而添加的!)因此,强烈建议您始终使用最新的SDK进行编译。您将获得对现有代码进行新编译检查的所有好处,避免新弃用的API,并准备好使用新API。minSdkVersion如果compileSdkVersion表示能否能用最新API,那minSdkVersion就是应用能运行的最低版本,如果用户的装置小于这个值,在Google Play商店就会不显示。我在网上搜了一下设置14、15基本就是底线了,能覆盖Google Play商店99.9%的用户吧。targetSdkVersion三者中最有趣的是targetSdkVersion。targetSdkVersion是Android 提供向前兼容的主要依据。比如用户系统是26,现在升级到了27,其中有一个方法26和27是不同的,但是如果应用的targetSdkVersion设置的是26,应用仍旧使用的是26的方法。在升级的过程中主要遇到的就是下面这个错误:在stackoverflow上找的解决办法:https://stackoverflow.com/que…A. Add this line in the defaultConfig section to enable multiDexmultiDexEnabled trueB. Than set the dexOptions, like this:dexOptions { incremental true javaMaxHeapSize “4G”}我这边改完如图:最后还是感谢大家,如果喜欢欢迎点赞收藏啊~ ...

March 6, 2019 · 1 min · jiezi

Weex系列(6) —— web组件和webview

目录Weex系列(序) —— 总要知道原生的一点东东(iOS)Weex系列(序) —— 总要知道原生的一点东东(Android)Weex系列(1) —— Hello World项目Weex系列(2) —— 页面跳转和通信Weex系列(3) —— 单页面还是多页面Weex系列(4) —— 老生常谈的三端统一Weex系列(5) —— 封装原生组件和模块Weex系列(6) —— webview和web组件[Weex系列(7) —— 踩坑填坑的集锦][Weex系列(8) —— 原理流程简析]不知不觉就3月1号了,这段时间在想怎么来收尾这个系列,打算把css小结放在踩坑那一章,那一章以后估计也会不定时更新。最后一章就简单分析一下流程原理。还是言归正传吧,webview是一个基于webkit引擎、展现web页面的控件,app里面是经常用到的,weex官方提供了web组件。webview这块是比较复杂的,所以官方提供的远远不够,但是对原生又不是很熟悉,就找到组件源码,在此基础上再进行二次封装,上一章也是有很详细的提到的。进行了二次封装,我们想添加功能配置什么的就方便很多了。iOSiOS端的webview坑要少一些,几乎没怎么改过,主要就是html和原生的交互。1、可以用到URL Schemes来拦截做一些简单的跳转处理2、实在绕不过,就用到了一个比较复杂的WebViewJavascriptBridge,我用的就是谷歌搜出来第一个,参照例子加在我们自己封装的组件里面了,我这边直接就加在了viewWillAppear方法里面,同理也需要在html里面配置,最后app就能监听到html里面的点击等交互动作了。Android安卓要麻烦许多,网上大多也都是安卓的webview讲解,我也是遇到了好多坑。我把网上需要配置的基本都加上了,每个设置的说明看方法能猜出一二。1、然后就是shouldOverrideUrlLoading,页面跳转遇到的无限加载、白屏等都需要在这个方法里面做处理,由于这块涉及业务处理,也就不截出来了,我也是参照网上的方案解决的,需要耐心,多试几次,会解决的。private void initWebView(WebView wv) { WebSettings settings = wv.getSettings(); settings.setAppCacheEnabled(true); settings.setAllowFileAccess(true);//设置启用或禁止访问文件数据 settings.setDomStorageEnabled(true); settings.setLoadsImagesAutomatically(true); //适应屏幕 settings.setUseWideViewPort(true); // 设置可以支持缩放 settings.setSupportZoom(true); // 设置出现缩放工具 settings.setBuiltInZoomControls(true); //不显示webview缩放按钮 settings.setDisplayZoomControls(false); settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); settings.setLoadWithOverviewMode(true); // 设置与Js交互的权限 settings.setJavaScriptEnabled(true); // 设置允许JS弹窗 settings.setJavaScriptCanOpenWindowsAutomatically(true); //设置字体大小 settings.setTextZoom(100); wv.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {2、接着就是安卓的上传图片文件,用到了如下的方法,最后用到的是WXWebView.mUploadCallbackAboveL 回传图片的// For Android < 3.0 public void openFileChooser(ValueCallback<Uri> valueCallback) { mUploadMessage = valueCallback; openImageChooserActivity(); } // For Android >= 3.0 public void openFileChooser(ValueCallback valueCallback, String acceptType) { mUploadMessage = valueCallback; openImageChooserActivity(); } //For Android >= 4.1 public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) { //Log.e(TAG, “onShowFileChooser: “+acceptType); mUploadMessage = valueCallback; openImageChooserActivity(); } // For Android >= 5.0 @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { //Log.e(TAG, “onShowFileChooser: “+fileChooserParams); mUploadCallbackAboveL = filePathCallback; openImageChooserActivity(); return true; }3、还有一个点是webview里面音视频播放,退出页面,还会有声音等,可以在原生.java的onPause方法里面做处理,我记得这个没处理的时候有的安卓应用商店都是审核不过的。@Override public void onPause() { super.onPause(); if(WXWebView.mWebView != null){ WXWebView.mWebView.pauseTimers(); //这里只对页面中只有一个音频的情况做了处理,如果有多个音频需要遍历整个数组记录状态 WXWebView.mWebView.loadUrl( “javascript:audioEty = document.getElementsByTagName(‘audio’)[0]; audioEty.pause();” ); WXWebView.mWebView.loadUrl( “javascript:videoEty = document.getElementsByTagName(‘video’)[0]; videoEty.pause();” ); WXWebView.mWebView.onPause(); } }页面宽高适配最后本来是打算想把app的宽高适配等问题放在css那个小结的,但是现在归类在了踩坑里面,就把这个放在这儿讲吧。1、iOS我是在viewDidLayoutSubviews里面重新绘制了一下,在适配iPhoneX、XR、XMAX的时候会用到,安卓倒是没有怎么处理。_instance.frame = CGRectMake(safeArea.left, safeArea.top, self.view.frame.size.width-safeArea.left-safeArea.right, _weexHeight-safeArea.top);2、weex官网config这一章里面有讲到这个例子,大家也可以扫码看一下,主要就是weex.config.env.deviceWidth和weex.config.env.deviceHeight。最后这个系列就剩下两章了,下一篇也会尽快发布出来,感谢大家,如果喜欢欢迎收藏点赞啊~ ...

March 1, 2019 · 1 min · jiezi

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

目录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#import <Foundation/Foundation.h>#import <WeexSDK/WXModuleProtocol.h>@interface myModule : NSObject<WXModuleProtocol>@end新建 myModule.m#import “myModule.h”@implementation myModuleWX_EXPORT_METHOD(@selector(log:))- (void)log:(NSString *)inputParam{ NSLog(@"%@",inputParam);}@end第二步:AppDelegate.m里面注册module[WXSDKEngine registerModule:@“myModule” withClass:[myModule class]];Android:第一步:新建myModule.javapublic class MyModule extends WXModule { //run JS thread @JSMethod (uiThread = false) public void log(String inputParam) { Log.d(“自定义模块:”, inputParam); }}第二步:WXApplication.java里面注册moduleWXSDKEngine.registerModule(“MyModule”, MyModule.class);最后:在上层vue里面,我们可以require我们自己封装的module,就能够调用原生的log方法,分别在xcode和Android Studio的控制台,看到hello weex的消息了。这里需要强调一点的是:iOS和Android的module的名字方法要一致,这样在vue里面才能统一的。weex.requireModule(“myModule”).log(“hello weex”)自定义组件组件封装起来比模块是麻烦许多的,一开始也是摸不着头脑,后来就找到weexsdk里面封装的组件,依样画葫芦的开始了。iOS:第一步:新建myComponent.h#import “WXComponent.h”@interface myComponent : WXComponent<UIWebViewDelegate>- (void)notifyWebview:(NSDictionary *) data;- (void)reload;- (void)goBack;- (void)goForward;@end新建myComponent.m#import “myComponent.h”#import <WeexSDK/WXComponent.h>#import <WeexSDK/WXComponentManager.h>#import “WXUtility.h”#import “WXURLRewriteProtocol.h”#import “WXSDKEngine.h”#import <JavaScriptCore/JavaScriptCore.h>@interface WXWebView : UIWebView@end@implementation WXWebView- (void)dealloc{ if (self) {// self.delegate = nil; }}@end@interface myComponent ()@property (nonatomic, strong) JSContext *jsContext;@property (nonatomic, strong) WXWebView *webview;@property (nonatomic, strong) NSString *url;@property (nonatomic, assign) BOOL startLoadEvent;@property (nonatomic, assign) BOOL finishLoadEvent;@property (nonatomic, assign) BOOL failLoadEvent;@property (nonatomic, assign) BOOL notifyEvent;@end@implementation myComponentWX_EXPORT_METHOD(@selector(goBack))WX_EXPORT_METHOD(@selector(reload))WX_EXPORT_METHOD(@selector(goForward))- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance{ if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) { self.url = attributes[@“src”]; } return self;}- (UIView *)loadView{ return [[WXWebView alloc] init];}- (void)viewDidLoad{ _webview = (WXWebView *)self.view; _webview.delegate = self; _webview.allowsInlineMediaPlayback = YES; _webview.scalesPageToFit = YES; [_webview setBackgroundColor:[UIColor clearColor]]; _webview.opaque = NO; _jsContext = [_webview valueForKeyPath:@“documentView.webView.mainFrame.javaScriptContext”]; __weak typeof(self) weakSelf = self; _jsContext[@"$notifyWeex"] = ^(JSValue *data) { if (weakSelf.notifyEvent) { [weakSelf fireEvent:@“notify” params:[data toDictionary]]; } }; if (_url) { [self loadURL:_url]; }}- (void)updateAttributes:(NSDictionary *)attributes{ if (attributes[@“src”]) { self.url = attributes[@“src”]; }}- (void)addEvent:(NSString *)eventName{ if ([eventName isEqualToString:@“pagestart”]) { _startLoadEvent = YES; } else if ([eventName isEqualToString:@“pagefinish”]) { _finishLoadEvent = YES; } else if ([eventName isEqualToString:@“error”]) { _failLoadEvent = YES; }}- (void)setUrl:(NSString )url{ NSString newURL = [url copy]; WX_REWRITE_URL(url, WXResourceTypeLink, self.weexInstance) if (!newURL) { return; } if (![newURL isEqualToString:_url]) { _url = newURL; if (_url) { [self loadURL:_url]; } }}- (void)loadURL:(NSString *)url{ if (self.webview) { NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:url]]; [self.webview loadRequest:request]; }}- (void)reload{ [self.webview reload];}- (void)goBack{ if ([self.webview canGoBack]) { [self.webview goBack]; }}- (void)goForward{ if ([self.webview canGoForward]) { [self.webview goForward]; }}- (void)notifyWebview:(NSDictionary *) data{ NSString *json = [WXUtility JSONString:data]; 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]; [_jsContext evaluateScript:code];}#pragma mark Webview Delegate- (NSMutableDictionary<NSString *, id> *)baseInfo{ NSMutableDictionary<NSString *, id> *info = [NSMutableDictionary new]; [info setObject:self.webview.request.URL.absoluteString ?: @"" forKey:@“url”]; [info setObject:[self.webview stringByEvaluatingJavaScriptFromString:@“document.title”] ?: @"" forKey:@“title”]; [info setObject:@(self.webview.canGoBack) forKey:@“canGoBack”]; [info setObject:@(self.webview.canGoForward) forKey:@“canGoForward”]; return info;}- (void)webViewDidStartLoad:(UIWebView *)webView{ }- (void)webViewDidFinishLoad:(UIWebView *)webView{ if (_finishLoadEvent) { NSDictionary *data = [self baseInfo]; [self fireEvent:@“pagefinish” params:data domChanges:@{@“attrs”: @{@“src”:self.webview.request.URL.absoluteString}}]; }}- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{ if (_failLoadEvent) { NSMutableDictionary *data = [self baseInfo]; [data setObject:[error localizedDescription] forKey:@“errorMsg”]; [data setObject:[NSString stringWithFormat:@"%ld", (long)error.code] forKey:@“errorCode”]; NSString * urlString = error.userInfo[NSURLErrorFailingURLStringErrorKey]; if (urlString) { // webview.request may not be the real error URL, must get from error.userInfo [data setObject:urlString forKey:@“url”]; if (![urlString hasPrefix:@“http”]) { return; } } [self fireEvent:@“error” params:data]; }}- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ if (_startLoadEvent) { NSMutableDictionary<NSString *, id> data = [NSMutableDictionary new]; [data setObject:request.URL.absoluteString ?:@"" forKey:@“url”]; [self fireEvent:@“pagestart” params:data]; } return YES;}@end第二步:AppDelegate.m里面注册component[WXSDKEngine registerComponent:@“myComponent” withClass:[myComponent class]];这里需要说明:上面基本上是照着weexsdk里面的webview组件改的,而且就是改了一下名字,方法什么的大家就可以自由发挥了。Android:第一步:新建myComponent.java/ * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * “License”); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */package com.taobao.weex.ui.component;import android.content.Context;import android.net.Uri;import android.support.annotation.NonNull;import android.text.TextUtils;import android.view.View;import com.taobao.weex.WXSDKInstance;import com.taobao.weex.annotation.Component;import com.taobao.weex.adapter.URIAdapter;import com.taobao.weex.common.Constants;import com.taobao.weex.dom.WXDomObject;import com.taobao.weex.ui.view.IWebView;import com.taobao.weex.ui.view.WXWebView;import com.taobao.weex.utils.WXUtils;import java.util.HashMap;import java.util.Map;@Component(lazyload = false)public class myComponent extends WXComponent { public static final String GO_BACK = “goBack”; public static final String GO_FORWARD = “goForward”; public static final String RELOAD = “reload”; protected IWebView mWebView; @Deprecated public myComponent(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, String instanceId, boolean isLazy) { this(instance,dom,parent,isLazy); } public myComponent(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, boolean isLazy) { super(instance, dom, parent, isLazy); createWebView(); } protected void createWebView(){ mWebView = new WXWebView(getContext()); } @Override protected View initComponentHostView(@NonNull Context context) { mWebView.setOnErrorListener(new IWebView.OnErrorListener() { @Override public void onError(String type, Object message) { fireEvent(type, message); } }); mWebView.setOnPageListener(new IWebView.OnPageListener() { @Override public void onReceivedTitle(String title) { if (getDomObject().getEvents().contains(Constants.Event.RECEIVEDTITLE)) { Map<String, Object> params = new HashMap<>(); params.put(“title”, title); fireEvent(Constants.Event.RECEIVEDTITLE, params); } } @Override public void onPageStart(String url) { if ( getDomObject().getEvents().contains(Constants.Event.PAGESTART)) { Map<String, Object> params = new HashMap<>(); params.put(“url”, url); fireEvent(Constants.Event.PAGESTART, params); } } @Override public void onPageFinish(String url, boolean canGoBack, boolean canGoForward) { if ( getDomObject().getEvents().contains(Constants.Event.PAGEFINISH)) { Map<String, Object> params = new HashMap<>(); params.put(“url”, url); params.put(“canGoBack”, canGoBack); params.put(“canGoForward”, canGoForward); fireEvent(Constants.Event.PAGEFINISH, params); } } }); return mWebView.getView(); } @Override public void destroy() { super.destroy(); getWebView().destroy(); } @Override protected boolean setProperty(String key, Object param) { switch (key) { case Constants.Name.SHOW_LOADING: Boolean result = WXUtils.getBoolean(param,null); if (result != null) setShowLoading(result); return true; case Constants.Name.SRC: String src = WXUtils.getString(param,null); if (src != null) setUrl(src); return true; } return super.setProperty(key,param); } @WXComponentProp(name = Constants.Name.SHOW_LOADING) public void setShowLoading(boolean showLoading) { getWebView().setShowLoading(showLoading); } @WXComponentProp(name = Constants.Name.SRC) public void setUrl(String url) { if (TextUtils.isEmpty(url) || getHostView() == null) { return; } if (!TextUtils.isEmpty(url)) { loadUrl(getInstance().rewriteUri(Uri.parse(url), URIAdapter.WEB).toString()); } } public void setAction(String action) { if (!TextUtils.isEmpty(action)) { if (action.equals(GO_BACK)) { goBack(); } else if (action.equals(GO_FORWARD)) { goForward(); } else if (action.equals(RELOAD)) { reload(); } } } private void fireEvent(String type, Object message) { if (getDomObject().getEvents().contains(Constants.Event.ERROR)) { Map<String, Object> params = new HashMap<>(); params.put(“type”, type); params.put(“errorMsg”, message); fireEvent(Constants.Event.ERROR, params); } } private void loadUrl(String url) { getWebView().loadUrl(url); } private void reload() { getWebView().reload(); } private void goForward() { getWebView().goForward(); } private void goBack() { getWebView().goBack(); } private IWebView getWebView() { return mWebView; }}第二步:WXApplication.java里面注册componentWXSDKEngine.registerComponent(“myComponent”, myComponent.class);最后:在上层vue里面,我们就可以直接使用封装好的组件。这里需要强调一点的是:iOS和Android的组件名字一定要一致,这样在vue里面才能统一的。<myComponent src=“url” class=“webview” :style="{ height : screenHeight+‘px’ }"></myComponent>小结1、从上面可以看出不管是组件还是模块,都是要iOS和Android各封装一套的,而且名字还要一致,如果兼容web端,还要做web的扩展,这样才能三端统一的。2、封装组件的版块,我把weex sdk里面的web组件代码拿出来了,也是为了后面webview章节做铺垫吧。3、建议大家可以多看看weex sdk的源码,(这里请忘掉我只是一个前端,我干嘛还要学习oc、java的这些想法吧)其实也还好,也可能是目前我们的项目没有太复杂,封装的还不是很多,也还算简单,谷歌上一搜基本都能解决吧。最后祝大家新的一年,少点bug,多点money,越来越好吧。如果喜欢就请点个赞收藏一下啦~~~ ...

January 8, 2019 · 5 min · jiezi

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

Hello World项目之后就在想着这个系列接下来该怎么写,那就先简单拟个目录吧,一方面督促自己能坚持下去,一方面如果大家有兴趣的话,也请多多关注我的专栏,顺手点个赞啊~~目录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) —— 先这么多吧想到在写。。。]大致就是这个顺序吧,可能会微调,那下面就开始这一章吧。入口标题上加了官网怎么集成Weex到已有应用的链接,里面提到了很重要的入口方法。iOSNSURL *URL = [self testURL: [self.url absoluteString]];NSString *randomURL = [NSString stringWithFormat:@"%@%@random=%d",URL.absoluteString,URL.query?@"&":@"?",arc4random()];[_instance renderWithURL:[NSURL URLWithString:randomURL] options:@{@“bundleUrl”:URL.absoluteString} data:nil];这是前一篇用weex脚手架初始化的helloworld项目,在WXDemoViewController.m的render方法里面可以看到这段代码。然后重点来了,weex.config.bundleUrl的值:1、取得是上面options的bundleUrl值2、如果这个值不填,取得就是我们赋给renderWithURL的url地址。所以如果我们加载服务器上的一个页面js,然后这个页面又想跳回到本地的一个页面js,那么在服务器页面取bundleUrl的时候取得就是http的一个地址,是取不到我们想要跳到本地页面js绝对前缀地址的,有点绕,最后就讲讲我们App的思路吧。我做的两个App页面全部都是用vue写的,所以首页、tab页肯定的页面js肯定是的打在包里面的,我们也有做过拉新的活动页,这个页面就可以放在服务器上,支持热更新啊,就遇到了上面的跳转问题,我是全局取了一个bundlejs的绝对地址,在服务器上的页面也就是我们的拉新活动页面里面直接用这个地址就跳回到本地的页面了- (void)renderWithURL:(NSURL *)url options:(NSDictionary )options data:(id)data{ if (!url) { WXLogError(@“Url must be passed if you use renderWithURL”); return; } self.needValidate = [[WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)] needValidate:url]; WXResourceRequest request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy]; [self _renderWithRequest:request options:options data:data]; [WXTracingManager startTracingWithInstanceId:self.instanceId ref:nil className:nil name:WXTNetworkHanding phase:WXTracingBegin functionName:@“renderWithURL” options:@{@“bundleUrl”:url?[url absoluteString]:@"",@“threadName”:WXTMainThread}];}Android可以在WXSDKInstance.java里面可以看到render(pageName,template,options,jsonInitData,flag);renderByUrl(pageName,url,options,jsonInitData,flag);安卓和iOS基本类似,但是这儿有两个方法,官网的文档是render,这一个render害死人啊,不过用weex脚手架初始化的项目用的是renderByUrl,所以如果官网直接用脚手架开发的,躲过一劫啊。可以看到这两个方法就差了第二个参数,下面是官网的代码,用render方法的时候,第二个参数里面得用WXFileUtils.loadFileContent这个方法,而且如果option不填的话bundleUrl是取不到js地址?后面我们加的参数的/ * WXSample 可以替换成自定义的字符串,针对埋点有效。 * template 是.we transform 后的 js文件。 * option 可以为空,或者通过option传入 js需要的参数。例如bundle js的地址等。 * jsonInitData 可以为空。 * width 为-1 默认全屏,可以自己定制。 * height =-1 默认全屏,可以自己定制。 */mWXSDKInstance.render(“WXSample”,WXFileUtils.loadFileContent(“hello.js”, this), null, null, -1, -1, WXRenderStrategy.APPEND_ASYNC);下面就来说说几种常见的跳转吧Native -> Weex也就是用开头我们提到的两个方法,然后把我们的bundlejs地址传入就可以打开Weex页面了Weex -> Native这个我这边用的很少,大概思路就是,拦截处理,iOS用Scheme、[[UIApplication sharedApplication] openURL:weburl];吧,Android用intent-filter吧。Weex -> Weex大家在我的helloworld那篇bundlejs小节里面有一个路径截图,可以对比代码参考一下,下面我也把iOS和Android的bundlejs路径图截出来了。const device = weex.config.env;getBaseUrl(url) { if (device.platform === ‘iOS’) { nativeBase = url.substring(0, bundleUrl.lastIndexOf(’/’) + 1); } else { nativeBase = ‘file://assets/dist/’; }}Weex页面A:Weex页面B的地址BUrl=getBaseUrl(weex.config.bundleUrl)+B.jsnavigator.push({url:BUrl}, function(e) {});webview -> Weex这也是比较常遇到的一个跳转,大概思路和Weex跳原生类似,也是一个拦截处理,这一块就放在后面Weex系列(7) —— web组件和webview这个章节讲吧。页面通信这块用的比较多的大概有三种。bundlejs路径地址传参就如标题描述的一样,weex.config.bundleUrl拿到类似A.js?a=1&b=2,和解析网页地址一样,拿到A传给B的a、b后面的值。BroadcastChannel我们在B页面操作完成之后,navigator.pop()之后回到A页面,希望A页面的button状态改变,因为页面是栈式操作,A页面不会自动刷新,可以用Weex提供的这个BroadcastChannel通道来解决,具体操作,大家点击标题就可以了解了。storage感觉这个大家应该非常熟悉,对,Weex也提供给我们了,我们可以愉快的在页面上使用了。globalevent最后还是提一下这个globalEvent,Weex和原生通过这个可以通信,这个我们用到的还是挺多的,大家也可以去官网了解一下呦。就这么多吧,欢迎大家关注我的专栏啊,如果有一点点喜欢,也请点个赞啊~ ...

November 14, 2018 · 1 min · jiezi