weex相关原理,请看官方网站
此IOS Weex demo实现的功能,从原生界面跳转到Weex容器页面,然后点击Weex容器页面的button(js)跳转到另一个原生界面。
一. 先上效果图
二.实现
1. weex容器渲染的js代码如下,上面第二张图的代码
启动一个本地的Node环境,可以通过浏览器访问,也可以通过Weex容器渲染成上面的第二张图的界面
import { createElement, Component } from 'rax';
import View from 'rax-view';
import Text from 'rax-text';
import Button from 'rax-button';
import { setTitle, openUrl, getAppStoken } from 'lib/jsbridge';
import styles from './app.css';
class APP extends Component {
constructor(props) {
super(props);
this.state = {
timesPressed1: 0,
list: [],
};
}
componentDidMount() {
// alert('请求错误'); // eslint-disable-line
}
handlePress = () => {
this.setState({
timesPressed1: this.state.timesPressed1 + 1,
});
// alert('弹框测试!!!'); // eslint-disable-line
openUrl({
// url: 'weex://go/scan',
url: 'weex://go/ljDetail?orderId=123',
});
};
render() {
return (
<View style={styles.body}>
<Text style={styles.loadingText}>当前页面是个weex容器</Text>
<Text style={styles.loadingText}>加载的是个weex页面</Text>
<Button style={styles.button} onPress={this.handlePress}>点击我从weex页面跳转到原生</Button>
</View>
);
}
}
export default APP;
2. 原生的Weex容器
NSString *url = @"http://10.50.62.53:9999/wxTest/index.html?lj_weexurl=http://10.50.62.53:9999/wxTest/index.js";
此容器的设计,当Weex加载失败的时候,可以将当前的展示成html页面,加载的是wxTest/index.html页面,不影响使用。
当Weex加载成功的时候,渲染的是wxTest/index.js的代码
#import "WXViewController.h"
#import <WeexSDK/WXSDKInstance.h>
#import <WeexSDK/WXSDKEngine.h>
#import <WeexSDK/WXUtility.h>
#import <WeexSDK/WXDebugTool.h>
#import <WeexSDK/WXSDKManager.h>
#import "UIViewController+WXDemoNaviBar.h"
#import "WXPrerenderManager.h"
#import "WXMonitor.h"
#import "WXTracingManager.h"
#import "LJWKWebView.h"
#import "LJWKWebViewUtils.h"
#define kNavAndStatuesHeight 64
#define kUseWeexFlag @"lj_weexurl"
@interface WXViewController ()
@property (nonatomic, strong) WXSDKInstance *instance;
@property (nonatomic, strong) UIView *weexView;
@property (nonatomic, assign) BOOL isUseWeexRender; //是否使用weex渲染
@property (nonatomic, strong) LJWKWebView *webView;
@end
@implementation WXViewController
#pragma mark -- dealloc
- (void)dealloc
{
[_instance destroyInstance];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (instancetype)init
{
self = [super init];
if (self) {
NSAssert(NO, @"请使用initWithUrl初始化");
}
return self;
}
- (instancetype)initWithUrl:(NSURL *)url useWeexEnv:(BOOL)useWeexEnv
{
self = [super init];
if (self) {
_url = url;
_isUseWeexRender = useWeexEnv && ([url.absoluteString rangeOfString:kUseWeexFlag].location != NSNotFound);
}
return self;
}
#pragma mark -- life cycle
- (void)viewDidLoad
{
[super viewDidLoad];
// [self setTopNavBarTitle:@"Weex Container"];
[self setGrayTopBarBg];
if (_isUseWeexRender) {
[self.view setClipsToBounds:YES];
[self renderWeex];
}else{
[self setDeafaultTopBarBg];
[self setTopNavBackButton];
[self setTopNavBarTitle:@"加载中..."];
[self loadWebViewWithUrl:self.url.absoluteString];
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (_isUseWeexRender) {
[self updateInstanceState:WeexInstanceAppear];
}
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if (_isUseWeexRender) {
[self updateInstanceState:WeexInstanceDisappear];
}
}
appdelegate代码
#import "AppDelegate.h"
#import "WXViewController.h"
#import "UIViewController+WXDemoNaviBar.h"
#import "WXLJCustomeEventModule.h"
#import "WXImgLoaderDefaultImpl.h"
#import "WXScannerVC.h"
#import "UIView+UIThreadCheck.h"
#import <WeexSDK/WeexSDK.h>
#import <AVFoundation/AVFoundation.h>
#import <ATSDK/ATManager.h>
#import "WXNavigationHandlerImpl.h"
#import "ViewController.h"
//#import "WXAnalyzerCenter.h"
#ifdef DEBUG
#import "DebugAnalyzer.h"
#endif
@interface AppDelegate ()
@end
@implementation AppDelegate
#pragma mark
#pragma mark application
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
[self initWeexSDK];
ViewController *vc = [[ViewController alloc]init];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:vc];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
[self startSplashScreen];
#if DEBUG
// check if there are any UI changes on main thread.
[UIView wx_checkUIThread];
#endif
return YES;
}
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
{
if ([shortcutItem.type isEqualToString:QRSCAN]) {
WXScannerVC * scanViewController = [[WXScannerVC alloc] init];
[(WXRootViewController*)self.window.rootViewController pushViewController:scanViewController animated:YES];
}
if ([shortcutItem.type isEqualToString:QRSCAN_HISTORY]) {
// WXScannerHistoryVC *scannerHistoryVC = [WXScannerHistoryVC new];
// [(WXRootViewController*)self.window.rootViewController pushViewController:scannerHistoryVC animated:YES];
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
#ifdef UITEST
#if !TARGET_IPHONE_SIMULATOR
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
setenv("GCOV_PREFIX", [documentsDirectory cStringUsingEncoding:NSUTF8StringEncoding], 1);
setenv("GCOV_PREFIX_STRIP", "6", 1);
#endif
extern void __gcov_flush(void);
__gcov_flush();
#endif
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
NSString *newUrlStr = url.absoluteString;
if([url.scheme isEqualToString:@"wxpage"]) {
newUrlStr = [newUrlStr stringByReplacingOccurrencesOfString:@"wxpage://" withString:@"http://"];
}
UIViewController * viewController = [self demoController:newUrlStr];
// ((WXViewController*)viewController).url = [NSURL URLWithString:newUrlStr];
[(WXRootViewController*)self.window.rootViewController pushViewController:viewController animated:YES];
return YES;
}
#pragma mark weex
- (void)initWeexSDK
{
[WXAppConfiguration setAppGroup:@"AliApp"];
[WXAppConfiguration setAppName:@"WeexDemo"];
[WXAppConfiguration setExternalUserAgent:@"ExternalUA"];
[WXSDKEngine initSDKEnvironment];
[WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];
[WXSDKEngine registerHandler:[WXNavigationHandlerImpl new] withProtocol:@protocol(WXNavigationProtocol)];
// 注册自定义的JS回调原生方法的事件方法
[WXSDKEngine registerHandler:[WXLJCustomeEventModule new] withProtocol:@protocol(WXModuleProtocol)];
[WXSDKEngine registerModule:@"actionBridge" withClass:[WXLJCustomeEventModule class]];
// 注册自定义的JS回调原生方法的事件方法
#ifdef DEBUG
[WXAnalyzerCenter addWxAnalyzer:[DebugAnalyzer new]];
#endif
#if !(TARGET_IPHONE_SIMULATOR)
[self checkUpdate];
#endif
#ifdef DEBUG
[self atAddPlugin];
[WXDebugTool setDebug:YES];
[WXLog setLogLevel:WXLogLevelLog];
#ifndef UITEST
[[ATManager shareInstance] show];
#endif
#else
[WXDebugTool setDebug:NO];
[WXLog setLogLevel:WXLogLevelError];
#endif
}
- (UIViewController *)demoController:(NSString*)url
{
// NSString *url = @"http://10.50.62.53:9999/wxTest/index.js";
// NSString *url = @"http://10.50.62.53:9999/wxTableview/index.js";
// NSString *url = @"https://www.baidu.com/";
UIViewController *demo = [[WXViewController alloc] initWithUrl:[NSURL URLWithString:url] useWeexEnv:YES];
return demo;
}
#pragma mark
#pragma mark animation when startup
- (void)startSplashScreen
{
UIView* splashView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
splashView.backgroundColor = WEEX_COLOR;
UIImageView *iconImageView = [UIImageView new];
UIImage *icon = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"weex-icon" ofType:@"png"]];
if ([icon respondsToSelector:@selector(imageWithRenderingMode:)]) {
iconImageView.image = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
iconImageView.tintColor = [UIColor whiteColor];
} else {
iconImageView.image = icon;
}
iconImageView.frame = CGRectMake(0, 0, 320, 320);
iconImageView.contentMode = UIViewContentModeScaleAspectFit;
iconImageView.center = splashView.center;
[splashView addSubview:iconImageView];
[self.window addSubview:splashView];
float animationDuration = 1.4;
CGFloat shrinkDuration = animationDuration * 0.3;
CGFloat growDuration = animationDuration * 0.7;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
[UIView animateWithDuration:shrinkDuration delay:1.0 usingSpringWithDamping:0.7f initialSpringVelocity:10 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(0.75, 0.75);
iconImageView.transform = scaleTransform;
} completion:^(BOOL finished) {
[UIView animateWithDuration:growDuration animations:^{
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(20, 20);
iconImageView.transform = scaleTransform;
splashView.alpha = 0;
} completion:^(BOOL finished) {
[splashView removeFromSuperview];
}];
}];
} else {
[UIView animateWithDuration:shrinkDuration delay:1.0 options:0 animations:^{
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(0.75, 0.75);
iconImageView.transform = scaleTransform;
} completion:^(BOOL finished) {
[UIView animateWithDuration:growDuration animations:^{
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(20, 20);
iconImageView.transform = scaleTransform;
splashView.alpha = 0;
} completion:^(BOOL finished) {
[splashView removeFromSuperview];
}];
}];
}
}
#pragma mark
- (void)atAddPlugin {
#if DEBUG
[[ATManager shareInstance] addPluginWithId:@"weex" andName:@"weex" andIconName:@"../weex" andEntry:@"" andArgs:@[@""]];
[[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"logger" andName:@"logger" andIconName:@"log" andEntry:@"WXATLoggerPlugin" andArgs:@[@""]];
// [[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"viewHierarchy" andName:@"hierarchy" andIconName:@"log" andEntry:@"WXATViewHierarchyPlugin" andArgs:@[@""]];
[[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"test2" andName:@"test" andIconName:@"at_arr_refresh" andEntry:@"" andArgs:@[]];
[[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"test3" andName:@"test" andIconName:@"at_arr_refresh" andEntry:@"" andArgs:@[]];
#endif
}
- (void)checkUpdate {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
NSString *currentVersion = [infoDic objectForKey:@"CFBundleShortVersionString"];
NSString *URL = @"http://itunes.apple.com/lookup?id=1130862662";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:URL]];
[request setHTTPMethod:@"POST"];
NSHTTPURLResponse *urlResponse = nil;
NSError *error = nil;
NSData *recervedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString *results = [[NSString alloc] initWithBytes:[recervedData bytes] length:[recervedData length] encoding:NSUTF8StringEncoding];
NSDictionary *dic = [WXUtility objectFromJSON:results];
NSArray *infoArray = [dic objectForKey:@"results"];
if ([infoArray count]) {
NSDictionary *releaseInfo = [infoArray objectAtIndex:0];
weakSelf.latestVer = [releaseInfo objectForKey:@"version"];
if ([weakSelf.latestVer floatValue] > [currentVersion floatValue]) {
if (![[NSUserDefaults standardUserDefaults] boolForKey: weakSelf.latestVer]) {
[[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:weakSelf.latestVer];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New Version" message:@"Will update to a new version" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"update", nil];
[alert show];
});
}
}
}
});
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0:
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:self.latestVer];
break;
case 1:
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/cn/app/weex-playground/id1130862662?mt=8"]];
default:
break;
}
[alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
}
@end
自定义的weex组件-------具体跟js交互的文件
#import "WXLJCustomeEventModule.h"
#import <WeexSDK/WeexSDK.h>
#import "WXViewController.h"
#import "HomeViewController.h"
@interface WXLJCustomeEventModule()
@property (nonatomic, copy) WXModuleKeepAliveCallback loginSuccessCallBack;
@end
@implementation WXLJCustomeEventModule
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(openUrl:callback:))
WX_EXPORT_METHOD(@selector(close:callback:))
WX_EXPORT_METHOD(@selector(setNavBarTitle:callback:))
- (void)openUrl:(id)paramsJSON callback:(WXModuleKeepAliveCallback)callback
{
NSDictionary *paramsDic = [CHUtil dictionaryWithJsonString:paramsJSON];
// url: 'weex://go/ljDetail?orderId=123',
if (paramsDic) {
NSString *url = paramsDic[@"url"];
NSDictionary *queryDic = [CHUtil getParamsDicWithUrl: url];
if ([url hasPrefix:@"http"]) {
WXViewController *vc = [[WXViewController alloc] initWithUrl:[NSURL URLWithString:url] useWeexEnv:YES];
[[weexInstance.viewController navigationController] pushViewController:vc animated:YES];
} else if ([url hasPrefix:@"weex"] && [url rangeOfString:@"ljDetail"].location != NSNotFound){
HomeViewController *vc = [HomeViewController new ];
vc.orderId = queryDic[@"orderId"];
[[weexInstance.viewController navigationController] pushViewController:vc animated:YES];
NSLog(@"url:%@", url);
return;
}
}
}
- (void)close:(id)paramsJSON callback:(WXModuleKeepAliveCallback)callback
{
[weexInstance.viewController.navigationController popViewControllerAnimated:YES];
if (callback) {
callback(@"", NO);
}
}