动态页面生成

编写页面的dart代码如下:

import 'package:fair/fair.dart';
import 'package:fairdemo/plugins/screen_util.dart';
import 'package:flutter/material.dart';
@FairPatch()
class Test2 extends StatefulWidget {
  @override
  State<Test2> createState() => _Test2State();
}
class _Test2State extends State<Test2> {
  String getHeight(double height) {
    return '${height + 100}';
  }
  @override
  Widget build(BuildContext context) {
    return Text(getHeight(100));
  }
}

经过fair compiler编译生成逻辑js文件和json文件:
页面json文件:

{
  "className": "Text",
  "pa": [
    "%(getHeight(100))"
  ],
  "methodMap": {},
  "digest": "fc6dd47c7b54434b70b954c981085540"
}

逻辑js文件:

GLOBAL['#FairKey#'] = (function(__initProps__) {
    const __global__ = this;
    return runCallback(function(__mod__) {
        with(__mod__.imports) {
            function _Test2State() {
                const inner = _Test2State.__inner__;
                if (this == __global__) {
                    return new _Test2State({
                        __args__: arguments
                    });
                } else {
                    const args = arguments.length > 0 ? arguments[0].__args__ || arguments : [];
                    inner.apply(this, args);
                    _Test2State.prototype.ctor.apply(this, args);
                    return this;
                }
            }
            _Test2State.__inner__ = function inner() {};
            _Test2State.prototype = {
                getHeight: function getHeight(height) {
                    const __thiz__ = this;
                    const __arg_ctx__ = {
                        height,
                    };
                    with(__thiz__) {
                        with(__arg_ctx__) {
                            return `${height + 100}`;
                        }
                    }
                },
            };
            _Test2State.prototype.ctor = function() {};;
            return _Test2State();
        }
    }, []);
})(convertObjectLiteralToSetOrMap(JSON.parse('#FairProps#')));

动态页面还原成dart页面渲染进程

经过FairWidget加载:

FairWidget(
  name: "test1",
  path: 'assets/fair/lib_fair_test_test2.fair.json',
)

解析第一步:
经过toWidget办法将json文件还原成widget

var widget = _convert(context, layout!, methodMap, data: data);

这一步layout数据便是json格局页面数据

经过遍历map

{
  "className": "Text",
  "pa": [
    "%(getHeight(100))"
  ],
  "methodMap": {},
  "digest": "fc6dd47c7b54434b70b954c981085540"
}

tag值是className

var name = map[tag];

1、先在module中匹配

var module = bound?.modules?.moduleOf(name)?.call();

这个module的界说能够在FairApp初始化中装备

FairApp(
      generated: AppGeneratedModule(),
      modules: {},
      delegate: { 
      },
      child: MyApp(),
    );

2、在办法和变量中匹配

mapper = bound?.functionOf(name) ?? bound?.valueOf(name);

这个bound经过FairApp获取,先获取FairApp,

var app = FairApp.of(context);
var bound = app?.bindData[page];

FairApp.of(context)这个办法是从 context 中 findAncestorWidgetOfExactType经过widget 树结构查找。

static FairApp? of(BuildContext? context, {bool rebuild = false}) {
 return rebuild ? context?.dependOnInheritedWidgetOfExactType<FairApp>() : context?.findAncestorWidgetOfExactType<FairApp>();
}

咱们在main中经过FairApp在最外层包裹页面。
所以这儿对应app目标便是从main中初始化的FairApp

FairApp(
     generated: AppGeneratedModule(),
     modules: {},
     delegate: {
     },
     child: MyApp(),
   );

FairApp继承自 AppState

class FairApp extends InheritedWidget with AppState 

bindData是AppState界说的特点,经过其register办法绑定

Future<dynamic> register(FairState state)

注册页面 的

    bindData.putIfAbsent(
      state.state2key,
      () => BindingData(
        modules,
        functions: delegate.bindFunction(),
        values: delegate.bindValue(),
      ),
    );

这儿key名便是 页面姓名,即对应

FairWidget(
  name: "test1",
  path: 'assets/fair/lib_fair_test_test2.fair.json',
)

这个name 进行核算得到:

state2key = GlobalState.id(widget.name);

经过_counter大局的变量标识,防止同一个可能会运用多次而导致数据混用问题:

static String id(String? prefix) {
  return '$prefix#${GlobalState._counter++}';
}

因此回到上面盯梢的进程:

mapper = bound?.functionOf(name) ?? bound?.valueOf(name);

