parent
6222454bf6
commit
5ce9f4cc15
@ -0,0 +1,306 @@ |
|||||||
|
# dependencies |
||||||
|
/node_modules |
||||||
|
|
||||||
|
# production |
||||||
|
/dist |
||||||
|
|
||||||
|
# misc |
||||||
|
.DS_Store |
||||||
|
.vscode |
||||||
|
.ideal |
||||||
|
|
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
yarn.lock |
||||||
|
package-lock.json |
||||||
|
|
||||||
|
|
||||||
|
# General |
||||||
|
.DS_Store |
||||||
|
.AppleDouble |
||||||
|
.LSOverride |
||||||
|
|
||||||
|
# Icon must end with two \r |
||||||
|
Icon |
||||||
|
|
||||||
|
# Thumbnails |
||||||
|
._* |
||||||
|
|
||||||
|
# Files that might appear in the root of a volume |
||||||
|
.DocumentRevisions-V100 |
||||||
|
.fseventsd |
||||||
|
.Spotlight-V100 |
||||||
|
.TemporaryItems |
||||||
|
.Trashes |
||||||
|
.VolumeIcon.icns |
||||||
|
.com.apple.timemachine.donotpresent |
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share |
||||||
|
.AppleDB |
||||||
|
.AppleDesktop |
||||||
|
Network Trash Folder |
||||||
|
Temporary Items |
||||||
|
.apdisk |
||||||
|
|
||||||
|
|
||||||
|
# Compiled class file |
||||||
|
*.class |
||||||
|
|
||||||
|
# Log file |
||||||
|
*.log |
||||||
|
|
||||||
|
# BlueJ files |
||||||
|
*.ctxt |
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME) |
||||||
|
.mtj.tmp/ |
||||||
|
|
||||||
|
# Package Files # |
||||||
|
*.jar |
||||||
|
*.war |
||||||
|
*.nar |
||||||
|
*.ear |
||||||
|
*.zip |
||||||
|
*.tar.gz |
||||||
|
*.rar |
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml |
||||||
|
hs_err_pid* |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Built application files |
||||||
|
*.apk |
||||||
|
*.ap_ |
||||||
|
*.aab |
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM |
||||||
|
*.dex |
||||||
|
|
||||||
|
# Java class files |
||||||
|
*.class |
||||||
|
|
||||||
|
# Generated files |
||||||
|
bin/ |
||||||
|
gen/ |
||||||
|
out/ |
||||||
|
release/ |
||||||
|
|
||||||
|
# Gradle files |
||||||
|
.gradle/ |
||||||
|
build/ |
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc) |
||||||
|
local.properties |
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse |
||||||
|
proguard/ |
||||||
|
|
||||||
|
# Log Files |
||||||
|
*.log |
||||||
|
|
||||||
|
# Android Studio Navigation editor temp files |
||||||
|
.navigation/ |
||||||
|
|
||||||
|
# Android Studio captures folder |
||||||
|
captures/ |
||||||
|
|
||||||
|
# IntelliJ |
||||||
|
*.iml |
||||||
|
.idea/workspace.xml |
||||||
|
.idea/tasks.xml |
||||||
|
.idea/gradle.xml |
||||||
|
.idea/assetWizardSettings.xml |
||||||
|
.idea/dictionaries |
||||||
|
.idea/libraries |
||||||
|
# Android Studio 3 in .gitignore file. |
||||||
|
.idea/caches |
||||||
|
.idea/modules.xml |
||||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you |
||||||
|
.idea/navEditor.xml |
||||||
|
|
||||||
|
# Keystore files |
||||||
|
# Uncomment the following lines if you do not want to check your keystore files in. |
||||||
|
#*.jks |
||||||
|
#*.keystore |
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later |
||||||
|
.externalNativeBuild |
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase) |
||||||
|
# google-services.json |
||||||
|
|
||||||
|
# Freeline |
||||||
|
freeline.py |
||||||
|
freeline/ |
||||||
|
freeline_project_description.json |
||||||
|
|
||||||
|
# fastlane |
||||||
|
fastlane/report.xml |
||||||
|
fastlane/Preview.html |
||||||
|
fastlane/screenshots |
||||||
|
fastlane/test_output |
||||||
|
fastlane/readme.md |
||||||
|
|
||||||
|
# Version control |
||||||
|
vcs.xml |
||||||
|
|
||||||
|
# lint |
||||||
|
lint/intermediates/ |
||||||
|
lint/generated/ |
||||||
|
lint/outputs/ |
||||||
|
lint/tmp/ |
||||||
|
# lint/reports/ |
||||||
|
|
||||||
|
|
||||||
|
# Xcode |
||||||
|
# |
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore |
||||||
|
|
||||||
|
## Build generated |
||||||
|
build/ |
||||||
|
DerivedData/ |
||||||
|
|
||||||
|
## Various settings |
||||||
|
*.pbxuser |
||||||
|
!default.pbxuser |
||||||
|
*.mode1v3 |
||||||
|
!default.mode1v3 |
||||||
|
*.mode2v3 |
||||||
|
!default.mode2v3 |
||||||
|
*.perspectivev3 |
||||||
|
!default.perspectivev3 |
||||||
|
xcuserdata/ |
||||||
|
|
||||||
|
## Other |
||||||
|
*.moved-aside |
||||||
|
*.xccheckout |
||||||
|
*.xcscmblueprint |
||||||
|
|
||||||
|
## Obj-C/Swift specific |
||||||
|
*.hmap |
||||||
|
*.ipa |
||||||
|
*.dSYM.zip |
||||||
|
*.dSYM |
||||||
|
|
||||||
|
# CocoaPods |
||||||
|
# |
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However |
||||||
|
# you should judge for yourself, the pros and cons are mentioned at: |
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control |
||||||
|
# |
||||||
|
# Pods/ |
||||||
|
# |
||||||
|
# Add this line if you want to avoid checking in source code from the Xcode workspace |
||||||
|
# *.xcworkspace |
||||||
|
|
||||||
|
# Carthage |
||||||
|
# |
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies. |
||||||
|
# Carthage/Checkouts |
||||||
|
|
||||||
|
Carthage/Build |
||||||
|
|
||||||
|
# fastlane |
||||||
|
# |
||||||
|
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the |
||||||
|
# screenshots whenever they are needed. |
||||||
|
# For more information about the recommended setup visit: |
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/#source-control |
||||||
|
|
||||||
|
fastlane/report.xml |
||||||
|
fastlane/Preview.html |
||||||
|
fastlane/screenshots/**/*.png |
||||||
|
fastlane/test_output |
||||||
|
|
||||||
|
# Code Injection |
||||||
|
# |
||||||
|
# After new code Injection tools there's a generated folder /iOSInjectionProject |
||||||
|
# https://github.com/johnno1962/injectionforxcode |
||||||
|
|
||||||
|
iOSInjectionProject/ |
||||||
|
|
||||||
|
|
||||||
|
# Xcode |
||||||
|
# |
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore |
||||||
|
|
||||||
|
## Build generated |
||||||
|
build/ |
||||||
|
DerivedData/ |
||||||
|
|
||||||
|
## Various settings |
||||||
|
*.pbxuser |
||||||
|
!default.pbxuser |
||||||
|
*.mode1v3 |
||||||
|
!default.mode1v3 |
||||||
|
*.mode2v3 |
||||||
|
!default.mode2v3 |
||||||
|
*.perspectivev3 |
||||||
|
!default.perspectivev3 |
||||||
|
xcuserdata/ |
||||||
|
|
||||||
|
## Other |
||||||
|
*.moved-aside |
||||||
|
*.xccheckout |
||||||
|
*.xcscmblueprint |
||||||
|
|
||||||
|
## Obj-C/Swift specific |
||||||
|
*.hmap |
||||||
|
*.ipa |
||||||
|
*.dSYM.zip |
||||||
|
*.dSYM |
||||||
|
|
||||||
|
## Playgrounds |
||||||
|
timeline.xctimeline |
||||||
|
playground.xcworkspace |
||||||
|
|
||||||
|
# Swift Package Manager |
||||||
|
# |
||||||
|
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. |
||||||
|
# Packages/ |
||||||
|
# Package.pins |
||||||
|
# Package.resolved |
||||||
|
.build/ |
||||||
|
|
||||||
|
# CocoaPods |
||||||
|
# |
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However |
||||||
|
# you should judge for yourself, the pros and cons are mentioned at: |
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control |
||||||
|
# |
||||||
|
# Pods/ |
||||||
|
# |
||||||
|
# Add this line if you want to avoid checking in source code from the Xcode workspace |
||||||
|
# *.xcworkspace |
||||||
|
|
||||||
|
# Carthage |
||||||
|
# |
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies. |
||||||
|
# Carthage/Checkouts |
||||||
|
|
||||||
|
Carthage/Build |
||||||
|
|
||||||
|
# Accio dependency management |
||||||
|
Dependencies/ |
||||||
|
.accio/ |
||||||
|
|
||||||
|
# fastlane |
||||||
|
# |
||||||
|
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the |
||||||
|
# screenshots whenever they are needed. |
||||||
|
# For more information about the recommended setup visit: |
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/#source-control |
||||||
|
|
||||||
|
fastlane/report.xml |
||||||
|
fastlane/Preview.html |
||||||
|
fastlane/screenshots/**/*.png |
||||||
|
fastlane/test_output |
||||||
|
|
||||||
|
# Code Injection |
||||||
|
# |
||||||
|
# After new code Injection tools there's a generated folder /iOSInjectionProject |
||||||
|
# https://github.com/johnno1962/injectionforxcode |
||||||
|
|
||||||
|
iOSInjectionProject/ |
@ -0,0 +1,16 @@ |
|||||||
|
# dependencies |
||||||
|
/node_modules |
||||||
|
|
||||||
|
# production |
||||||
|
/dist |
||||||
|
|
||||||
|
# misc |
||||||
|
.DS_Store |
||||||
|
.vscode |
||||||
|
.ideal |
||||||
|
|
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
yarn.lock |
||||||
|
package-lock.json |
@ -0,0 +1,45 @@ |
|||||||
|
# JSBridgeH5 |
||||||
|
`JSBridge` 实例中 `H5` 端代码实现。 |
||||||
|
|
||||||
|
此项目使用 react 进行编写,但是关于 react 的代码不多,其中关于 jsbridge 使用的代码在任意项目或者框架中均可使用。 |
||||||
|
|
||||||
|
代码中有详细注释。 |
||||||
|
|
||||||
|
|
||||||
|
## 下载项目 |
||||||
|
``` bash |
||||||
|
git clone https://github.com/beichensky/jsbridge-example.git |
||||||
|
``` |
||||||
|
|
||||||
|
## 安装插件 |
||||||
|
``` bash |
||||||
|
# 打开 JSBridgeH5 项目 |
||||||
|
cd JSBridgeH5 |
||||||
|
|
||||||
|
# 安装依赖 |
||||||
|
npm install |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
## 运行项目 |
||||||
|
``` bash |
||||||
|
npm run start |
||||||
|
``` |
||||||
|
|
||||||
|
打开浏览器,输入:`localhost:8000` 查看项目运行效果。 |
||||||
|
|
||||||
|
运行项目后,才能在原生应用中展示,否则移动端 Webview 加载不出来页面。请记得在将当前的 ip 地址和端口替换到移动端 url 上。 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 项目打包 |
||||||
|
``` bash |
||||||
|
npm run build |
||||||
|
``` |
||||||
|
|
||||||
|
新增 `dist` 目录,里面是打包好的项目代码 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 更多 |
||||||
|
关于项目的更多介绍请查看我的博客:[使用 JSBridge 与原生 IOS、Android 进行交互(含H5、Android、IOS端代码,附 Demo)]() |
@ -0,0 +1,69 @@ |
|||||||
|
module.exports = (api) => { |
||||||
|
api.cache(true); |
||||||
|
|
||||||
|
return { |
||||||
|
presets: [ |
||||||
|
"@babel/preset-env", |
||||||
|
"@babel/preset-react" |
||||||
|
], |
||||||
|
plugins: [ |
||||||
|
[ |
||||||
|
"@babel/plugin-proposal-decorators", |
||||||
|
{ |
||||||
|
"legacy": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"import", |
||||||
|
{ |
||||||
|
"libraryName": "antd", |
||||||
|
"style": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"@babel/plugin-transform-runtime", |
||||||
|
{ |
||||||
|
"corejs": 2 |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"@babel/plugin-proposal-class-properties",
|
||||||
|
{
|
||||||
|
"loose": true |
||||||
|
} |
||||||
|
], |
||||||
|
"@babel/plugin-syntax-dynamic-import", |
||||||
|
// "@babel/plugin-syntax-import-meta",
|
||||||
|
// 可以用 const ex = "before
|
||||||
|
// after"; 这种方式编写字符串
|
||||||
|
// "@babel/plugin-proposal-json-strings",
|
||||||
|
// 可以使用 generate 语法
|
||||||
|
// "@babel/plugin-proposal-function-sent",
|
||||||
|
// 可以使用 export * 这种命名空间的方式导出模块
|
||||||
|
"@babel/plugin-proposal-export-namespace-from", |
||||||
|
// 可以使用数字分离器书写数字
|
||||||
|
// "@babel/plugin-proposal-numeric-separator"
|
||||||
|
// 可以使用异常抛出表达式,
|
||||||
|
"@babel/plugin-proposal-throw-expressions", |
||||||
|
// 默认导出
|
||||||
|
"@babel/plugin-proposal-export-default-from", |
||||||
|
// 可以使用逻辑赋值运算符
|
||||||
|
"@babel/plugin-proposal-logical-assignment-operators", |
||||||
|
// 可以使用可选链的方式访问深层嵌套的属性或者函数 ?.
|
||||||
|
"@babel/plugin-proposal-optional-chaining", |
||||||
|
// 可以使用管道运算符 |>
|
||||||
|
[ |
||||||
|
"@babel/plugin-proposal-pipeline-operator", |
||||||
|
{ |
||||||
|
"proposal": "minimal" |
||||||
|
} |
||||||
|
], |
||||||
|
// 可以使用空值合并语法 ??
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator", |
||||||
|
// 可以使用 do 表达式(可以认为是三元运算符的复杂版本)
|
||||||
|
"@babel/plugin-proposal-do-expressions", |
||||||
|
// 可以使用功能绑定语法 obj::func
|
||||||
|
"@babel/plugin-proposal-function-bind" |
||||||
|
] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
{ |
||||||
|
"name": "jsbridge-h5", |
||||||
|
"version": "1.0.0", |
||||||
|
"description": "", |
||||||
|
"private": true, |
||||||
|
"scripts": { |
||||||
|
"start": "webpack-dev-server --config webpack/webpack.config.dev.js", |
||||||
|
"build": "webpack --config webpack/webpack.config.prod.js" |
||||||
|
}, |
||||||
|
"keywords": [], |
||||||
|
"author": "", |
||||||
|
"license": "ISC", |
||||||
|
"devDependencies": { |
||||||
|
"@babel/core": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-class-properties": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-decorators": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-do-expressions": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-export-default-from": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-export-namespace-from": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-function-bind": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-logical-assignment-operators": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-optional-chaining": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-pipeline-operator": "^7.0.0", |
||||||
|
"@babel/plugin-proposal-throw-expressions": "^7.0.0", |
||||||
|
"@babel/plugin-syntax-dynamic-import": "^7.0.0", |
||||||
|
"@babel/plugin-transform-runtime": "^7.0.0", |
||||||
|
"@babel/preset-env": "^7.0.0", |
||||||
|
"@babel/preset-react": "^7.0.0", |
||||||
|
"@babel/runtime-corejs2": "^7.0.0", |
||||||
|
"autoprefixer": "^9.5.1", |
||||||
|
"babel-loader": "^8.0.0", |
||||||
|
"babel-plugin-import": "^1.11.0", |
||||||
|
"clean-webpack-plugin": "^2.0.1", |
||||||
|
"css-loader": "^2.1.1", |
||||||
|
"csv-loader": "^3.0.2", |
||||||
|
"file-loader": "^3.0.1", |
||||||
|
"friendly-errors-webpack-plugin": "^1.7.0", |
||||||
|
"html-loader": "^0.5.5", |
||||||
|
"html-webpack-plugin": "^3.2.0", |
||||||
|
"less": "^3.9.0", |
||||||
|
"less-loader": "^4.1.0", |
||||||
|
"markdown-loader": "^5.0.0", |
||||||
|
"mini-css-extract-plugin": "^0.5.0", |
||||||
|
"optimize-css-assets-webpack-plugin": "^5.0.1", |
||||||
|
"postcss-loader": "^3.0.0", |
||||||
|
"style-loader": "^0.23.1", |
||||||
|
"uglifyjs-webpack-plugin": "^2.1.2", |
||||||
|
"webpack": "^4.29.6", |
||||||
|
"webpack-cli": "^3.3.0", |
||||||
|
"webpack-dev-server": "^3.1.4", |
||||||
|
"webpack-merge": "^4.2.1", |
||||||
|
"xml-loader": "^1.2.1" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"antd": "^3.16.2", |
||||||
|
"js-cookie": "^2.2.0", |
||||||
|
"moment": "^2.24.0", |
||||||
|
"prop-types": "^15.7.2", |
||||||
|
"qs": "^6.7.0", |
||||||
|
"react": "^16.8.6", |
||||||
|
"react-dom": "^16.8.6" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,12 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge"> |
||||||
|
<title>JSBridge Demo</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="root"></div> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,79 @@ |
|||||||
|
import React, { Component, useState } from 'react'; |
||||||
|
import { Button, Input, message } from 'antd'; |
||||||
|
import Cookie from 'js-cookie'; |
||||||
|
|
||||||
|
// 使用 CSS Module 的方式引入 App.less
|
||||||
|
import styles from './App.less'; |
||||||
|
|
||||||
|
|
||||||
|
const isAndroid = navigator.userAgent.endsWith('android'); |
||||||
|
|
||||||
|
export default (props) => { |
||||||
|
|
||||||
|
const [user, setUser] = useState(); |
||||||
|
const [name, setName] = useState(); |
||||||
|
const [token, setToken] = useState(Cookie.get('token')); |
||||||
|
|
||||||
|
window.setupWebViewJavascriptBridge(bridge => { |
||||||
|
bridge.registerHandler("changeName", (data, fn) => { |
||||||
|
setName(data); |
||||||
|
fn && fn(""); |
||||||
|
}); |
||||||
|
|
||||||
|
bridge.registerHandler("syncCookie", (data, fn) => {
|
||||||
|
setToken(Cookie.get('token')); |
||||||
|
fn && fn(""); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
/** |
||||||
|
* 调用原生的默认接受方法 |
||||||
|
*/ |
||||||
|
const handleInit = () => { |
||||||
|
window.setupWebViewJavascriptBridge(bridge => { |
||||||
|
bridge.send("JS 传递给原生的消息", (data) => { |
||||||
|
message.success(data); |
||||||
|
}) |
||||||
|
}) |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* 调用原生方法刷新 H5 界面 |
||||||
|
*/ |
||||||
|
const handleReload = () => { |
||||||
|
window.setupWebViewJavascriptBridge(bridge => { |
||||||
|
bridge.callHandler('reloadUrl'); |
||||||
|
}) |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* 修改原生界面的 User 名称 |
||||||
|
*/ |
||||||
|
const handleChangeUser = () => { |
||||||
|
window.setupWebViewJavascriptBridge(bridge => { |
||||||
|
bridge.callHandler('changeUser', user, () => { |
||||||
|
message.success('user 修改成功!'); |
||||||
|
setUser(''); |
||||||
|
}); |
||||||
|
}) |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className={ styles.app }> |
||||||
|
<h2>H5 界面:</h2> |
||||||
|
{ isAndroid ? <Button style={{ margin: '10px 0 30px' }} type="primary" onClick={ handleInit }>调用原生默认接收方法</Button> : null} |
||||||
|
<br /> |
||||||
|
<Button style={{ marginBottom: 30 }} type="primary" onClick={ handleReload }>调用原生方法刷新 H5 界面</Button> |
||||||
|
<br /> |
||||||
|
<Button type="primary" onClick={ handleChangeUser }>修改原生界面的 user 值</Button> |
||||||
|
<Input value={ user } onChange={ (e) => setUser(e.target.value) } style={{ marginLeft: 10, width: 160 }} placeholder="请输入新的 user 名称" /> |
||||||
|
<div style={{ marginTop: 30, fontSize: 16 }}> |
||||||
|
<label>Name 值:</label><span style={{ marginLeft: 40 }}>{ name }</span> |
||||||
|
</div> |
||||||
|
<div style={{ marginTop: 30, fontSize: 16 }}> |
||||||
|
<label>同步原生设置的 Cookie 值:</label><span style={{ marginLeft: 20 }}>{ token }</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
|
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
.app { |
||||||
|
padding: 20px; |
||||||
|
background: #f0f0f0; |
||||||
|
} |
@ -0,0 +1,91 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import ReactDom from 'react-dom'; |
||||||
|
import { LocaleProvider, message } from 'antd'; |
||||||
|
import zh_CN from 'antd/lib/locale-provider/zh_CN'; |
||||||
|
import 'moment/locale/zh-cn'; |
||||||
|
|
||||||
|
import App from './App'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用 JSBridge 总结: |
||||||
|
* 1、跟 IOS 交互的时候,只需要且必须注册 iosFuntion 方法即可, |
||||||
|
* 不能在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则 IOS 无法调用到 H5 的注册函数; |
||||||
|
* 2、与安卓进行交互的时候 |
||||||
|
* ①、使用 iosFuntion,就可以实现 H5 调用 安卓的注册函数,但是安卓无法调用 H5 的注册函数, |
||||||
|
* 并且 H5 调用安卓成功后的回调函数也无法执行 |
||||||
|
* ②、使用 andoirFunction 并且要在 setupWebViewJavascriptBridge 中执行 bridge.init 方法, |
||||||
|
* 安卓才可以正常调用 H5 的回调函数,并且 H5 调用安卓成功后的回调函数也可以正常执行了 |
||||||
|
*/ |
||||||
|
|
||||||
|
const isAndroid = navigator.userAgent.endsWith('android'); |
||||||
|
|
||||||
|
/** |
||||||
|
* Android 与安卓交互时: |
||||||
|
* 1、不调用这个函数安卓无法调用 H5 注册的事件函数; |
||||||
|
* 2、但是 H5 可以正常调用安卓注册的事件函数; |
||||||
|
* 3、还必须在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则: |
||||||
|
* ①、安卓依然无法调用 H5 注册的事件函数 |
||||||
|
* ①、H5 正常调用安卓事件函数后的回调函数无法正常执行 |
||||||
|
*
|
||||||
|
* @param {*} callback
|
||||||
|
*/ |
||||||
|
const andoirFunction = (callback) => { |
||||||
|
if (window.WebViewJavascriptBridge) { |
||||||
|
callback(window.WebViewJavascriptBridge); |
||||||
|
} else { |
||||||
|
document.addEventListener('WebViewJavascriptBridgeReady', function () { |
||||||
|
callback(window.WebViewJavascriptBridge); |
||||||
|
}, false) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* IOS 与 IOS 交互时,使用这个函数即可,别的操作都不需要执行 |
||||||
|
* @param {*} callback
|
||||||
|
*/ |
||||||
|
const iosFuntion = (callback) => { |
||||||
|
if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge) } |
||||||
|
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback) } |
||||||
|
window.WVJBCallbacks = [callback]; |
||||||
|
var WVJBIframe = document.createElement('iframe'); |
||||||
|
WVJBIframe.style.display = 'none'; |
||||||
|
WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; |
||||||
|
document.documentElement.appendChild(WVJBIframe); |
||||||
|
setTimeout(function(){ |
||||||
|
document.documentElement.removeChild(WVJBIframe); |
||||||
|
}, 0); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 注册 setupWebViewJavascriptBridge 方法 |
||||||
|
* 之所以不将上面两个方法融合成一个方法,是因为放在一起,那么就只有 iosFuntion 中相关的方法体生效 |
||||||
|
*/ |
||||||
|
window.setupWebViewJavascriptBridge = isAndroid ? andoirFunction : iosFuntion; |
||||||
|
|
||||||
|
/** |
||||||
|
* 这里如果不做判断是不是安卓,而是直接就执行下面的方法,就会导致
|
||||||
|
* 1、IOS 无法调用 H5 这边注册的事件函数 |
||||||
|
* 2、H5 可以正常调用 IOS 这边的事件函数,并且 H5 的回调函数可以正常执行 |
||||||
|
*/ |
||||||
|
if (isAndroid) { |
||||||
|
/** |
||||||
|
* 与安卓交互时,不调用这个函数会导致: |
||||||
|
* 1、H5 可以正常调用 安卓这边的事件函数,但是无法再调用到 H5 的回调函数 |
||||||
|
*
|
||||||
|
* 前提 setupWebViewJavascriptBridge 这个函数使用的是 andoirFunction 这个,否则还是会导致上面 1 的现象出现 |
||||||
|
*/ |
||||||
|
window.setupWebViewJavascriptBridge(function (bridge) { |
||||||
|
// 注册 H5 界面的默认接收函数(与安卓交互时,不注册这个事件无法接收回调函数)
|
||||||
|
bridge.init(function (msg, responseCallback) { |
||||||
|
message.success(msg); |
||||||
|
responseCallback("JS 返回给原生的消息内容"); |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
ReactDom.render( |
||||||
|
<LocaleProvider locale={zh_CN}> |
||||||
|
<App /> |
||||||
|
</LocaleProvider>, |
||||||
|
document.querySelector('#root') |
||||||
|
); |
@ -0,0 +1,146 @@ |
|||||||
|
const path = require('path'); |
||||||
|
const HTMLWebpackPlugin = require('html-webpack-plugin'); |
||||||
|
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); |
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); |
||||||
|
const autoprefixer = require('autoprefixer'); |
||||||
|
|
||||||
|
const appSrc = path.resolve(__dirname, '../src'); |
||||||
|
const appDist = path.resolve(__dirname, '../dist'); |
||||||
|
const appPublic = path.resolve(__dirname, '../public'); |
||||||
|
const appIndex = path.resolve(appSrc, 'index.js'); |
||||||
|
const appHtml = path.resolve(appPublic, 'index.html'); |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
entry: { |
||||||
|
main: [appIndex], |
||||||
|
common: ['react', 'react-dom'] |
||||||
|
}, |
||||||
|
output: { |
||||||
|
filename: 'public/js/[name].[hash:8].js', |
||||||
|
path: appDist, |
||||||
|
publicPath: '/' |
||||||
|
}, |
||||||
|
plugins: [ |
||||||
|
// 自动在出口目录生成 html 并自动引入 js 文件
|
||||||
|
new HTMLWebpackPlugin({ |
||||||
|
template: appHtml, |
||||||
|
filename: 'index.html' |
||||||
|
}), |
||||||
|
// 在命令行展示更清晰地提示信息
|
||||||
|
new FriendlyErrorsWebpackPlugin() |
||||||
|
], |
||||||
|
module: { |
||||||
|
rules: [ |
||||||
|
// 解析 js
|
||||||
|
{ |
||||||
|
test: /\.(js|jsx)$/, |
||||||
|
loader: 'babel-loader?cacheDirectory', |
||||||
|
include: [ appSrc ], |
||||||
|
exclude: /node_modules/ |
||||||
|
}, |
||||||
|
// 解析样式
|
||||||
|
{ |
||||||
|
test: /\.(css|less)$/, |
||||||
|
exclude: /node_modules/, |
||||||
|
use: [ |
||||||
|
{ |
||||||
|
// 使用 MiniCssExtractPlugin.loader 代替 style-loader
|
||||||
|
loader: MiniCssExtractPlugin.loader |
||||||
|
}, |
||||||
|
{ |
||||||
|
loader: 'css-loader', |
||||||
|
options: { |
||||||
|
sourceMap: true, |
||||||
|
modules: true, |
||||||
|
localIdentName: '[local].[hash:8]' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
loader: 'postcss-loader', |
||||||
|
options: { |
||||||
|
plugins: () => [autoprefixer()] |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
loader: 'less-loader', |
||||||
|
options: { |
||||||
|
javascriptEnabled: true |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
test: /\.(css|less)$/, |
||||||
|
include: /node_modules/, |
||||||
|
use: [ |
||||||
|
{ |
||||||
|
loader: MiniCssExtractPlugin.loader |
||||||
|
}, |
||||||
|
{ |
||||||
|
loader: 'css-loader', |
||||||
|
options: {} |
||||||
|
}, |
||||||
|
{ |
||||||
|
loader: 'postcss-loader', |
||||||
|
options: { |
||||||
|
plugins: () => [autoprefixer()] |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
loader: 'less-loader', |
||||||
|
options: { |
||||||
|
javascriptEnabled: true |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
// 解析图片资源
|
||||||
|
{ |
||||||
|
test: /\.(png|svg|jpg|gif)$/, |
||||||
|
use: [ |
||||||
|
'file-loader' |
||||||
|
] |
||||||
|
}, |
||||||
|
// 解析 字体
|
||||||
|
{ |
||||||
|
test: /\.(woff|woff2|eot|ttf|otf)$/, |
||||||
|
use: [ |
||||||
|
'file-loader' |
||||||
|
] |
||||||
|
}, |
||||||
|
// 解析数据资源
|
||||||
|
{ |
||||||
|
test: /\.(csv|tsv)$/, |
||||||
|
use: [ |
||||||
|
'csv-loader' |
||||||
|
] |
||||||
|
}, |
||||||
|
// 解析数据资源
|
||||||
|
{ |
||||||
|
test: /\.xml$/, |
||||||
|
use: [ |
||||||
|
'xml-loader' |
||||||
|
] |
||||||
|
}, |
||||||
|
// 解析 MakeDown 文件
|
||||||
|
{ |
||||||
|
test: /\.md$/, |
||||||
|
use: [ |
||||||
|
'html-loader', |
||||||
|
'markdown-loader' |
||||||
|
] |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
resolve: { |
||||||
|
// 设置别名
|
||||||
|
alias: { |
||||||
|
src: appSrc, |
||||||
|
utils: path.resolve(__dirname, '../src/utils'), |
||||||
|
pages: path.resolve(__dirname, '../src/pages'), |
||||||
|
components: path.resolve(__dirname, '../src/components') |
||||||
|
}, |
||||||
|
// 设置模块查找范围
|
||||||
|
modules: [path.resolve(__dirname, '../node_modules')] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
const path = require('path'); |
||||||
|
const webpack = require('webpack'); |
||||||
|
const merge = require('webpack-merge'); |
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); |
||||||
|
const common = require('./webpack.common'); |
||||||
|
|
||||||
|
const appPublic = path.resolve(__dirname, '../public'); |
||||||
|
|
||||||
|
const config = merge(common, { |
||||||
|
mode: 'development', |
||||||
|
devtool: 'inline-source-map', |
||||||
|
devServer: { |
||||||
|
// 作为服务器发布的目录
|
||||||
|
contentBase: appPublic, |
||||||
|
// 热加载
|
||||||
|
hot: true, |
||||||
|
// host 地址,设置成 0.0.0.0 才能在移动端使用 ip 地址访问到
|
||||||
|
host: '0.0.0.0', |
||||||
|
// 端口号
|
||||||
|
port: 8000, |
||||||
|
historyApiFallback: true, |
||||||
|
// 是否在浏览器蒙层展示错误信息
|
||||||
|
overlay: true, |
||||||
|
inline: true, |
||||||
|
// 展示的统计信息
|
||||||
|
stats: 'errors-only', |
||||||
|
// 配置代理
|
||||||
|
proxy: { |
||||||
|
'/api': { |
||||||
|
changeOrigin: true, |
||||||
|
target: 'https://easy-mock.com/mock/5c2dc9665cfaa5209116fa40/example', |
||||||
|
pathRewrite: { |
||||||
|
'^/api/': '/' |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
plugins: [ |
||||||
|
// 热加载插件
|
||||||
|
new webpack.HotModuleReplacementPlugin(), |
||||||
|
// 提取 css 文件
|
||||||
|
new MiniCssExtractPlugin({ |
||||||
|
filename: 'public/styles/[name].css', |
||||||
|
chunkFilename: 'public/styles/[name].chunk.css' |
||||||
|
}) |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
module.exports = config; |
@ -0,0 +1,95 @@ |
|||||||
|
const webpack = require('webpack'); |
||||||
|
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); |
||||||
|
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); |
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); |
||||||
|
const CleanWebpackPlugin = require('clean-webpack-plugin'); |
||||||
|
const merge = require('webpack-merge'); |
||||||
|
const common = require('./webpack.common'); |
||||||
|
|
||||||
|
const config = merge(common, { |
||||||
|
mode: 'production', |
||||||
|
devtool: 'hidden-source-map', |
||||||
|
plugins: [ |
||||||
|
// 提取 css 文件
|
||||||
|
new MiniCssExtractPlugin({ |
||||||
|
filename: 'public/styles/[name].[contenthash:8].css', |
||||||
|
chunkFilename: 'public/styles/[name].[contenthash:8].chunk.css' |
||||||
|
}), |
||||||
|
// 区分环境
|
||||||
|
new webpack.DefinePlugin({ |
||||||
|
// 定义 NODE_ENV 环境变量为 production
|
||||||
|
'process.env': { |
||||||
|
NODE_ENV: JSON.stringify('production') |
||||||
|
} |
||||||
|
}), |
||||||
|
// 清理 dist 文件,2.0。0 版本之后不需要设置参数就可以自动清除打包生成的目录
|
||||||
|
new CleanWebpackPlugin() |
||||||
|
], |
||||||
|
optimization: { |
||||||
|
// 打包压缩js/css文件
|
||||||
|
minimizer: [ |
||||||
|
new UglifyJsPlugin({ |
||||||
|
uglifyOptions: { |
||||||
|
compress: { |
||||||
|
// 在UglifyJs删除没有用到的代码时不输出警告
|
||||||
|
warnings: false, |
||||||
|
// 删除所有的 `console` 语句,可以兼容ie浏览器
|
||||||
|
drop_console: true, |
||||||
|
// 内嵌定义了但是只用到一次的变量
|
||||||
|
collapse_vars: true, |
||||||
|
// 提取出出现多次但是没有定义成变量去引用的静态值
|
||||||
|
reduce_vars: true, |
||||||
|
}, |
||||||
|
output: { |
||||||
|
// 最紧凑的输出
|
||||||
|
beautify: false, |
||||||
|
// 删除所有的注释
|
||||||
|
comments: false, |
||||||
|
} |
||||||
|
} |
||||||
|
}), |
||||||
|
// 压缩 CSS 代码
|
||||||
|
new OptimizeCSSAssetsPlugin({}) |
||||||
|
], |
||||||
|
// 拆分公共模块
|
||||||
|
splitChunks: { |
||||||
|
cacheGroups: { |
||||||
|
styles: { |
||||||
|
name: 'styles', |
||||||
|
test: /\.(css|less)/, |
||||||
|
chunks: 'all', |
||||||
|
enforce: true, |
||||||
|
// 表示是否使用已有的 chunk
|
||||||
|
reuseExistingChunk: true
|
||||||
|
}, |
||||||
|
commons: { |
||||||
|
name: 'commons', |
||||||
|
chunks: 'initial', |
||||||
|
minChunks: 2, |
||||||
|
reuseExistingChunk: true |
||||||
|
}, |
||||||
|
vendors: { |
||||||
|
name: 'vendors', |
||||||
|
test: /[\\/]node_modules[\\/]/, |
||||||
|
priority: -10, |
||||||
|
reuseExistingChunk: true |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
// 为每个仅含有 runtime 的入口起点添加一个额外 chunk
|
||||||
|
runtimeChunk: true |
||||||
|
}, |
||||||
|
// 性能提醒
|
||||||
|
performance: { |
||||||
|
hints: false |
||||||
|
}, |
||||||
|
// 统计信息展示
|
||||||
|
stats: { |
||||||
|
modules: false, |
||||||
|
children: false, |
||||||
|
chunks: false, |
||||||
|
chunkModules: false |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
module.exports = config; |
Loading…
Reference in new issue