├── .gitignore ├── test └── test.js ├── img └── react-native-webview-callback_01.png ├── src ├── baseH5Api.ts ├── baseReactNativeApi.ts ├── index.ts └── events.ts ├── tsconfig.types.json ├── babel.config.js ├── LICENSE ├── tsconfig.json ├── package.json ├── rollup.config.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /dist 3 | .DS_Store 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | // const { sayHelloWorld } = require('../dist/index.js') 2 | 3 | console.log('helo'); -------------------------------------------------------------------------------- /img/react-native-webview-callback_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liutaohz/react-native-webview-callback/HEAD/img/react-native-webview-callback_01.png -------------------------------------------------------------------------------- /src/baseH5Api.ts: -------------------------------------------------------------------------------- 1 | // 测试React Native 自定义基础API 2 | const echoH5Test = (res: any) => { 3 | return new Promise((resolve, reject) => { 4 | if (res === 'hello world H5') { 5 | resolve(res) // 成功 6 | } else { 7 | reject(res) // 失败 8 | } 9 | }) 10 | }; 11 | 12 | export default { 13 | echoH5Test: echoH5Test, 14 | } -------------------------------------------------------------------------------- /src/baseReactNativeApi.ts: -------------------------------------------------------------------------------- 1 | // 测试React Native 自定义基础API 2 | const echoReactNativeTest = (res: any) => { 3 | return new Promise((resolve, reject) => { 4 | if (res === 'hello world react-native') { 5 | resolve(res) // 成功 6 | } else { 7 | reject(res) // 失败 8 | } 9 | }) 10 | }; 11 | 12 | export default { 13 | echoReactNativeTest: echoReactNativeTest, 14 | } -------------------------------------------------------------------------------- /tsconfig.types.json: -------------------------------------------------------------------------------- 1 | { 2 | // 继承 tsconfig.json 中的通用配置 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "declaration": true, /* 生成相应的 '.d.ts' file. */ 6 | "declarationDir": "./dist/types", /* 类型声明文件输出目录 */ 7 | "emitDeclarationOnly": true, /* 只生成声明文件,不生成 js 文件*/ 8 | "rootDir": "./src", /* 指定输出文件目录(用于输出),用于控制输出目录结构 */ 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | /* Babel 会在 Rollup 有机会做处理之前,将我们的模块转成 CommonJS,导致 Rollup 的一些处理失败 */ 7 | "modules": false 8 | } 9 | ] 10 | ], 11 | "plugins": [ 12 | [ 13 | // 与 babelHelpers: 'runtime' 配合使用 14 | "@babel/plugin-transform-runtime" 15 | ] 16 | ] 17 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import baseH5Api from './baseH5Api'; 2 | import baseReactNativeApi from './baseReactNativeApi'; 3 | import { 4 | useH5AddListener, 5 | h5CallreactNative, 6 | useReactNativeAddListener, 7 | reactNativeCallH5, 8 | } from './events'; 9 | // 合并基础方法,将合并的方法返回到应用端,用户方法监听调用 10 | const mergeReactNativeApi = (userApi = {}) => { 11 | return { 12 | ...baseReactNativeApi, 13 | ...userApi, // 用户定义APP接口 14 | }; 15 | }; 16 | // 合并基础方法,将合并的方法返回到应用端,用户方法监听调用 17 | const mergeH5Api = (userApi = {}) => { 18 | return { 19 | ...baseH5Api, 20 | ...userApi, // 用户定义H5接口 21 | }; 22 | }; 23 | export { 24 | mergeH5Api, 25 | useH5AddListener, 26 | h5CallreactNative, 27 | mergeReactNativeApi, 28 | useReactNativeAddListener, 29 | reactNativeCallH5, 30 | }; 31 | export default { 32 | mergeH5Api, 33 | useH5AddListener, // 只需要在入口文件初始化一次。初始化,将合并后的API作为参数传进去 34 | h5CallreactNative, // 在任何页面都可以直接调用 35 | mergeReactNativeApi, 36 | useReactNativeAddListener, // react native 初始化 37 | reactNativeCallH5, // react native 调用H5接口 38 | }; 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 liutao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* 基础选项 */ 4 | "target": "esnext", /* 指定 ECMAScript 目标版本:'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "esnext", /* 输出的代码使用什么方式进行模块化: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": [ /* 指定引用的标准库 */ 7 | "esnext", 8 | "dom", 9 | "dom.iterable", 10 | ], 11 | "allowJs": true, /* 允许编译 js 文件 */ 12 | "removeComments": true, /* 输出不包含注释 */ 13 | /* 严格类型检查选项 */ 14 | "strict": true, /* 启用所有严格类型检查选项 */ 15 | "noImplicitAny": false, /* 检查隐含 any 类型的表达式和声明 */ 16 | "strictNullChecks": false, /* 严格空检查. */ 17 | /* 额外检查 */ 18 | "noUnusedLocals": false, /* 检查无用的变量. */ 19 | /* Module Resolution Options */ 20 | "moduleResolution": "node", /* 指定模块查找策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6) */ 21 | "baseUrl": "./", /* 查找模块的基础目录 */ 22 | "paths": { 23 | "@/*": [ 24 | "src/*" 25 | ] 26 | }, /* 记录 baseUrl 的模块路径查找别名 */ 27 | "types": [], /* 类型声明文件 */ 28 | }, 29 | "include": [ /* 指定编译处理的文件列表 */ 30 | "src/*.ts" 31 | ], 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-webview-callback", 3 | "version": "0.0.5", 4 | "description": "A lightweight tool library for connecting React Native and webview, providing communication and success and failure callback methods", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.esm.js", 7 | "umd": "./dist/index.umd.js", 8 | "types": "./dist/types/index.d.ts", 9 | "scripts": { 10 | "clean:dist": "rimraf dist", 11 | "build:types": "npm run clean:dist && tsc -b ./tsconfig.types.json", 12 | "build": "npm run build:types && rollup -c", 13 | "test": "node test/test.js", 14 | "pretest": "npm run build" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/liutaohz/react-native-webview-callback.git" 19 | }, 20 | "keywords": [ 21 | "React", 22 | "Native", 23 | "webview", 24 | "callback", 25 | "promise", 26 | "h5", 27 | "communication" 28 | ], 29 | "author": "liutaohangzhou@163.com", 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/liutaohz/react-native-webview-callback/issues" 33 | }, 34 | "homepage": "https://github.com/liutaohz/react-native-webview-callback#readme", 35 | "devDependencies": { 36 | "@babel/plugin-transform-runtime": "^7.22.15", 37 | "@babel/preset-env": "^7.22.20", 38 | "@rollup/plugin-babel": "^6.0.4", 39 | "@rollup/plugin-commonjs": "^25.0.5", 40 | "@rollup/plugin-node-resolve": "^15.2.3", 41 | "@types/events": "^3.0.1", 42 | "@types/react": "^18.2.27", 43 | "rimraf": "^5.0.5", 44 | "rollup": "^2.79.1", 45 | "rollup-plugin-terser": "^7.0.2", 46 | "rollup-plugin-typescript2": "^0.36.0", 47 | "typescript": "^5.2.2" 48 | }, 49 | "files": [ 50 | "dist" 51 | ], 52 | "dependencies": { 53 | "events": "^3.3.0" 54 | }, 55 | "peerDependencies": { 56 | "react": ">16.8.3" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import resolve from '@rollup/plugin-node-resolve' 3 | import commonjs from '@rollup/plugin-commonjs' 4 | import rollupTypescript from 'rollup-plugin-typescript2' 5 | import babel from '@rollup/plugin-babel' 6 | import { DEFAULT_EXTENSIONS } from '@babel/core' 7 | import { terser } from 'rollup-plugin-terser' 8 | 9 | // 读取 package.json 配置 10 | import pkg from './package.json' 11 | // 当前运行环境,可通过 cross-env 命令行设置 12 | const env = process.env.NODE_ENV 13 | // umd 模式的编译结果文件输出的全局变量名称 14 | const name = 'ReactNativeWebViewCallback' 15 | const config = { 16 | // 入口文件,src/index.ts 17 | input: path.resolve(__dirname, 'src/index.ts'), 18 | // 输出文件 19 | output: [ 20 | // commonjs 21 | // { 22 | // // package.json 配置的 main 属性 23 | // file: pkg.main, 24 | // format: 'cjs', 25 | // }, 26 | // index 打一个UMD包,不打CJS 27 | { 28 | // umd 导出文件的全局变量 29 | name, 30 | // package.json 配置的 umd 属性 31 | file: pkg.main, 32 | format: 'umd' 33 | }, 34 | // es module 35 | { 36 | // package.json 配置的 module 属性 37 | file: pkg.module, 38 | format: 'es', 39 | }, 40 | // umd 41 | { 42 | // umd 导出文件的全局变量 43 | name, 44 | // package.json 配置的 umd 属性 45 | file: pkg.umd, 46 | format: 'umd' 47 | } 48 | ], 49 | plugins: [ 50 | // 解析第三方依赖 51 | resolve(), 52 | // 识别 commonjs 模式第三方依赖 53 | commonjs(), 54 | // rollup 编译 typescript 55 | rollupTypescript(), 56 | // babel 配置 57 | babel({ 58 | // 编译库使用 runtime 59 | babelHelpers: 'runtime', 60 | // 只转换源代码,不转换外部依赖 61 | exclude: 'node_modules/**', 62 | // babel 默认不支持 ts 需要手动添加 63 | extensions: [ 64 | ...DEFAULT_EXTENSIONS, 65 | '.ts', 66 | ], 67 | }), 68 | ] 69 | } 70 | 71 | // 若打包正式环境,压缩代码 72 | if (env === 'production') { 73 | config.plugins.push(terser({ 74 | compress: { 75 | pure_getters: true, 76 | unsafe: true, 77 | unsafe_comps: true, 78 | warnings: false 79 | } 80 | })) 81 | } 82 | export default config -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-webview-callback 2 | 3 | [](https://npmjs.org/package/react-native-webview-callback) 4 | [](https://npmjs.org/package/react-native-webview-callback) 5 | 6 | A lightweight tool library for connecting React Native and webview, providing communication and success and failure callback methods 7 | 8 | 我的博文:[实现React Native与内嵌H5相互通信](https://juejin.cn/post/7297144566251454502) 9 | 10 |  11 | 12 | 13 | 14 | 15 | ## Usage 16 | 17 | ### Import Dependency Package 18 | 19 | ``` 20 | npm install react-native-webview-callback 21 | 22 | ``` 23 | 24 | ### Configure and use on H5 end 25 | 26 | #### Define your own methods to provide for React Native calls 27 | 28 | You can define your own event API and incorporate it during subsequent initialization. eg(myEvent.ts) 29 | 30 | 31 | 32 | 33 | ``` js 34 | // customH5Api.ts 35 | 36 | // Define your own methods to provide for React Native calls 37 | const getWebToken = () => { 38 | return new Promise((resolve, reject) => { 39 | try { 40 | const token = window.localStorage.getItem('token')||'hello'; 41 | resolve(token) // Successful callback 42 | } catch (error) { 43 | reject(error) // Failed callback 44 | } 45 | }) 46 | }; 47 | // other methods 48 | 49 | export default { 50 | getWebToken: getWebToken, 51 | // other methods 52 | } 53 | ``` 54 | 55 | #### Initialize listening in the entry file && Use and get callback 56 | 57 | Initialize listening methods in the entry file 58 | 59 | ``` js 60 | import { useEffect, useState } from 'react' 61 | import { 62 | mergeReactNativeApi, 63 | useReactNativeAddListener, 64 | reactNativeCallH5, 65 | } from 'react-native-webview-callback'; 66 | import myEvent from './customH5Api'; 67 | import './App.css'; 68 | function App() { 69 | useH5AddListener(mergeH5Api(myEvent)) // just need init once ,Entry file 70 | useEffect(() => { 71 | window.localStorage.setItem('token', 'mytokenStrXXXXX');// mock data 72 | },[]) 73 | const [result, setResult] = useState('--'); 74 | const testFn = () => { 75 | h5CallreactNative({ 76 | methodName: "getAppInfo", // Or other interface functions that you customize on the React Native end, eg:“myReactNativeMethod” 77 | data: "", // Object data can also be passed, and the specific parameter format depends on the defined interface parameters 78 | }) 79 | .then((data) => { 80 | if (typeof data === 'object') { 81 | setResult(JSON.stringify(data)) 82 | } else if (typeof data === 'string') { 83 | setResult(data) 84 | } 85 | console.log("Successful data:", data); 86 | }) 87 | .catch((error) => { 88 | alert("Failed from React Native callback"); 89 | console.error("Failed data:", error); 90 | }); 91 | } 92 | return ( 93 | <> 94 |
100 | {result} 101 |
102 |