这个办法便是在 delegate.bindFunction(), 和delegate.bindValue(),办法在FairApp创建时分经过传入的delegate完成的:

 FairApp(
      generated: AppGeneratedModule(),
      modules: {},
      delegate: {
        ///界说办法和变量映射表
      },
      child: MyApp(),
    );

3,在mapper = proxyMirror?.componentOf(name);中查找

mapper = proxyMirror?.componentOf(name);
ProxyMirror 这个便是一个大map 叫做_provider目标办理,存放 字符串到dart办法的映射联系。

class ProxyMirror with P {
  final _provider = BindingProvider();
}

分为3大部分:

首先是fair_version下面的,这是flutter framework 系统widget和办法的对应联系

BindingProvider 混入$BindingImpl类

class BindingProvider with $BindingImpl

$BindingImpl界说如下

  import '\$\$c.dart' as $0;
import '\$\$w.dart' as $1;
import '\$\$p.dart' as $2;
import '\$\$m.dart' as $3;
import '\$\$r.dart' as $4;
import '\$\$a.dart' as $5;
  mixin $BindingImpl {
    final provider = [
$0.p,
$1.p,
$2.p,
$3.p,
$4.p,
$5.p,
];}

一些特别映射表:

specialBinding =
    SplayTreeMap.from({
  ...common.provider(),
  ...geometry.provider(),
  ...flow.provider(),
});

对应的是geometry.dart
common.dart
flow.dart 这3个文件中界说的映射联系,比方FairWidget Color等这些目标的映射对照表:

