当前位置:   article > 正文

ArkTS 动态解析 JavaScript 的替代方案(一)_arkts runjavascript

arkts runjavascript

利用 Web 来实现 JavaScript 的动态解析,代码如下:

  1. import webview from '@ohos.web.webview';
  2. function logDefault(msg: Object) {
  3. if (msg) console.log("ArkTS" + (msg ? ": " + msg.toString() : "null"));
  4. }
  5. type ScriptCallback = (error: Error, result: string) => void;
  6. type VoidCallback = () => void;
  7. /**
  8. * 请配合 JSEngineContainer 一起使用
  9. */
  10. export class JSEngine {
  11. private _controller: webview.WebviewController = new webview.WebviewController();
  12. private _isReady: boolean = false;
  13. private _scriptList: string[] = [];
  14. private _scriptCallbackList: ScriptCallback[] = [];
  15. private execCallback: VoidCallback;
  16. /**
  17. * @param execCallback 执行完毕时,回调的方法
  18. */
  19. constructor(execCallback?: VoidCallback) {
  20. this.execCallback = execCallback;
  21. }
  22. public setExecCallback(execCallback?: VoidCallback) {
  23. this.execCallback = execCallback;
  24. }
  25. get controller(): webview.WebviewController {
  26. return this._controller;
  27. }
  28. public runJavaScript(script: string, callback?: ScriptCallback) {
  29. if (this._scriptList.length == 0 && this._isReady) {
  30. this._controller.runJavaScript(script)
  31. .then((result) => {
  32. if (callback) callback(null, result);
  33. })
  34. .catch((err) => {
  35. if (callback) callback(err, null);
  36. })
  37. .finally(() => {
  38. this.execCallback();
  39. });
  40. } else {
  41. this._scriptList.push(script);
  42. this._scriptCallbackList.push(callback);
  43. }
  44. }
  45. private async execScriptList() {
  46. if (this._scriptList.length > 0) {
  47. let count = this._scriptList.length;
  48. for (let i = 0; i < count; i++) {
  49. let callback: ScriptCallback = this._scriptCallbackList[i];
  50. try {
  51. let result = await this._controller.runJavaScript(this._scriptList[i]);
  52. if (callback) callback(null, result);
  53. } catch (err) {
  54. if (callback) callback(err, null);
  55. }
  56. }
  57. this._scriptList.splice(0, count);
  58. this._scriptCallbackList.splice(0, count);
  59. await this.execScriptList();
  60. }
  61. }
  62. public setIsReady(value: boolean) {
  63. this._isReady = value;
  64. if (this._scriptList.length > 0) {
  65. this.execScriptList().finally(() => {
  66. if (this.execCallback) this.execCallback();
  67. });
  68. }
  69. }
  70. public getIsReady(initIsReady: boolean = false, returnValue?: boolean): boolean {
  71. if (initIsReady) this._isReady = false;
  72. return returnValue == null ? this._isReady : returnValue;
  73. }
  74. public resultToInt(result: string, defaultValue: number = 0, radix?: number) {
  75. if (result && result.length > 0) {
  76. try {
  77. return parseInt(result, radix);
  78. } catch (err) {
  79. return defaultValue;
  80. }
  81. }
  82. return defaultValue;
  83. }
  84. public resultToFloat(result: string, defaultValue: number = 0) {
  85. if (result && result.length > 0) {
  86. try {
  87. return parseFloat(result);
  88. } catch (err) {
  89. return defaultValue;
  90. }
  91. }
  92. return defaultValue;
  93. }
  94. public resultToString(result: string) {
  95. if (result && result.length > 0) {
  96. if (result.startsWith('"') && result.endsWith('"')) {
  97. return result.substring(1, result.length - 1);
  98. }
  99. return result;
  100. }
  101. return "";
  102. }
  103. public resultToObject(result: string, defaultValue: Object = null) {
  104. if (result && result.length > 0) {
  105. if (result.startsWith('"') && result.endsWith('"')) {
  106. result = result.substring(1, result.length - 1);
  107. result = result.replace(/\\\\/gi, '\\');
  108. result = result.replace(/\\"/gi, '"');
  109. }
  110. try {
  111. return JSON.parse(result);
  112. } catch (err) {
  113. return defaultValue;
  114. }
  115. }
  116. return defaultValue;
  117. }
  118. public getJSMethodList(): Array<string> {
  119. return ["getNumberByField1", "getStringByField1", "getObjectByField1"];
  120. }
  121. public getNumberByField1(fieldName1: string): number {
  122. return 88;
  123. }
  124. public getStringByField1(fieldName1: string): string {
  125. return "文本";
  126. }
  127. public getObjectByField1(fieldName1: string): string {
  128. return JSON.stringify({ key: "值" });
  129. }
  130. }
  131. @Builder
  132. export function JSEngineContainer(jsEngine: JSEngine) {
  133. if (jsEngine.getIsReady(true, true)) {
  134. Web({ src: "JSEngine", controller: jsEngine.controller })
  135. .javaScriptAccess(true)
  136. .onErrorReceive(() => {
  137. jsEngine.setIsReady(true);
  138. })
  139. .javaScriptProxy({
  140. object: jsEngine,
  141. name: "formData",
  142. methodList: jsEngine.getJSMethodList(),
  143. controller: jsEngine.controller,
  144. })
  145. .width(1)
  146. .height(1)
  147. }
  148. }
  149. @Entry
  150. @Component
  151. struct TestAct {
  152. readonly jsEngine: JSEngine = new JSEngine(() => {
  153. logDefault("执行完毕")
  154. });
  155. @State runResult: string = "";
  156. aboutToAppear() {
  157. this.jsEngine.runJavaScript("formData.getNumberByField1('field1');", (err, result) => {
  158. if (err == null) {
  159. this.runResult = result.toString();
  160. let temp = this.jsEngine.resultToInt(result);
  161. logDefault("formData.getNumberByField1('field1') = " + temp);
  162. }
  163. });
  164. }
  165. build() {
  166. Column() {
  167. JSEngineContainer(this.jsEngine);
  168. Button("执行脚本").onClick(() => {
  169. this.jsEngine.runJavaScript("formData.getStringByField1('field1');", (err, result) => {
  170. if (err == null) {
  171. this.runResult = result.toString();
  172. let temp = this.jsEngine.resultToString(result);
  173. logDefault("formData.getStringByField1('field1') = " + temp);
  174. }
  175. });
  176. this.jsEngine.runJavaScript("formData.getObjectByField1('field1');", (err, result) => {
  177. if (err == null) {
  178. this.runResult = result.toString();
  179. let temp = this.jsEngine.resultToObject(result);
  180. logDefault("formData.getObjectByField1('field1') = " + temp["key"]);
  181. }
  182. });
  183. })
  184. if (this.runResult && this.runResult.length > 0) {
  185. Text("执行脚本结果:").margin({ top: 16 })
  186. Text(this.runResult).margin({ top: 16 }).fontColor(Color.Brown)
  187. }
  188. }.alignItems(HorizontalAlign.Start).padding(16)
  189. }
  190. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/273700
推荐阅读
相关标签
  

闽ICP备14008679号