混合开发---ionic代码篇

作者: FMG | 来源:发表于2017-03-22 19:01 被阅读1380次

    这里着重说下,怎样真真切切的做混合开发,如果你还对是否采用ionic来开发web纠结,请看我上篇文章
    注:本文章适用于1.x 版本

    OK,言归正传,首先混合开发,就要明白你不是用ionic完成你项目中的所有模块,比如:你的boss说咱们有四大模块,分别为:A、B、C、D,A和C模块因为各种原因需要用原生来写,那么其他B和D,你来用web来写好了;对于这种情况,就可以说你是在混合开发了。

    作为混合开发,你要明白ionic到底是个什么鬼,实际他就是一个WebView(相对Android来说,在iOS那叫做UIWebView),在这个WebView中ionic会模拟原生的页面跳转,按钮点击,手势操作,不管他怎么炫,始终是 一个 WebView(相对原生来说)。那么现在的情况就是 A原生、BWebView、C原生、DWebView,你需要面临的主要问题是怎样四个模块相互切换,了解原生的可能会说,这不是很好切换吗,不就是个WebView么,但是这里你要注意,控件的生命周期问题,A切B没问题,B切A,你就要保证在切到A的时候要把B销毁,特别是B切D的时候,因为一个项目中不允许有两个ionic同时共存,所以,该kill 的不要手软。

    咱们顺着思路往下走,既然刚才说了,一个项目中不能同时存在两个ionic,那就把两个模块的代码写到一个ionic中,每次打开ionic的时候让他动态选择要加载哪个模块,对ionic已经熟悉点的都知道,加载哪个模块是靠 路由 来决定的,而路由也是写死的,默认会加载.config函数中$urlRouterProvider服务的otherwise方法指定的模板

    var templateName = 'login';
     $urlRouterProvider.otherwise(templateName);
    

    所以这里就要想办法去动态改变templateName的值,在这里可以通过桥接,在加载ionic的时候原生给ionic传递一个想要加载的模块名称,以iOS为例:

    ** 原生代码 **:

    我使用的是javaScriptCore,作为原生与web之间的交互
    
    先实现UIWebView代理<UIWebViewDelegate>
    
    // 实现代理方法
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
        
        JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        FMGIonicBridge *bridge = [[FMGIonicBridge alloc] init];
        
        __weak typeof(self)weakSelf = self;
        bridge.message = @{ // 在这里你可以传给ionic一些参数
                           @"BBBB": @"bb",
                           @"AAAA":@"aa",
                           @"XXX":@"x"};
        bridge.templateName = @"login"; // 这个就是我前面提到我告诉ionic我要加载哪个模块,
    
        // ionic调用原生的侧边栏
        bridge.back = ^(NSString *info) {
            // 我们项目中有侧边栏,所以写个这个方法,只使用底部切换模块的,请忽略。。。
            weakSelf.showSlideMenu();
        };
        bridge.webDidFinishedLoad = ^{ // 在这里你可以在ionic加载完成的时候做一些操作,
            weakSelf.hideNavigation(YES); //  比如隐藏原生的导航条
            weakSelf.view.alpha = 1;  // 解决加载ionic时的白屏问题
        };
        context[@"myNative"] = bridge;  // myNative 要跟ionic中保持统一
    }
    
    

    ** ionic 代码 **:

    // willShowTemplateName是桥接的一个方法,获取原生想要加载哪个模块
    var templateName = myNative.willShowTemplateName(); 
    
     $urlRouterProvider.otherwise(templateName);
    app.js 配置代码
    define([
        'controllers/controllers',
      ],
    
      function () {
        'use strict';
    // Ionic Starter App
    // 'starter.controllers' is found in controllers.js
        var app = angular.module('starter', ['ionic','ngCordova', 'starter.controllers'])
    
        app.run(function($ionicPlatform) {
          $ionicPlatform.ready(function() {
            // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
            // for form inputs)
            if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
              cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
              cordova.plugins.Keyboard.disableScroll(true);
            }
            if (window.StatusBar) {
              // org.apache.cordova.statusbar required
              StatusBar.styleDefault();
            }
          });
        })
     .config(function ($stateProvider, $urlRouterProvider, $controllerProvider,$httpProvider,$ionicConfigProvider) {
            app.registerController = $controllerProvider.register;
            app.loadControllerJs = function (controllerJs) {
              return function ($rootScope, $q) {
                var def = $q.defer(), deps = [];
                angular.isArray(controllerJs) ? (deps = controllerJs) : deps.push(controllerJs);
                require(deps, function () {
                  $rootScope.$apply(function () {
                    def.resolve();
                  });
                });
                return def.promise;
              };
            }
    //------以上部分是为了做异步加载控制器用,不采用一个.js文件将所有的js操作加载,这样可以提升加载速度-------
            //$httpProvider.defaults.headers.common = {"Access-Control-Allow-Origin":"*"}
            $ionicConfigProvider.backButton.previousTitleText(false);
            $ionicConfigProvider.backButton.text("");
    
    //------以上部分是为了设置导航条只是返回箭头,没有文字-------
    
    /******* 顺便提下这里是纯ionic 开发整套app代码
            //if none of the above states are matched, use this as the fallback
            //var templateName = myObj.willShowTemplateName();
            var originInfo = window.localStorage.getItem('userInfo');
            console.log('&&&&&&'+originInfo)
            if(originInfo == 'undefined' || originInfo == null ) {
              console.log('登录');
              var templateName = 'login';
            } else { //控制跳转
              console.log('现实' + window.localStorage.getItem('userInfo'));
              var userInfo = window.JSON.parse(window.localStorage.getItem('userInfo'))
              var templateName = 'actuality';
            }
            $urlRouterProvider.otherwise(templateName);
    *******/
    
          // willShowTemplateName是桥接的一个方法,获取原生想要加载哪个模块(混合开发必备)
          var templateName = myNative.willShowTemplateName(); 
          $urlRouterProvider.otherwise(templateName);
    
            // Ionic uses AngularUI Router which uses the concept of states
            $stateProvider
              //*************************************** 登录注册***************************************//
              // 登录
              .state('login', {
                url: '/login',
                templateUrl: 'templates/loginAndRegister/login.html',
                controller: 'loginCtrl',
                resolve : {
                  deps: app.loadControllerJs('./controllers/loginAndRegister/login')
                }
              })
              .state('xxxx', { // 模仿登录写就OK了
                url: '/xxx',
                templateUrl: 'xxx',
                controller: 'xxxx',
                resolve : {
                  deps: app.loadControllerJs('./xxxxxx')
                }
              })
          });
    

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
        <title></title>
    
        <link rel="manifest" href="manifest.json">
    
      
        <link href="lib/ionic/css/ionic.css" rel="stylesheet">
        <link href="css/style.css" rel="stylesheet">
    
        <script src="lib/ionic/js/ionic.bundle.js"></script>
    
        <!-- cordova script (this will be a 404 during development) -->
        //引入ngCordova库
        <script src="lib/ngCordova/dist/ng-cordova.min.js"></script>
        <script src="cordova.js"></script>
    
        //环境配置,也叫启动文件
        <script data-main="js/require-config.js" src="lib/requirejs/require.js"> </script>
    
        // 自定义全局变量文件
        <script src="js/common.js"></script>
    
      </head>
      <body>
    
      <ion-nav-bar class="bar-stable">
        <ion-nav-back-button>
        </ion-nav-back-button>
      </ion-nav-bar>
      <ion-nav-view></ion-nav-view>
    
      </body>
    </html>
    
    

    require-config.js

    require.config({
      baseUrl:'js',
      paths: {
      },
      deps: [
        'bootstrap'
      ]
    });
    

    controllers.js

    define(function (require) {
      'use strict';
      var services = require('services/services');  // 不需要自定义服务的可以忽略
      var controllers = angular.module('starter.controllers', []);
      return controllers;
    });
    

    bootstraps.js

    define(['app'], function (app) {
      'use strict';
    
      angular.element(document.getElementsByTagName('html')[0]).ready(function(){
        var width = document.documentElement.clientWidth;
        // 这里可以设置字体动态化,使用rem,下面只是个例子具体怎么动态化,请观看其他文章
        //document.documentElement.style.fontSize = window.innerWidth/3.75 + 'px';
        try {
          angular.bootstrap(document, ['starter']);
        } catch (e) {
          console.error(e.stack || e.message || e);
        }
      });
    
    });
    
    项目结构.png

    先到这吧,有不清楚的请留言!祝君工作愉快!

    相关文章

      网友评论

        本文标题:混合开发---ionic代码篇

        本文链接:https://www.haomeiwen.com/subject/iwcjvttx.html