{
    'FairWidget': (props) => FairWidget(
          name: props['name'],
          path: props['path'],
          data: props['data'],
        ),
    'Color': (props) {
      var color = pa0(props);
      return color is String ? FairUtils.fromHex(color) : Color(color);
    },

最终一部分便是GeneratedModule经过@FairBindging注解生成的第三方包中的办法和widget

  void addGeneratedBinding(GeneratedModule? generated) {
    if (generated == null) {
      return;
    }
    _generatedMapping.addAll(generated.mapping());
    _provider.binding.addAll(generated.components());
  }

经过_proxy.addGeneratedBinding(generated);办法添加。

GeneratedModule

FairApp(
  generated: AppGeneratedModule(),
  modules: {},
  delegate: {
  },
  child: MyApp(),
)

AppGeneratedModule是一个经过@FairBinding经过fair compiler工具自动化生成的代码

class AppGeneratedModule extends GeneratedModule 

GeneratedModule 类对应的便是需要供给办法:

abstract class GeneratedModule {
  Map<String, dynamic> components();
  Map<String, bool> mapping();
}

也是一个map

归纳上面3个大map

就完成了 proxyMirror?.componentOf(name);这个组件的查找的逻辑。

在大map中找到匹配联系

调用return block(map, methodMap, context, domain, mapper, name, isWidget);办法。

这个mapper目标则为fun ,便是 json 页面中name为key从大map找到的对应的完成,是一个办法或者是一个widget构造目标,这就完成了从json string name到widget的映射查找联系。

dynamic block(
  Map map,
  Map? methodMap,
  BuildContext ctx,
  Domain? domain,
  dynamic fun,
  String name,
  bool widget, {
  bool forceApply = false,
}) 

经过named办法递归遍历json结构 并且回来当前层的context即dart三棵树的Element数BuildContext目标,经过positioned办法提取参数

var na = named(name, map['na'], methodMap, ctx, domain);
var pa = positioned(map['pa'], methodMap, ctx, domain);

看下之前转化的json 这个是一层,

{
  "className": "Text",
  "pa": [
    "%(getHeight(100))"
  ],
  "methodMap": {},
  "digest": "fc6dd47c7b54434b70b954c981085540"
}

这个是多层widget嵌套样子:

{
  "className": "Scaffold",
  "na": {
    "appBar": {
      "className": "AppBar",
      "na": {
        "title": {
          "className": "Text",
          "pa": [
            "测验2131"
          ],
          "na": {
            "style": {
              "className": "TextStyle",
              "na": {
                "color": "#(Colors.black)",
                "fontSize": 20
              }
            }
          }
        }
      }
    }}

named办法递归遍历完成如下:经过 json中na往下遍历

W<Map<String, dynamic>> named(
    String tag,
    dynamic naMap,
    Map? methodMap,
    BuildContext context,
    Domain? domain,
  ) {
    var na = <String, dynamic>{};
    var needBinding = false;
    if (naMap is Map) {
      naMap.entries.forEach((e) {
        if (e.value is Map) {
          na[e.key] = namedMap(tag, naMap, methodMap, context, domain, e);
        } else if (e.value is List) {
          na[e.key] =
              namedList(tag, naMap, methodMap, context, domain, e.value);
        } else if (domain != null && domain.match(e)) {
          na[e.key] = domain.bindValue(e as String);
        } else if (domain != null && e is MapEntry && domain.match(e.value)) {
          na[e.key] = domain.bindValue(e.value);
        } else if (e.value is String) {
          var w = namedString(tag, naMap, methodMap, context, domain, e.value);
          needBinding = w.binding ?? false;
          na[e.key] = w.data;
        } else {
          na[e.key] = e.value;
        }
      });
    }
    na['\$'] = context;
    return W<Map<String, dynamic>>(na, needBinding);
  }

经过positioned办法进行参数解析

var r = proxyMirror?.evaluate(context, bound, e, domain: domain);

有8种Expression正则表达式匹配,用来解析字符串对应提取特点值。是办法还是变量的调用。

abstract class Expression {
  R onEvaluate(
      ProxyMirror? proxy, BindingData? binding, Domain? domain, String? exp, String? pre);
  /// fail-fast
  bool hitTest(String? exp, String? pre);
}

这儿从源码中全部找出来如下:

final List<Expression> _expressions = [
  ComponentExpression(),
  InlineExpression(),
  InlineObjectExpression(),
  WidgetParamExpression(),
  FunctionExpression(),
  GestureExpression(),
  PropValueExpression(),
  ValueExpression(),
];

ValueExpression匹配放到最终,一切无法匹配的当作变量。

ComponentExpression:
return RegExp('#\\(.+\\)', multiLine: true).hasMatch(exp ?? '');
InlineExpression:
return RegExp(r'\$\w+', multiLine: true).hasMatch(pre ?? '');
InlineObjectExpression:
return RegExp(r'\$\{\w.+\}', multiLine: true).hasMatch(pre ?? '');
WidgetParamExpression:
return RegExp('#\\(widget\..+\\)', multiLine: true).hasMatch(exp ?? '');
FunctionExpression:
return RegExp(r'\%\(.+\)', multiLine: false).hasMatch(exp ?? '');
GestureExpression:
return RegExp(r'\@\(.+\)', multiLine: false).hasMatch(exp ?? '');
PropValueExpression:
return RegExp(r'\^\(\w+\)', multiLine: false).hasMatch(exp ?? '');

所以回到本次比如中json格局:

{
  "className": "Text",
  "pa": [
    "%(getHeight(100))"
  ],
  "methodMap": {},
  "digest": "fc6dd47c7b54434b70b954c981085540"
}

%(getHeight(100)) 这个匹配的是FunctionExpression对应为一个函数办法的调用

分别会提取 getHeight 和 参数 100

完整的postion办法完成如下:

  W<List> positioned(
      dynamic paMap, Map? methodMap, BuildContext context, Domain? domain) {
    var pa = [];
    var needBinding = false;
    if (paMap is List) {
      paMap.forEach((e) {
        if (e is Map) {
          pa.add(convert(context, e, methodMap, domain: domain));
        } else if (domain != null && domain.match(e)) {
          pa.add(domain.bindValue(e));
        } else if (domain != null && e is MapEntry && domain.match(e.value)) {
          pa.add(domain.bindValue(e.value));
        } else if (e is String) {
          var r = proxyMirror?.evaluate(context, bound, e, domain: domain);
          if (r?.binding == true) {
            needBinding = true;
          }
          pa.add(r?.data);
        } else {
          pa.add(e);
        }
      });
    }
    return W<List>(pa, needBinding);
  }

注意到这儿有一个匹配methodMap办法。

重新创建一个稍微杂乱的运用情况:

import 'package:fair/fair.dart';
import 'package:fairdemo/plugins/custom_method.dart';
import 'package:fairdemo/plugins/custom_method2.dart';
import 'package:flutter/material.dart';
@FairPatch()
class Test2 extends StatefulWidget {
  @override
  State<Test2> createState() => _Test2State();
}
class _Test2State extends State<Test2> {
  String getHeight(double height) {
    return '${height + 100}';
  }
  String getHeight2(double height) {
    return CustomMethod.getString('$height');
  }
  String getHeight3() {
    return CustomMethod.getString('123123');
  }
  String getHeight4() {
    getHeight2(23);
    getHeight3();
    CustomMethod2.getString2('123123');
    return CustomMethod.getString('123123');
  }
  String getHeight5() {
    getHeight2(23);
    getHeight3();
    CustomMethod.getString('123123');
    return CustomMethod2.getString2('123123');
  }
  String getHeight6() {
    getHeight2(23);
    getHeight3();
    return CustomMethod2.getString2('123123') +
        CustomMethod.getString('123123');
  }
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(getHeight(100)),
        Text(getHeight2(100)),
        Text(getHeight3()),
        Text(getHeight4()),
        Text(getHeight5()),
        Text(getHeight6()),
      ],
    );
  }
}

