Skip to content

Latest commit

 

History

History
424 lines (338 loc) · 17 KB

File metadata and controls

424 lines (338 loc) · 17 KB

Dimina 能力参考指南

语法差异

Vue 作为底层的渲染框架,自然会与小程序的语法存在一定的差异。这些差异点需要我们在框架中进行适配,或者要求业务代码做些许的改造,以实现无缝迁移。例如:

相比微信小程序,具有以下语法和实现差异:

  • 具名插槽的显示逻辑

    在小程序中,具名插槽可以同名且能同时渲染显示,而 Vue 的插槽机制会默认覆盖同名插槽。对此,需要为小程序的插槽机制设计一套适配逻辑。比如 <text slot="info">成功</text><text slot="info">失败</text>,后面的文案不会显示。

  • 组件属性的默认值

    小程序中,组件属性如果为空字符串,会默认解析为 false;而在 Vue 中,空字符串会被解析为 true。这种行为差异需要在属性处理逻辑中进行适配。 另外针对字符串类型的组件属性,如果未赋值,微信小程序会处理成空字符串(伴有提示:received type-uncompatible value: expected <String> but get null value. Use empty string instead.),但是星河不会处理而是直接透传,这一点请注意。

  • 循环内的访问限制

    在小程序中,wx:for 标签用于在元素上直接进行循环操作,并允许直接在该元素上使用 wx:if 直接访问循环实例的属性。Vue 的 v-for 不支持这个特性,需要修改访问属性的方法移动到下一级节点。

组件列表

组件
block
button
checkbox
checkbox-group
cover-image
cover-view
form
icon
image
input
label
movable-area
movable-view
navigation-bar
navigator
picker
picker-view
picker-view-column
progress
radio
radio-group
rich-text
scroll-view
slider
slot
swiper
swiper-item
switch
template
text
textarea
view
web-view
wxs
include
import

说明:

  • 该列表包含运行时内置组件,以及编译期支持的 WXML 模板标签(如 slottemplatewxsincludeimport)。
  • 同层渲染组件暂未支持(Android/iOS)。
  • tabBar 暂未支持(Android/iOS/Harmony)。

模板语法支持

能力 支持说明
slot 支持默认插槽、具名插槽,以及 slot="{{name}}" 形式的动态插槽。具名插槽会转换为 Vue 插槽语法。
template 支持通过 <template name="..."> 定义模板,并通过 <template is="..." data="..."> 使用模板。模板内容会在编译期收集并注入。
wxs 支持内联 WXS 和 src 外链 WXS;支持 WXS 内部 require 相对路径依赖,npm 组件内的 WXS 路径会做适配。
include 支持将目标 WXML/DDML 文件中除 templatewxsdds 外的内容内联到当前位置;include 节点上的条件属性会保留并包裹到生成节点上。
import 支持导入目标 WXML/DDML 文件中的 template 与相关 WXS 依赖,导入节点本身会在编译期移除。

自定义全局 API 命名空间

Dimina 支持宿主应用注册自定义的全局 API 命名空间,使小程序可以通过自定义前缀(如 custom.xxx())调用 API,等同于 wx.xxx() 的效果。

使用场景

