本文将介绍小程序的核心视图层逻辑层分离架构,并通过 iOS 的代码来模拟这种双线程模型。
小程序是一种新的移动应用程序格式,是一种依赖 Web 技术,但也集成了原生应用程序功能的混合解决方案。
目前市面上小程序平台微信、支付宝、百度、头条、京东、凡泰等;小程序一些特性有助于填补 Web 和原生平台之间的鸿沟,因此小程序受到了一些超级应用程序的欢迎。
1、分离视图层与逻辑层
在小程序中,视图层通常与逻辑层分离。
视图层和逻辑层分离有很多好处:
先看一下运行结果
接下来我们将用 iOS 代码来模拟上述的双线程模型。首先我们来实现视图层与逻辑层的数据通讯
如上图所示,视图层与逻辑层都分别通过 JS Bridge 的 publish 和 subscribe 来实现数据的收发。
1、视图层调用JSBridge.publish把事件传递给原生;参数: {eventName: ‘’, data: {}}
//点击按钮,通知JS执行业务逻辑
function onTest() {
console.log('aaa')
FinChatJSBridge.subscribe('PAGE_EVENT', function (params) {
document.getElementById('testId').innerHTML = params.data.title })
FinChatJSBridge.publish('PAGE_EVENT', {
eventName: 'onTest',data: {}
})
}
2、原生 view 层收到 page 的事件,把事件传递转发给 service 层处理
if ([message.name isEqualToString:@"publishHandler"]) {
NSString *e = message.body[@"event"];
[self.service callSubscribeHandlerWithEvent:e param:message.body[@"paramsString"]];
}
3、原生 service 层收到原生 view 层的事件,通过 jsbridge 把事件及参数传递给视图 ervice 层执行 js 逻辑
NSString *js = [NSString stringWithFormat:@"ServiceJSBridge.subscribeHandler('%@',%@)",eventName,jsonParam];
[self evaluateJavaScript:js completionHandler:nil];
4、视图 service,收到事件后,执行 JS 业务代码
var Page = {
setData: function(data) {
//向原生视图层发送更新数据信息
ServiceJSBridge.publish('PAGE_EVENT', {
eventName: 'onPageDataChange',
data: data
})
},
methods: {
onTest: function() {
// 执行JS方法,模拟小程序的setData,把数据更新到视图层
Page.setData({
title: '我来自JS代码更新'
})
console.log('my on Test')
}
}
}
var onWebviewEvent = function(fn) {
ServiceJSBridge.subscribe('PAGE_EVENT', function(params) {
console.log('FinChatJSBridge.subscribe')
var data = params.data,
eventName = params.eventName
fn({
data: data,
eventName: eventName
})
})
}
var doWebviewEvent = function(pEvent, params) {
// do dom ready
if (Page.methods.hasOwnProperty(pEvent)) {
// 收到视图层的事件,执行JS对应的方法
Page.methods[pEvent].call(params)
}
}
5、执行业务 JS 代码后,把数据更新传递给视图层去更新 UI 界面展示数据
ServiceJSBridge.publish('PAGE_EVENT',{
eventName:'onPageDataChange',
data: data
})
6、原生 service 层收到视图 service 层的事件,把事件传递给原生视图层
if ([message.name isEqualToString:@"publishHandler"]) {
NSString *e = message.body[@"event"];
[self.controller callSubscribeHandlerWithEvent:e param:message.body[@"paramsString"]]; }
7、原生视图层把收到的事件,传递给视图 view 层
NSString *js = [NSString stringWithFormat:@"FinChatJSBridge.subscribeHandler('%@',%@)",eventName,jsonParam];
[self evaluateJavaScript:js completionHandler:nil];
8、视图 view 层,收到事件后,更新界面
FinChatJSBridge.subscribe('PAGE_EVENT',function(params){
document.getElementById('testId').innerHTML = params.data.title
})
// 首先订阅数据回调
JSBridge.subscribe('PAGE_EVENT', function(params) {
// ... 这里对返回的数据进行处理
})
// 向JS Bridge发布数据
// eventName: 用于标识事件名
// data: 为传递的数据
JSBridge.publish('PAGE_EVENT', { eventName: 'onTest', data: {} })
WKUserContentController *userContentController = [WKUserContentController new];
NSString *souce = @"window.__fcjs_environment='miniprogram'";
WKUserScript *script = [[WKUserScript alloc] initWithSource:souce injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:true];
[userContentController addUserScript:script];
[userContentController addScriptMessageHandler:self name:@"publishHandler"];
WKWebViewConfiguration *wkWebViewConfiguration = [WKWebViewConfiguration new];
wkWebViewConfiguration.allowsInlineMediaPlayback = YES;
wkWebViewConfiguration.userContentController = userContentController;
if (@available(iOS 9.0, *)) {
[wkWebViewConfiguration.preferences setValue:@(true) forKey:@"allowFileAccessFromFileURLs"];
}
WKPreferences *preferences = [WKPreferences new];
preferences.javaScriptCanOpenWindowsAutomatically = YES;
wkWebViewConfiguration.preferences = preferences;
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:wkWebViewConfiguration];
self.webView.clipsToBounds = YES;
self.webView.allowsBackForwardNavigationGestures = YES;
[self.view addSubview:self.webView];
NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"view.html" ofType:nil];
NSURL *fileURL = [NSURL fileURLWithPath:urlStr];
[self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];
// 执行视图层事件回调
- (void)callSubscribeHandlerWithEvent:(NSString *)eventName param:(NSString *)jsonParam
{
NSString *js = [NSString stringWithFormat:@"FinChatJSBridge.subscribeHandler('%@',%@)",eventName,jsonParam];
[self evaluateJavaScript:js completionHandler:nil];
}
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void(^)(id result,NSError *error))completionHandle
{
[self.webView evaluateJavaScript:javaScriptString completionHandler:completionHandler];
}
#pragma mark - WKScriptMessageHandle
// 视图层JSBridge请求接收处理
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
if ([message.name isEqualToString:@"publishHandler"]) {
NSString *e = message.body[@"event"];
[self.service callSubscribeHandlerWithEvent:e param:message.body[@"paramsString"]];
}
}
function onTest() {
console.log('aaa')
FinChatJSBridge.subscribe('PAGE_EVENT', function(params) {
document.getElementById('testId').innerHTML = params.data.title
})
FinChatJSBridge.publish('PAGE_EVENT', {
eventName: 'onTest',
data: {}
})
}
<div id="testId">我来自视图层!</div>
<input type="button" value="调用JS逻辑层setData" style="border-radius:15px;background:#ed0c50;border: #EDD70C;color: white;font-size: 14px; width: 80%;" onclick="onTest();" />
// page 对像模拟
var Page = {
setData: function(data) {
ServiceJSBridge.publish('PAGE_EVENT', {
eventName: 'onPageDataChange',
data: data
})
},
methods: {
onTest: function() {
Page.setData({
title: '我来自JS代码更新'
})
console.log('my on Test')
}
}
}
var onWebviewEvent = function(fn) {
ServiceJSBridge.subscribe('PAGE_EVENT', function(params) {
var data = params.data,
eventName = params.eventName
fn({
data: data,
eventName: eventName
})
})
}
var doWebviewEvent = function(pEvent, params) {
// do dom ready
if (Page.methods.hasOwnProperty(pEvent)) {
Page.methods[pEvent].call(params)
}
}
onWebviewEvent(function(params) {
var eventName = params.eventName
var data = params.data
return doWebviewEvent(eventName, data)
})
文档中心: Document
本文示例代码: https://github.com/finogeeks/fino-applet
相关文章:凡泰极客私有云小程序技术
关于凡泰极客:帮助金融机构乃至任何希望拥有类似技术的其他行业机构,建立“碎片”的集散地、降低管理成本、提高研发效能,形成自己的数字化生态、与客户和伙伴建立真正的数字化连接。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。