最近開發一個項目,原本是用的RN開發,後來打算三端統一,後來決定用VUE開發,是以涉及到一些Vue和原生互動的地方,做一下筆記~~
先直接上Vue代碼
<template>
<div class="page-box">
<div class="page-content">
<div class="page-bg">
<div class="page-login-head">
<img class="head-img" src="./images/head.png"/>
<div class="head-text" @click="goLogin">
{{userMsg}}
</div>
</div>
</div>
<!-- 我的賬單 -->
<div class="mine-item mine-item-head" @click="gotoBill">
<div class="mine-item-content mine-item-content-bottom">
<div class="left">
<img class="item-img-size" src="./images/bill.png"/>
<span class="item-text">我的賬單</span>
</div>
<span class="icon-right"></span>
</div>
</div>
<!-- 我的銀行卡 -->
<div class="mine-item">
<div class="mine-item-content">
<div class="left">
<img src="./images/bankcard.png" style="width:5vw; height:4.1vw"/>
<span class="item-text">我的銀行卡</span>
</div>
<span class="icon-right"></span>
</div>
</div>
<!-- 更改交易密碼 -->
<div class="mine-item mine-item-head">
<div class="mine-item-content mine-item-content-bottom">
<div class="left">
<img class="item-img-size" src="./images/change_psw.png"/>
<span class="item-text">更改交易密碼</span>
</div>
<span class="icon-right"></span>
</div>
</div>
<!-- 意見與回報 -->
<div class="mine-item" @click="gotoFeedback">
<div class="mine-item-content mine-item-content-bottom">
<div class="left">
<img style="width:4.8vw; height:5vw" src="./images/opinion.png"/>
<span class="item-text">意見與回報</span>
</div>
<span class="icon-right"></span>
</div>
</div>
<!-- 幫助中心 -->
<div class="mine-item" @click="gotoHelpCenter">
<div class="mine-item-content mine-item-content-bottom">
<div class="left">
<img style="width:5vw; height:5vw" src="./images/help.png"/>
<span class="item-text">幫助中心</span>
</div>
<span class="icon-right"></span>
</div>
</div>
<!-- 免責聲明 -->
<div class="mine-item" @click="ocrtest">
<div class="mine-item-content">
<div class="left">
<img style="width:5vw; height:5vw" src="./images/exemption.png"/>
<span class="item-text">免責聲明</span>
</div>
<span class="icon-right"></span>
</div>
</div>
<!-- 關于我們 -->
<div class="mine-item mine-item-head" @click="gotoAboutUs">
<div class="mine-item-content">
<div class="left">
<img style="width:5vw; height:5vw" src="./images/about.png"/>
<span class="item-text">關于我們</span>
</div>
<span class="icon-right"></span>
</div>
</div>
</div>
<TabBar></TabBar>
</div>
</template>
<script>
import TabBar from '@/components/tabBar/TabBar'
import { mapGetters } from 'vuex'
export default {
components: { TabBar },
data () {
return {
userMsg: '登陸/注冊'
}
},
mounted () {
this.initView()
},
methods: {
initView () {
if (this.ifLogin) {
this.userMsg = this.userInfo.cellphone
} else {
this.userMsg = '登陸/注冊'
}
},
goLogin () {
if (!this.ifLogin) {
this.$bridge.push({ name: 'login' })
}
},
gotoAboutUs () {
let params = {
jumpUrl: 'http://192.168.1.38:8080/aboutus',
title: '關于我們'
}
window.android.callAndroid(JSON.stringify(params))
},
gotoFeedback () {
this.$bridge.push({ name: 'feedback' })
},
gotoHelpCenter () {
this.$bridge.push({ name: 'helpcenter' })
},
gotoBill () {
this.$bridge.push({ name: 'bill' })
},
ocrtest () {
let params = {
jumpUrl: 'http://192.168.1.38:8080/userinfo',
title: 'ORC調試'
}
window.android.callAndroid(JSON.stringify(params))
}
},
computed: {
...mapGetters(['userInfo', 'ifLogin'])
}
}
</script>
<style scoped>
.page-box { position: relative; min-height: 100%; background: #F5F5F5}
.page-content {
position: relative;
z-index: 0;
padding-bottom :190px;
}
.page-bg {
width: 100%; height: 380px;
background: linear-gradient(32deg,rgba(46,42,50,1) 0%,rgba(78,65,80,1) 100%);
display :flex;
justify-content :center;
align-items :center;
}
.page-box .page-bg .page-login-head {
display :flex;
flex-direction :column;
align-items :center;
}
.page-box .page-bg .page-login-head .head-img {
width: 124px; height: 124px;
}
.page-box .page-bg .page-login-head .head-text{
margin-top :15px;
font-size :28px;
color :#FFFFFF;
}
.mine-item-head {
margin-top :20px;
}
.mine-item {
background-color :#FFFFFF;
height :100px;
width :100%
padding-left :39px;
}
.mine-item .mine-item-content-bottom {
border-bottom-width :1px;
border-style :solid;
border-bottom-color :#DDDDDD;
}
.mine-item .mine-item-content {
display :flex;
height :100px;
width :100%
align-items :center;
justify-content :space-between;
}
.mine-item .left{
display :flex;
}
.item-text {
font-size :28px;
color :#333333;
margin-left :20px;
align-self :center;
}
.item-img-size {
width :31px;
height :38px;
}
.icon-right {
width: 36px; height: 36px;
background: url('./images/arrow_grey_right.png') no-repeat center center;
background-size: 19px 34px;
margin-right :30px;
}
</style>
這是一個個人中心完整VUE界面的代碼,包括樣式,點選事件,重點看這裡就行
vue和原生互動的原理和Html裡面js和原生互動一樣,都是通過js代碼來實作,都需要把原生方法挂載到window上面
是以這裡,這裡的params是需要傳遞給原生的資料,JSON.stringify(params)的作用是,必須把資料轉為json格式,原生才能收到,否則接收不到,其中callAndroid()是原生的方法,window後面的android是原生代碼裡面申明的一個标志
原生代碼如下
public class JsBridgeForMain {
private static final String TAG = "JsBridgeForMain";
private Handler deliver = new Handler(Looper.getMainLooper());
private AgentWeb agent;
private Context context;
private OnNativeDataGetInterface mOnNativeDataGetInterface;
public JsBridgeForMain(AgentWeb agent, Context context) {
this.agent = agent;
this.context = context;
}
public JsBridgeForMain(AgentWeb agent, Context context, OnNativeDataGetInterface onNativeDataGetInterface) {
this.agent = agent;
this.context = context;
mOnNativeDataGetInterface = onNativeDataGetInterface;
}
@JavascriptInterface
public void showMsg(final String obj) {
Log.e(TAG, "showMsg: " + obj);
}
@JavascriptInterface
public void jumpAndroid(final String obj) {
Log.e(TAG, "jumpAndroid: " + obj);
final Map<String, Object> params = AppUtils.getMap(obj);
assert params != null;
context.startActivity(new Intent(context, OcrCallbackActivity.class)
.putExtra(PrefKeys.EXTRA_URL, params.get("href").toString()));
}
@JavascriptInterface
public void callAndroid(final String obj) {
deliver.post(new Runnable() {
@Override
public void run() {
final Map<String, Object> params = AppUtils.getMap(obj);
assert params != null;
Log.e(TAG, "name: " + params);
if ("OCR".equals(params.get("name"))) {
Gson gson = new Gson();
String jsonString = gson.toJson(params.get("data")).replace("\\", "");
jsonString = jsonString.substring(1, jsonString.length() - 1);
OcrEntity ocrEntity = gson.fromJson(jsonString, OcrEntity.class);
OcrCallbackActivity.msgId = params.get("msgId").toString();
if (mOnNativeDataGetInterface != null)
mOnNativeDataGetInterface.onDataGot(ocrEntity);
Log.e(TAG, "ocrEntity: " + params);
}
if ("phoneContact".equals(params.get("name"))) {
OcrCallbackActivity.msgId = params.get("msgId").toString();
mOnNativeDataGetInterface.onAddressCalled();
}
if ("GPS".equals(params.get("name"))){
OcrCallbackActivity.msgId = params.get("msgId").toString();
mOnNativeDataGetInterface.onGpsCalled();
}
if ("GPSStatus".equals(params.get("name"))){
OcrCallbackActivity.msgId = params.get("msgId").toString();
mOnNativeDataGetInterface.onGpsStatus();
}
}
});
}
}
其中原生調用JS方法代碼如下
Map<String, String> contactMap = new HashMap<>();
contactMap.clear();
contactMap.put("phone", phoneNum);
contactMap.put("msgId", msgId);
contactMap.put("name", contactName);
Gson gson = new Gson();
String contactPersonData = gson.toJson(contactMap);
agentWeb.getJsAccessEntrace().quickCallJs("webViewBridge.callback_('" + contactPersonData + "')");
我使用的一個webview的中間件名字叫做AgentWeb,具體使用方法可以看github,
這裡的
webViewBridge.callback_('" + contactPersonData + "')" 為js中的方法,contactPersonData 為原生的json資料
webViewBridge.callback_是我們自己封裝的一個vue的連接配接橋可以忽略也可以吧這部分直接改成js裡具體的方法比如前面vue代碼中method裡面的任意一個方法