js文件如下:

GLOBAL['#FairKey#'] = (function(__initProps__) {
    const __global__ = this;
    return runCallback(function(__mod__) {
        with(__mod__.imports) {
            function _Test2State() {
                const inner = _Test2State.__inner__;
                if (this == __global__) {
                    return new _Test2State({
                        __args__: arguments
                    });
                } else {
                    const args = arguments.length > 0 ? arguments[0].__args__ || arguments : [];
                    inner.apply(this, args);
                    _Test2State.prototype.ctor.apply(this, args);
                    return this;
                }
            }
            _Test2State.__inner__ = function inner() {};
            _Test2State.prototype = {
                getHeight: function getHeight(height) {
                    const __thiz__ = this;
                    const __arg_ctx__ = {
                        height,
                    };
                    with(__thiz__) {
                        with(__arg_ctx__) {
                            return `${height + 100}`;
                        }
                    }
                },
                getHeight2: function getHeight2(height) {
                    const __thiz__ = this;
                    const __arg_ctx__ = {
                        height,
                    };
                    with(__thiz__) {
                        with(__arg_ctx__) {
                            return CustomMethod.getString(`${height}`);
                        }
                    }
                },
                getHeight3: function getHeight3() {
                    const __thiz__ = this;
                    with(__thiz__) {
                        return CustomMethod.getString('123123');
                    }
                },
                getHeight4: function getHeight4() {
                    const __thiz__ = this;
                    with(__thiz__) {
                        getHeight2(23);
                        getHeight3();
                        CustomMethod2.getString2('123123');
                        return CustomMethod.getString('123123');
                    }
                },
                getHeight5: function getHeight5() {
                    const __thiz__ = this;
                    with(__thiz__) {
                        getHeight2(23);
                        getHeight3();
                        CustomMethod.getString('123123');
                        return CustomMethod2.getString2('123123');
                    }
                },
                getHeight6: function getHeight6() {
                    const __thiz__ = this;
                    with(__thiz__) {
                        getHeight2(23);
                        getHeight3();
                        return CustomMethod2.getString2('123123') + CustomMethod.getString('123123');
                    }
                },
            };
            _Test2State.prototype.ctor = function() {};;
            return _Test2State();
        }
    }, []);
})(convertObjectLiteralToSetOrMap(JSON.parse('#FairProps#')));

json如下:

{
  "className": "Column",
  "na": {
    "children": [
      {
        "className": "Text",
        "pa": [
          "%(getHeight(100))"
        ]
      },
      {
        "className": "Text",
        "pa": [
          "%(getHeight2(100))"
        ]
      },
      {
        "className": "Text",
        "pa": [
          "%(getHeight3)"
        ]
      },
      {
        "className": "Text",
        "pa": [
          "%(getHeight4)"
        ]
      },
      {
        "className": "Text",
        "pa": [
          "%(getHeight5)"
        ]
      },
      {
        "className": "Text",
        "pa": [
          "%(getHeight6)"
        ]
      }
    ]
  },
  "methodMap": {
    "getHeight2": {
      "className": "CustomMethod.getString",
      "pa": [
        "#($height)"
      ]
    },
    "getHeight3": {
      "className": "CustomMethod.getString",
      "pa": [
        "123123"
      ]
    },
    "getHeight4": {
      "className": "CustomMethod.getString",
      "pa": [
        "123123"
      ]
    },
    "getHeight5": {
      "className": "CustomMethod2.getString2",
      "pa": [
        "123123"
      ]
    }
  },
  "digest": "40c9bc448860777c9ff7bd08912d877c"
}

getHeight2办法和getHeight3办法因为办法内部调用了其他办法,所以在methodMap则有一个界说。
这个methodMap生成规矩这儿不研究。

