- 创建原生组件 需继承
WXComponent<原生组件类>
,重写initComponentHostView()
方法
public class AndroidText extends WXComponent<TextView> {
public AndroidText(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) {
super(instance, parent, basicComponentData);
}
// 在init方法中提供控件的实例对象
@Override
protected TextView initComponentHostView(@NonNull Context context) {
TextView textView = new TextView(context);
textView.setTextSize(20);
return textView;
}
// 自定义Vue组件中的属性,但Vue组件属性修改时,会回调这个方法进行处理
@WXComponentProp(name = "androidTextColor")
public void setAndroidTextColor(String colorText) {
getHostView().setText(colorText);
getHostView().setTextColor(Color.parseColor(colorText));
}
// 自定义Vue组件持有实例时,可调用的方法
@JSMethod
public void setSimpleText(String value) {
getHostView().setText(value);
}
}
在application
中注册原生组件,说明组件名,和组件类型。
WXSDKEngine.registerComponent("androidText", AndroidText::class.java)
- 在Vue组建中使用
<template>
<div class="container">
<androidText ref="androidText" :androidTextColor="color" @click="handleTextClicked"/>
div>
template>
<script>
export default {
data () {
return {
color: '#000000'
}
},
methods: {
handleTextClicked () {
this.color = '#FF00FF'
// 调用原生组件的方法
this.$refs.androidText.setSimpleText('Jack')
}
}
}
script>
开发中我们可能需要调用原生的一些方法,比如调用相机,请求权限,存储数据到sharepreferences等,这些不是View的UI界面,那么我们需要通过定义
模块
的方式来实现。
比如:我们想获取到手机内安装的所有App
- 创建模块需要继承
WXModule
,通过@JsMethod
注解来声明可调用的方法, 同时也支持传入回调方法用于接收当模块方法处理完成后的返回值。
public class AndroidAppListModule extends WXModule {
@JSMethod(uiThread = false)
public void getAppList(String total, String callBackId) {
// 首先获取到Android 安装的app列表
JSONArray array = new JSONArray();
List<PackageInfo> packages =
MyApplication.Companion.instanceContext().getPackageManager().getInstalledPackages(0);
for(PackageInfo packageInfo : packages) {
JSONObject obj = new JSONObject();
try {
obj.put("name", packageInfo.applicationInfo
.loadLabel(mWXSDKInstance.getContext().getPackageManager()).toString());
obj.put("packageName", packageInfo.packageName);
array.put(obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
HashMap<String, Object> map = new HashMap<>();
map.put(total, array.toString());
// 将结果回调给vue
WXSDKManager.getInstance().callback(mWXSDKInstance.getInstanceId(), callBackId, map, false);
}
}
- 在
application
中注册模块
WXSDKEngine.registerModule("applist", AndroidAppListModule::class.java)
- Vue中调用模块的方法,同时监听方法处理后的回调结果
<template>
<div class="container">
<text @click="handleTextClicked">{{ textValue }}text>
div>
template>
<script>
export default {
data () {
return {
textValue: 'App列表:'
}
},
methods: {
handleTextClicked () {
// 调用原生模块
weex.requireModule('applist').getAppList('keyName', (result) => {
this.textValue = result.keyName
})
}
}
}
script>
<style>
.container {
flex: 1
}
style>
我们在一个Vue文件中定义了一个组件,组件自己会管理自己的状态,但有时候我们希望子组件的一些交互操作事件能否往上抛,告知父组件,这时需要使用$emit(事件名, 数据)。
比如:我们有一个性别单选框,选中女,那么需要显示女生图标,选中男生,那么要显示男生图标。
<template>
<div class="container">
<div :class="[isSelectedMan ? `selectedItemState` : `noSelectedItemState`]" @click="onItemClicked(true)">
<text :class="[isSelectedMan ? `selectedTextState` : `noSelectedTextState`]">男text>
div>
<div :class="[isSelectedMan ? `noSelectedItemState` : `selectedItemState`]" @click="onItemClicked(false)">
<text :class="[isSelectedMan ? `noSelectedTextState` : `selectedTextState`]">女text>
div>
div>
template>
<script>
export default {
data () {
return {
isSelectedMan: true
}
},
methods: {
onItemClicked (value) {
this.isSelectedMan = value
this.$emit('valueChanged', value)
}
}
}
script>
<style>
.container {
flex-direction: row;
direction: ltr;
justify-content: center;
}
.selectedItemState {
border-radius: 8px;
background-color: #9999ff;
padding: 10px;
margin-left: 60px;
}
.noSelectedItemState {
border-radius: 8px;
border-color: #999999;
border-width: 2px;
margin-left: 60px;
padding: 10px;
}
.selectedTextState {
font-size: 30px;
color: #ffffff;
}
.noSelectedTextState {
font-size: 26px;
color: #666666;
}
style>
<template>
<div class="container">
<image :src="picSrc" style="width:300px;height:300px"/>
<singleSelectBox @valueChanged="onValueChanged"/>
div>
template>
<script>
export default {
data () {
return {
picSrc: '../man.png'
}
},
methods: {
onValueChanged (value) {
this.picSrc = value ? 'man.png' : 'woman.png'
}
}
}
script>
当Vue使用原生组件时,很多逻辑都在原生组件中处理,如果我们希望原生组件主动发送事件通知给Vue组件,
那么就需要在原生组件中使用WXSDKManager.getInstance().fireEvent()
Map maper = new HashMap<String, Object>();
maper.put("keyName", "valueName")
// 分别为managerID, 组件实例, 事件名, 事件所携带的数据(必须Map结构)
WXSDKManager.getInstance().fireEvent(getInstanceId(),getRef(),"eventName",maper);
Vue中对它进行接收
<template>
<div class="container">
<androidText @eventName="handleIt" :text="textValue"/>
div>
template>
<script>
data () {
return {
textValue: ''
}
},
methods: {
handleIt (result) {
// result就是原生传过来的maper
this.textValue = result.keyName // 值为"valueName"
}
}
script>
原生组件提供方法:
@JSMethod
public void getTestData(String params, JSCallback callback) {
// 根据传入的参数执行相应的逻辑
......
// 返回的结果必须为Map
Map<String, Object> maper = new HashMap();
maper.push("key", value)
callback.invoke(maper)
}