赞
踩
本文将介绍 小程序的核心视图层逻辑层分离架构,并通过 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: {} })
- WKWebView 初始化
- 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)
- })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。