主要methodMap有和没有在解析进程中有什么区别

参数办法履行

dynamic get value {
  var extract;
  matches
      ?.map((e) => {
            '0': binding?.runFunctionOf(
                e.group(0)!.substring(2, e.group(0)!.length - 1), proxyMirror, binding, domain),
            '1': e.group(0)
          })
      .forEach((e) {
    var first = e['0'] is ValueNotifier ? e['0'].value : e['0'];
    if (first != null) {
      extract = first; // extract.replaceFirst(e['1'], '$first');
    } else {
      extract = data;
    }
  });
  return extract;
}

经过 binding?.runFunctionOf( e.group(0)!.substring(2, e.group(0)!.length - 1), proxyMirror, binding, domain)办法进行办法调用的解析

提取办法姓名和办法参数:

dynamic runFunctionOf(String funcName, ProxyMirror? proxyMirror,
    BindingData? bound, Domain? domain,
    {String? exp}) {
  if (_functions?[funcName] == null) {
    var result;
    if (RegExp(r'.+(.+)', multiLine: false).hasMatch(funcName)) { //提取办法姓名
      var rFuncName = funcName.substring(0, funcName.indexOf('('));
      var params = funcName.substring(//提取参数
          funcName.indexOf('(') + 1, funcName.lastIndexOf(')'));
      var args = params.split(',').map((e) {
        if (RegExp(r'^(index)', multiLine: false).hasMatch(e) &&
            domain is IndexDomain?) {
          return domain?.index;
        } else if (domain != null && domain.match(e)) {
          return domain.bindValue(e);
        } else {
          var r = proxyMirror?.evaluate(null, bound, e, domain: domain);
          if (r?.data == null) {
            return e;
          } else {
            return r?.data is ValueNotifier ? r?.data.value : r?.data;
          }
        }
      }).toList();
      //经过运行时 调用native通道履行js
      result = _functions?['runtimeInvokeMethodSync']?.call(rFuncName, args);
    } else {
        //经过运行时  调用native通道履行js
      result = _functions?['runtimeInvokeMethodSync']?.call(funcName);
    }
    try {
      var value = jsonDecode(result);//回来成果用json解析
      return value['result']['result'];//获取native js办法成果,回来的result字段则运算成果数据
    } catch (e) {
      throw RuntimeError(errorMsg: result);
    }
  } else {
    return _functions?[funcName]?.call();
  }
}

调用js办法:

{
    "pageName": "test1#3",
    "type": "method",
    "args":
    {
        "funcName": "getHeight",
        "args":
        [
            "100"
        ]
    }
}

js办法调用:

function _invokeMethod(par) {
    let pageName = par['pageName'];
    let funcName = par['args']['funcName'];
    let args = par['args']['args'];
    if ('getAllJSBindData' === funcName) {
        return getAllJSBindData(par);
    }
    if ('releaseJS' === funcName) {
        return _release(par);
    }
    let mClass = GLOBAL[pageName];
    let func = mClass[funcName];
    let methodResult;
    if (isNull(func)) {
        methodResult = '';
    } else {
        methodResult = func.apply(mClass, args);
    }
    let result = {
        pageName: pageName,
        result: {
            result: methodResult
        }
    };
    return JSON.stringify(result);
}

成果回调数据格局:

{
    "pageName": "test1#3",
    "result":
    {
        "result": "100100"
    }
}

这儿有一个问题,为什么result总是回来字符串类型的? 这样会导致在运用如果是需要double类型的当地,则会到界面转化失利。

