Weex开发中,实现Vue组件导入Android原生控件,实现Android控件与vue组件的相互通信,以及通信回调

Vue组件导入原生组件的流程

  1. 创建原生组件 需继承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);
    }
}
  1. 在application中注册原生组件,说明组件名,和组件类型。
WXSDKEngine.registerComponent("androidText", AndroidText::class.java)
  1. 在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>

Vue组件导入原生模块的流程

开发中我们可能需要调用原生的一些方法,比如调用相机,请求权限,存储数据到sharepreferences等,这些不是View的UI界面,那么我们需要通过定义模块的方式来实现。

比如:我们想获取到手机内安装的所有App

  1. 创建模块需要继承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);
    }
}
  1. application中注册模块
WXSDKEngine.registerModule("applist", AndroidAppListModule::class.java)
  1. 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组件通知Vue父组件

我们在一个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使用原生组件时,很多逻辑都在原生组件中处理,如果我们希望原生组件主动发送事件通知给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>

Vue组件调用原生组件的方法并获取到数据

原生组件提供方法:

@JSMethod
public void getTestData(String params, JSCallback callback) {
  // 根据传入的参数执行相应的逻辑
  ......
  // 返回的结果必须为Map
  Map<String, Object> maper = new HashMap();
  maper.push("key", value)
  callback.invoke(maper)
}

你可能感兴趣的:(vue.js,android,前端)