数据交互实现参照(本方案以vue为例介绍):
https://blog.csdn.net/qq_44393166/article/details/105097286
https://blog.csdn.net/lyyo_cd/article/details/84304864
https://www.jianshu.com/p/f63bab6c90e0
首先通过以下方法确认登录设备为Android还是iOS,如果是iOS可进一步判断是否为iPad
(由于有些iPad内核显示使用了macOS系统,所以这里用触点区分,如有更好的方案可替代)
// iPad可能装载Mac OS
export function isIPad() {
var userAgentInfo = navigator.userAgent
var Agents = ['iPad','Mac']
var flag = false
var v = 0
for (; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
// iPad触点为5 Mac为0
if (navigator.maxTouchPoints==0) {
flag = "Mac"
}else{
flag = "iPad"
}
break
}
}
return flag
}
export function mobileInfo() {
var u = navigator.userAgent
if (u.indexOf('Android') > -1 || u.indexOf('Linux') > -1) {
//安卓手机
return '安卓'
} else if (u.indexOf('iPhone') > -1) {
//苹果手机
return '苹果'
} else if (u.indexOf('Windows Phone') > -1) {
//winphone手机
return 'winphone'
}
}
随后可通过以下方法完成与安卓、ios的数据互通。
// 访问ios、安卓
const sysInfo = mobileInfo()
const isIPadInfo = isIPad() == 'iPad'
// 调用原生方法(无回调)
export function setFn(methods, params) {
if (params == null) {
if (sysInfo == '安卓') {
window.android[methods]()
}
if (sysInfo == '苹果' || isIPadInfo) {
window.webkit.messageHandlers[methods].postMessage('')
}
} else {
let data = params
if (typeof data !== 'string') data = JSON.stringify(data)
if (sysInfo == '安卓') {
window.android[methods](data)
}
if (sysInfo == '苹果' || isIPadInfo) {
window.webkit.messageHandlers[methods].postMessage(data)
}
}
}
// 调用原生方法(有回调)
export function set(methods, params, fn) {
let fName = methods + 'Jg'
get([{ [fName]: fn }])
if (params == null) {
if (sysInfo == '安卓') {
window.android[methods]()
}
if (sysInfo == '苹果' || isIPadInfo) {
window.webkit.messageHandlers[methods].postMessage()
}
} else {
let data = params
if (typeof data !== 'string') data = JSON.stringify(data)
if (sysInfo == '安卓') {
window.android[methods](data, fName)
}
if (sysInfo == '苹果' || isIPadInfo) {
window.webkit.messageHandlers[methods].postMessage(data, fName)
}
}
}
// 提供方法给原生调用
export function get(fnArr) {
fnArr.forEach(el => {
for (var key in el) {
window[key] = el[key]
}
})
}
因没有找到web访问移动端原生后回调函数写法、这里就模拟了回调函数的方式,即:
采用原生提供的方法名+Jg的方式给原生层定义web提供的方法,并让原生层执行,以达到回调函数的目的。
使用原生方法时,就调用原生方法后边的js逻辑不执行的问题,可采用 上述回调函数 的方式激活方法。
原生调用vue中方法:
methods: {
// 测试方法
ceshi() {
console.log("测试方法1")
},
// 测试方法
ceshi2() {
console.log("测试方法2")
},
},
mounted() {
//暴露方法给安卓、ios
get( [{ ceshi: this.ceshi, ceshi2: this.ceshi2 }])
}
vue中调用原生方法:
methods: {
// 测试方法
ceshi1() {
const _this = this//需要转this
set('callAndroid', { test: '测试' }, function(res) {
alert('接收到的' + res)
})
},
// 测试方法
ceshi2() {
setFn('callAndroid', { test: '测试' })
}
}
第一个参数为原生提供给web的方法名。
第二个参数为传递的参数,不传参时写null。
第三个参数为原生调用的该方法的回调函数。
(setFn没有第三个参数、只有set有)
Android调用web方法:
bridgeJavascript(){
let that = this;
window.WebViewJavascriptBridge.callHandler(
'ceshi1'//与web一起定义的共同方法名
,{} // 参数
,function(res){//web方法返回值
res=JSON.parse(res);
alert(res)
}
)
}
Android提供方法给web调用:
window.WebViewJavascriptBridge.send( //提供方法名为send的方法给web调用
data //需要传递的消息参数
,function(res){ //返回的响应
alert(res)
}
)
iOS调用web方法:
// 调用JS方法
webView.evaluateJavaScript("ceshi1" + "('\(token)')") { (result, err) in
// result是JS返回的值
print(result as? String ?? "" , err.description)
}
iOS提供方法给web调用:
// 提供方法给web调用
func addJsObj(_ key: String, _ value: String) {
wkwebview.evaluateJavaScript("vm.\(key) = \(value)", completionHandler: nil)
}
如果有更方便的写法欢迎来讨论,让我们一起有条不紊的持续进步。
喜欢的话不妨点个小小的赞与关注,您的赞与关注将是我源源不断的前进动力