double getHeight(double height) {
  return height;
}
//转化为js办法: %(getHeight(100))
{
  "className": "Column",
  "na": {
    "children": [
      {
        "className": "Container",
        "na": {
          "height": "%(getHeight(100))"
        }
      }
    ]
  },
  "methodMap": {},
  "digest": "4f6da55171a3ae0e9c8550464b7bf25e"
}
//js办法界说
GLOBAL['#FairKey#'] = (function(__initProps__) {
    const __global__ = this;
    return runCallback(function(__mod__) {
        with(__mod__.imports) {
            function _Test3State() {
                const inner = _Test3State.__inner__;
                if (this == __global__) {
                    return new _Test3State({
                        __args__: arguments
                    });
                } else {
                    const args = arguments.length > 0 ? arguments[0].__args__ || arguments : [];
                    inner.apply(this, args);
                    _Test3State.prototype.ctor.apply(this, args);
                    return this;
                }
            }
            _Test3State.__inner__ = function inner() {};
            _Test3State.prototype = {
                getHeight: function getHeight(height) {
                    const __thiz__ = this;
                    const __arg_ctx__ = {
                        height,
                    };
                    with(__thiz__) {
                        with(__arg_ctx__) {
                            return height; //这个height是什么类型
                        }
                    }
                },
            };
            _Test3State.prototype.ctor = function() {};;
            return _Test3State();
        }
    }, []);
})(convertObjectLiteralToSetOrMap(JSON.parse('#FairProps#')));
//"{\"pageName\":\"test1#0\",\"type\":\"method\",\"args\":{\"funcName\":\"getHeight\",\"args\":[\"100\"]}}"
//经过native调用fair_core.js中的办法:
function invokeJSFunc(parameter) {
    if (parameter === null) {
        return null;
    }
    let map = JSON.parse(parameter);
    if ('method' === map['type']) {
        return _invokeMethod(map);// 类型是method则调用姓名为getHeight 的js办法
    } else if ('variable' === map['type']) {
        return _invokeVariable(map);
    }
    return null;
}
function _invokeMethod(par) {
    let pageName = par['pageName'];
    let funcName = par['args']['funcName'];
    let args = par['args']['args'];
    if ('getAllJSBindData' === funcName) {
        return getAllJSBindData(par);
    }
    if ('releaseJS' === funcName) {
        return _release(par);
    }
    let mClass = GLOBAL[pageName];
    let func = mClass[funcName];
    let methodResult;
    if (isNull(func)) {
        methodResult = '';
    } else {
        methodResult = func.apply(mClass, args);//调用js办法
    }
    let result = {
        pageName: pageName,
        result: {
            result: methodResult//methodResult为什么总是string类型
        }
    };
    return JSON.stringify(result);
}
经过native转化将成果成果经过 dartFFI函数回来dart端
//dartffi调用
const char *invokeJSCommonFuncSync(char *args) {
    if ([FairDynamicFlutter sharedInstance].delegate &&
        [[FairDynamicFlutter sharedInstance].delegate respondsToSelector:@selector(executeScriptSyncImpl:)]) {
        return [[FairDynamicFlutter sharedInstance].delegate executeScriptSyncImpl:args];
    }
    return "";
}
//[[FairDynamicFlutter sharedInstance].delegate executeScriptSyncImpl:args];native真实的完成
- (const char *)executeScriptSyncImpl:(char *)args
{
    JSValue *obj;
    if (self.delegate && [self.delegate respondsToSelector:@selector(executeJSFunctionSync:params:)]) {
        NSString *str = [NSString stringWithUTF8String:args];
        obj = [self.delegate executeJSFunctionSync:FairExecuteJSFunction params:@[str]];
    }
    NSString *result = [NSString stringWithFormat:@"%@", obj.toString];
    FairLog(@"result:%@", result);
    if([result isEqualToString:@"undefined"]){
        //取args中的funcName字段
        //arg ===> "{\"pageName\":\"null#0\",\"type\":\"method\",\"args\":{\"funcName\":\"_getAuth\",\"args\":null}}"
        NSString *str = [NSString stringWithUTF8String:args];
        NSData *jsonData = [str dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
        NSDictionary *args = dic[@"args"];
        NSString *funcName = args[@"funcName"];
        FairLog(@"invoke funcName:%@",funcName);
        NSString *errorResult = [NSString stringWithFormat:@"Runtime error while invoke JavaScript method:%@()", funcName];
        return errorResult.UTF8String;
    }
    return result.UTF8String;
}

总结

到这儿基本,就简单剖析了界面转化进程的源码完成部分。下一步继续剖析:

  • FairAppMap<String, FairModuleBuilder>? modules 运用
  • 自界说插件作业流程和运用
  • 带参数函数调用
  • json页面文件中办法被转化为在在methodMap和没有转化履行区别以及办法带参数时不能在methodMap中匹配履行区别
  • 关于自界说dart代码import 'package:fairdemo/fair_test/test_definemodule.dart'; import 'test_definemodule.dart';@FairPatch()页面中经过注解生成的js文件中 defineModule作用和生成规矩,生成的defineModule js部分示例代码为:
  defineModule(1, function(__mod__) {
        with(__mod__.imports) {
            inherit(ScreenUtilPlugin, IFairPlugin);
        }
        __mod__.exports.ScreenUtilPlugin = ScreenUtilPlugin;
    }, []);```