适用于以下情况:

  • 希望小程序使用品牌专属的 API 命名空间(如 myapp.xxx
  • 需要与现有小程序代码保持兼容性的同时,提供自有品牌标识
  • 多租户场景下,不同宿主应用可配置不同的命名空间

宿主接入方式

Web(JavaScript)

import { AppManager } from '@dimina/container'

// 在初始化应用前配置
AppManager.setup({ apiNamespaces: ['qd', 'myapp'] })

Android

val config = Dimina.DiminaConfig.Builder()
    .addApiNamespace("myapp")
    .build()
    
Dimina.getInstance().init(context, config)

iOS

DMPAppManager.sharedInstance().setup(apiNamespaces: ["myapp"])

HarmonyOS

DMPApp.init(context, { apiNamespaces: ["myapp"] })

API 列表

分类 API 名称 Android iOS Harmony Web
基础 env
canIUse
基础 - 系统 openSystemBluetoothSetting
getWindowInfo
getSystemSetting
getSystemInfoSync
getSystemInfoAsync
getSystemInfo
路由 reLaunch
redirectTo
navigateTo
navigateBack
界面 - 交互 showToast
showModal
showLoading
showActionSheet
hideToast
hideLoading
界面 - 导航栏 setNavigationBarTitle
setNavigationBarColor
界面 - 滚动 pageScrollTo
界面 - 菜单 getMenuButtonBoundingClientRect
界面 - 动画 createAnimation
WXML createSelectorQuery
createIntersectionObserver
网络 request
downloadFile
uploadFile
数据缓存 setStorageSync
getStorageSync
removeStorageSync
clearStorageSync
setStorage
getStorage
removeStorage
clearStorage
getStorageInfoSync
getStorageInfo
媒体 - 图片 saveImageToPhotosAlbum
previewImage
compressImage
chooseImage
媒体 - 视频 chooseMedia
设备 - 联系人 chooseContact
addPhoneContact
设备 - 剪贴板 setClipboardData
getClipboardData
设备 - 震动 vibrateShort
vibrateLong
设备 - 键盘 hideKeyboard
设备 - 网络 getNetworkType
设备 - 电话 makePhoneCall
第三方扩展 extBridge
extOnBridge
extOffBridge

说明:

  • "✓" 表示支持该平台。
  • "□" 表示当前不支持。
  • "✗" 表示明确不支持该平台。

第三方扩展 Bridge

第三方扩展 Bridge 允许宿主 App 向小程序暴露自定义的 native 能力,小程序通过 wx.extBridgewx.extOnBridgewx.extOffBridge 三个 API 与之通信,无需修改框架核心代码。

通信模型

小程序 JS
  │  wx.extBridge / wx.extOnBridge / wx.extOffBridge
  ▼
Service 逻辑层(JS)
  │  invokeAPI → container
  ▼
Container(Android / iOS / Harmony / Web)
  │  路由到已注册的 ExtModuleHandler
  ▼
宿主 Native 模块

wx.extBridge

用途:向指定 native 模块发起一次性调用,支持异步回调。

参数

参数 类型 必填 说明
module string 目标模块名,须与宿主注册时一致
event string 事件名称
data object 传递给模块的参数,默认 {}
success function 调用成功的回调
fail function 调用失败的回调
complete function 调用结束(无论成功/失败)的回调

示例

wx.extBridge({
  module: 'UserModule',
  event: 'getUserInfo',
  data: { uid: '001' },
  success(res) {
    console.log('用户信息:', res)
  },
  fail(err) {
    console.error('获取失败:', err.errMsg)
  },
})

wx.extOnBridge

用途:订阅 native 模块的持续事件推送(如传感器数据、登录状态变化等)。每次事件触发时 callBack 都会被调用,直到主动调用 wx.extOffBridge 或小程序销毁为止。

注意module 不能为空,也不能为保留名 DMServiceBridgeModule

参数

参数 类型 必填 说明
module string 目标模块名
event string 事件名称
callBack function 每次事件推送时触发的回调函数
isSustain boolean 是否持续订阅,默认 true

示例

wx.extOnBridge({
  module: 'SensorModule',
  event: 'onAccelerometer',
  callBack(res) {
    console.log('加速度数据:', res)
  },
})

wx.extOffBridge

用途:取消 wx.extOnBridge 建立的持续订阅。

注意module 不能为空,也不能为保留名 DMServiceBridgeModule

参数

参数 类型 必填 说明
module string 目标模块名
event string 事件名称

示例

wx.extOffBridge({
  module: 'SensorModule',
  event: 'onAccelerometer',
})

宿主接入:注册 Native 模块

宿主只需调用对应平台的注册 API,实现一个处理函数即可。同一个处理函数同时承载 extBridge(一次性)和 extOnBridge(持续订阅)两种场景:

  • 一次性调用:执行后调用 success / fail,函数返回 void / null / nil
  • 持续订阅:启动事件监听,返回取消函数;框架在 extOffBridge 或小程序销毁时自动调用。

Web(JavaScript)

import { AppManager } from '@dimina/container'

AppManager.registerExtModule('UserModule', ({ event, data, success, fail }) => {
  if (event === 'getUserInfo') {
    // 一次性调用
    fetchUser(data.uid).then(res => success(res)).catch(err => fail({ errMsg: err.message }))
    return  // 无需返回取消函数
  }

  if (event === 'onStatusChange') {
    // 持续订阅:返回取消函数
    const timer = setInterval(() => success({ status: getStatus() }), 1000)
    return () => clearInterval(timer)
  }

  fail({ errMsg: `UserModule: unknown event "${event}"` })
})

Android

Dimina.getInstance().registerExtModule("UserModule") { event, data, callback ->
    when (event) {
        "getUserInfo" -> {
            val uid = data.optString("uid")
            val info = fetchUserSync(uid)          // 同步或异步均可
            callback.onSuccess(JSONObject().apply {
                put("name", info.name)
                put("uid", info.uid)
            })
            null  // 一次性调用,无需取消函数
        }
        "onStatusChange" -> {
            // 持续订阅:返回取消订阅的 Runnable
            val job = statusObserver.observe { status ->
                callback.onSuccess(JSONObject().apply { put("status", status) })
            }
            Runnable { job.cancel() }
        }
        else -> {
            callback.onFail(JSONObject().apply {
                put("errMsg", "UserModule: unknown event \"$event\"")
            })
            null
        }
    }
}

Harmony

import { DMPMap } from '@dimina/dimina'

app.registerExtModule('UserModule', (event, data, callback) => {
  if (event === 'getUserInfo') {
    // 一次性调用
    const uid = data.get('uid') as string
    fetchUser(uid).then(info => {
      callback.onSuccess(new DMPMap({ name: info.name, uid: info.uid }))
    }).catch(err => {
      callback.onFail(new DMPMap({ errMsg: err.message }))
    })
    return null  // 一次性调用,无需取消函数
  }

  if (event === 'onStatusChange') {
    // 持续订阅:返回取消函数
    const timer = setInterval(() => {
      callback.onSuccess(new DMPMap({ status: getStatus() }))
    }, 1000)
    return () => clearInterval(timer)
  }

  callback.onFail(new DMPMap({ errMsg: `UserModule: unknown event "${event}"` }))
  return null
})

iOS

DMPAppManager.sharedInstance().registerExtModule("UserModule") { event, data, callback in
    switch event {
    case "getUserInfo":
        let uid = data["uid"] as? String ?? ""
        fetchUser(uid: uid) { info in
            callback.onSuccess(DMPMap(["name": info.name, "uid": info.uid]))
        }
        return nil  // 一次性调用

    case "onStatusChange":
        // 持续订阅:返回取消闭包
        let token = statusObserver.observe { status in
            callback.onSuccess(DMPMap(["status": status]))
        }
        return { statusObserver.remove(token) }

    default:
        callback.onFail(DMPMap(["errMsg": "UserModule: unknown event \"\(event)\""]))
        return nil
    }
}

生命周期说明

时机 行为
wx.extOnBridge 调用 框架调用宿主处理函数,保存返回的取消函数
wx.extOffBridge 调用 框架执行取消函数,清除订阅记录
重复订阅同一事件 框架自动先取消旧订阅,再建立新订阅
小程序销毁 框架执行所有未取消的订阅的取消函数,防止泄漏