Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
unidocs-uni-app-x-zh
提交
7c5a9575
U
unidocs-uni-app-x-zh
项目概览
DCloud
/
unidocs-uni-app-x-zh
通知
144
Star
2
Fork
33
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
9
列表
看板
标记
里程碑
合并请求
11
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
unidocs-uni-app-x-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
9
Issue
9
列表
看板
标记
里程碑
合并请求
11
合并请求
11
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
7c5a9575
编写于
12月 10, 2024
作者:
DCloud_iOS_XHY
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update uts-component-vue.md
上级
2aa5323e
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
543 addition
and
542 deletion
+543
-542
docs/plugin/uts-component-vue.md
docs/plugin/uts-component-vue.md
+543
-542
未找到文件。
docs/plugin/uts-component-vue.md
浏览文件 @
7c5a9575
# uts插件 - 标准模式组件开发
# uts插件 - 标准模式组件开发
> HBuilderX4.31 及以上版本支持
本文重点在于讲述如何在app-android和app-ios上,使用vue组件开发规范封装原生UI封装为 uni-app x 项目使用的UTS组件,供使用者在uvue页面template中以组件的方式调用。
主要思路是将app平台的原生view关联内置
[
native-view
](
../component/native-view.md
)
组件,实现UTS组件的特定功能及UI展示。
## 前置条件
继续阅读文档前,开发者需要了解以下前置条件:
-
了解
`标准模式`
和
`uni-app兼容模式`
的差异,详情参考
[
uts组件开发概述
](
./uts-component.md
)
-
了解
[
uts语法
](
/uts/
)
和
[
uts原生插件
](
uts-plugin.md
)
-
了解
[
vue组件
](
https://uniapp.dcloud.net.cn/tutorial/vue3-components.html
)
-
了解
[
native-view组件
](
../component/native-view.md
)
## UTS插件-标准模式组件目录结构@dir
<pre
v-pre=
""
data-lang=
""
>
<code
class=
"lang-"
style=
"padding:0"
>
┌─components // vue组件代码
| ├─xxx // vue组件名称文件夹 xxx代替组件名称
| ├─xxx.uvue // vue组件uts代码 xxx代替组件名称
├─static // 静态资源
├─utssdk
│ ├─app-android //Android平台目录
│ │ ├─assets //Android原生assets资源目录,可选
│ │ ├─libs //Android原生库目录,可选
│ │ ├─res //Android原生res资源目录,可选
│ │ ├─AndroidManifest.xml //Android原生应用清单文件,可选
│ │ ├─config.json //Android原生配置文件
│ │ ├─index.uts //Android原生插件能力实现,可选
│ ├─app-ios //iOS平台目录
│ │ ├─Frameworks //iOS原生依赖的第三方 framework 依赖库存放目录,可选
│ │ ├─Resources //iOS原生所依赖的资源文件存放目录,可选
│ │ ├─info.plist //iOS原生所需要添加到主 info.plist 文件中的配置文件,可选
│ │ ├─UTS.entitlements //iOS原生所需要添加到主工程 .entitlements 文件中的配置文件,可选
│ │ ├─config.json //iOS原生配置文件
│ │ ├─index.uts //iOS原生插件能力实现,可选
│ ├─web //web平台目录
│ │ └─index.uts
│ └─index.uts // 跨平台插件能力实现,可选
└─package.json // 插件清单文件
</code>
</pre>
如上所示,UTS插件-标准模式组件目录结构与UTS插件基本相同,差别在于components目录,vue组件代码存放components目录下。
其他目录文件详情可参考
[
UTS插件文档
](
https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin.html#%E6%8F%92%E4%BB%B6%E7%9A%84%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84
)
主要思路是将app平台的原生view关联内置
[
native-view
](
../component/native-view.md
)
组件,实现UTS组件的特定功能及UI展示。
## 前置条件
继续阅读文档前,开发者需要了解以下前置条件:
-
了解
`标准模式`
和
`uni-app兼容模式`
的差异,详情参考
[
uts组件开发概述
](
./uts-component.md
)
-
了解
[
uts语法
](
/uts/
)
和
[
uts原生插件
](
uts-plugin.md
)
-
了解
[
vue组件
](
https://uniapp.dcloud.net.cn/tutorial/vue3-components.html
)
-
了解
[
native-view组件
](
../component/native-view.md
)
## UTS插件-标准模式组件目录结构@dir
<pre
v-pre=
""
data-lang=
""
>
<code
class=
"lang-"
style=
"padding:0"
>
┌─components // vue组件代码
| ├─xxx // vue组件名称文件夹 xxx代替组件名称
| ├─xxx.uvue // vue组件uts代码 xxx代替组件名称
├─static // 静态资源
├─utssdk
│ ├─app-android //Android平台目录
│ │ ├─assets //Android原生assets资源目录,可选
│ │ ├─libs //Android原生库目录,可选
│ │ ├─res //Android原生res资源目录,可选
│ │ ├─AndroidManifest.xml //Android原生应用清单文件,可选
│ │ ├─config.json //Android原生配置文件
│ │ ├─index.uts //Android原生插件能力实现,可选
│ ├─app-ios //iOS平台目录
│ │ ├─Frameworks //iOS原生依赖的第三方 framework 依赖库存放目录,可选
│ │ ├─Resources //iOS原生所依赖的资源文件存放目录,可选
│ │ ├─info.plist //iOS原生所需要添加到主 info.plist 文件中的配置文件,可选
│ │ ├─UTS.entitlements //iOS原生所需要添加到主工程 .entitlements 文件中的配置文件,可选
│ │ ├─config.json //iOS原生配置文件
│ │ ├─index.uts //iOS原生插件能力实现,可选
│ ├─web //web平台目录
│ │ └─index.uts
│ └─index.uts // 跨平台插件能力实现,可选
└─package.json // 插件清单文件
</code>
</pre>
如上所示,UTS插件-标准模式组件目录结构与UTS插件基本相同,差别在于components目录,vue组件代码存放components目录下。
其他目录文件详情可参考
[
UTS插件文档
](
https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin.html#%E6%8F%92%E4%BB%B6%E7%9A%84%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84
)
也就是说:
**在components/xxx/xxx.uvue这个uvue组件文件中,定义组件的属性、事件、方法;然后这些属性、方法的具体实现,则调用在utssdk下的uts插件实现。**
## 开发UTS插件-标准模式组件
下面我们以一个例子来讲解标准模式组件的开发。
我们开发一个
`native-button`
组件,目标是把Android和iOS的原生button封装成uvue组件。
Android的原生button会带有水波纹效果。uni-app自带的button组件并没有这个效果。
该组件计划提供一个 text属性,用于显示按钮的文字;有一个buttonTap事件用于处理点击。
let's go!
### 新建标准模式组件
HBuilder X 选中你的项目,项目根目录选中
`uni_modules`
目录,右键选择新建
`uni_modules`
插件,弹窗后分类选择 “UTS插件-标准模式组件”,填写组件名称,以下均以
`native-button`
为例
![](
https://web-ext-storage.dcloud.net.cn/doc/uts/uts_plugin/create-uts-vue-component.png
)
创建完毕 HBuilder X 会自动创建一批模版文件,参考:
[
前述目录结构
](
#dir
)
### 标准模式组件功能实现
#### 添加 native-view
上一步创建标准模式组件(名称为native-button)后,HBuilder X 会自动创建components/native-button/native-button.uvue文件。
这个文件是一个标准的uvue组件,符合easycom规范,在这个文件编写组件的属性、事件。
首先在该文件的template区添加
[
native-view 组件
](
../component/native-view.md
)
```
html
<template>
<native-view></native-view>
</template>
```
#### native-view 与 原生对象关联
native-view 组件的用途就是提供一个占位view,并且可以和原生的view进行绑定。
native-view 组件初始化会触发 @init 事件,如下代码在init时创建原生NativeButton对象,在其内部实现了view的绑定。
[
NativeButton
](
#utscode
)
是在utssdk目录的app-android和app-ios目录下的index.uts中定义的原生对象。NativeButton对象内部处理原生view与native-view绑定关联业务。
native-button.uvue代码中用NativeButton对象调用插件相关的API。
native-view 组件在uts中对应着UniNativeViewElement对象,将 UniNativeViewElement 传递给NativeButton对象,进行关联绑定。
::: preview
> 组合式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
></native-view>
</template>
<script
setup
lang=
"uts"
>
//引入 NativeButton 原生对象
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
let
button
:
NativeButton
|
null
=
null
//native-view初始化时触发此方法
function
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 传递给NativeButton对象
button
=
new
NativeButton
(
e
.
detail
.
element
);
}
</script>
```
> 选项式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
></native-view>
</template>
<script
lang=
"uts"
>
//引入 NativeButton 原生对象
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
export
default
{
data
()
{
return
{
button
:
null
as
NativeButton
|
null
}
},
methods
:
{
//native-view初始化时触发此方法
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 实例化NativeButton将element以构造参数传递给NativeButton对象
this
.
button
=
new
NativeButton
(
e
.
detail
.
element
);
}
}
}
</script>
```
:::
#### 组件声明方法
vue中,为组件定义方法很简单,但分选项式和组合式。
选项式中,在 methods 节点中添加updateText方法;组合式中,直接定义function updateText。参考vue文档
[
页面调用vue组件方法
](
https://doc.dcloud.net.cn/uni-app-x/vue/component.html#page-call-component-method
)
native-button组件使用者可调用该updateText方法中更新native-button文字。
但在vue组件的updateText方法中,需再次调用NativeButton的updateText方法,在原生插件中实现按钮文字更新。
::: preview
> 组合式 API
```
ts
<
script
setup
lang
=
"
uts
"
>
//引入 NativeButton 原生对象
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
let
button
:
NativeButton
|
null
=
null
//声明方法
function
updateText
(
value
:
string
)
{
button
?.
updateText
(
value
)
}
<
/script>
```
> 选项式 API
```
ts
methods
:
{
//对外函数
updateText
(
value
:
string
)
{
this
.
button
?.
updateText
(
value
)
}
}
```
:::
#### 组件声明属性props
native-button 声明组件属性props,例如native-button的文案信息text属性,按vue组件规范监听到text属性更新,通过NativeButton对象驱动更新原生view属性,在components/native-button/native-button.uvue编写如下代码,具体参考vue文档
[
vue组件Props规范
](
https://cn.vuejs.org/guide/typescript/composition-api#typing-component-props
)
::: preview
> 组合式 API
```
html
<script
setup
lang=
"uts"
>
//声明属性
const
props
=
defineProps
<
{
text
:
string
}
>
()
//声明方法
function
updateText
(
value
:
string
)
{
button
?.
updateText
(
value
)
}
//监听属性变化
watchEffect
(()
=>
{
// console.log("watchEffect "+props.text)
const
text
=
props
.
text
updateText
(
text
)
})
</script>
```
> 选项式 API
```
html
<script
lang=
"uts"
>
export
default
{
props
:
{
"
text
"
:
{
type
:
String
,
default
:
''
}
},
watch
:
{
"
text
"
:
{
handler
(
newValue
:
string
,
oldValue
:
string
)
{
this
.
value
=
newValue
this
.
button
?.
updateText
(
this
.
value
)
},
immediate
:
true
},
},
}
</script>
```
:::
#### 组件声明事件
native-button 声明事件,例如原生组件触发点击事件@buttonTap, NativeButton对象通过 UniNativeViewElement 的 dispatchEvent 函数触发native-view的 @customClick 自定义事件。native-button.uvue监听native-view的 @customClick 自定义事件实现emit触发声明事件,具体参考
[
vue组件事件规范
](
https://cn.vuejs.org/guide/typescript/composition-api#typing-component-emits
)
::: preview
> 组合式 API
```
html
<template>
<native-view
@
customClick=
"ontap"
></native-view>
</template>
<script
setup
lang=
"uts"
>
//声明事件
const
emit
=
defineEmits
<
{
(
e
:
"
buttonTap
"
,
event
:
UniNativeViewEvent
)
:
void
}
>
()
function
ontap
(
e
:
UniNativeViewEvent
)
{
emit
(
"
buttonTap
"
,
e
)
}
</script>
```
> 选项式 API
```
html
<template>
<native-view
@
customClick=
"ontap"
></native-view>
</template>
<script
lang=
"uts"
>
export
default
{
methods
:
{
ontap
(
e
:
UniNativeViewEvent
)
{
this
.
$emit
(
"
buttonTap
"
,
e
)
}
}
}
</script>
```
:::
**注意:**
目前自定义事件参数仅支持
[
UniNativeViewEvent
](
../component/native-view#uninativeviewevent
)
native-button/components/native-button/native-button.uvue 最终代码如下:
::: preview
> 组合式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
@
customClick=
"ontap"
></native-view>
</template>
<script
setup
lang=
"uts"
>
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
let
button
:
NativeButton
|
null
=
null
//声明属性
const
props
=
defineProps
<
{
text
:
string
}
>
()
//声明事件
const
emit
=
defineEmits
<
{
(
e
:
"
buttonTap
"
,
event
:
UniNativeViewEvent
)
:
void
}
>
()
//声明方法
function
updateText
(
value
:
string
)
{
button
?.
updateText
(
value
)
}
//监听属性变化
watchEffect
(()
=>
{
const
text
=
props
.
text
updateText
(
text
)
})
//native-view初始化时触发此方法
function
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 传递给NativeButton对象
button
=
new
NativeButton
(
e
.
detail
.
element
);
updateText
(
props
.
text
)
}
function
ontap
(
e
:
UniNativeViewEvent
)
{
emit
(
"
buttonTap
"
,
e
)
}
function
onUnmounted
()
{
// iOS平台需要主动释放 uts 实例
button
?.
destroy
()
}
</script>
```
> 选项式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
@
customClick=
"ontap"
></native-view>
</template>
<script
lang=
"uts"
>
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
export
default
{
data
()
{
return
{
button
:
null
as
NativeButton
|
null
,
value
:
""
}
},
props
:
{
"
text
"
:
{
type
:
String
,
default
:
''
}
},
watch
:
{
"
text
"
:
{
handler
(
newValue
:
string
,
oldValue
:
string
)
{
this
.
value
=
newValue
this
.
updateText
(
newValue
)
},
immediate
:
true
},
},
methods
:
{
//native-view初始化时触发此方法
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 传递给NativeButton插件
this
.
button
=
new
NativeButton
(
e
.
detail
.
element
);
this
.
button
?.
updateText
(
this
.
value
)
},
ontap
(
e
:
UniNativeViewEvent
)
{
this
.
$emit
(
"
buttonTap
"
,
e
)
},
updateText
(
value
:
string
)
{
this
.
button
?.
updateText
(
value
)
}
},
unmounted
()
{
// iOS平台需要主动释放 uts 实例
this
.
button
?.
destroy
()
}
}
</script>
```
:::
#### 实现NativeButton对象@utscode
utssdk目录实现不同平台的原生NativeButton对象,构造参数获取UniNativeViewElement对象与原生view绑定,封装原生view功能关联的API。
::: preview
> Android
```
uts
import { Button } from "android.widget"
export class NativeButton {
$element : UniNativeViewElement;
constructor(element : UniNativeViewElement) {
//接收传递过来的UniNativeViewElement
this.$element = element;
this.bindView();
}
button : Button | null = null;
bindView() {
//通过UniElement.getAndroidActivity()获取android平台activity 用于创建view的上下文
this.button = new Button(this.$element.getAndroidActivity()!); //构建原生view
//限制原生Button 文案描述不自动大写
this.button?.setAllCaps(false)
//监听原生Button点击事件
this.button?.setOnClickListener(_ => {
const detail = {}
//构建自定义UniNativeViewEvent返回对象
const event = new UniNativeViewEvent("customClick", detail)
//触发原生Button的点击事件
this.$element.dispatchEvent(event)
})
//UniNativeViewEvent 绑定 安卓原生view
this.$element.bindAndroidView(this.button!);
}
updateText(text: string) {
//更新原生Button 文案描述
this.button?.setText(text)
}
destroy(){
//数据回收
}
}
```
> iOS
```
uts
import { UIButton, UIControl } from "UIKit"
export class NativeButton {
element : UniNativeViewElement;
button : UIButton | null;
constructor(element : UniNativeViewElement) {
// 接收组件传递过来的UniNativeViewElement
this.element = element;
super.init()
this.bindView();
}
// element 绑定原生view
bindView() {
// 初始化原生 UIButton
this.button = new UIButton(type=UIButton.ButtonType.system)
// 构建方法选择器
const method = Selector("buttonClickAction")
// button 绑定点击回调方法
button?.addTarget(this, action = method, for = UIControl.Event.touchUpInside)
// UniNativeViewElement 绑定原生 view
this.element.bindIOSView(this.button!);
}
updateText(text : string) {
// 更新 button 显示文字
this.button?.setTitle(text, for = UIControl.State.normal)
}
/**
* 按钮点击回调方法
* 在 swift 中,所有target-action (例如按钮的点击事件,NotificationCenter 的通知事件等)对应的 action 函数前面都要使用 @objc 进行标记。
*/
@objc buttonClickAction() {
//构建自定义 UniNativeViewEvent 对象
let event = new UniNativeViewEvent("customClick")
//触发自定义事件
this.element.dispatchEvent(event)
}
destroy() {
// 释放 UTS 实例对象,避免内存泄露
UTSiOS.destroyInstance(this)
}
}
```
:::
更多实现可参考 标准模式组件
[
native-button
](
https://gitcode.net/dcloud/hello-uni-app-x/-/tree/dev/uni_modules/native-button
)
此时一个简单的UTS插件-标准模式组件就完成了,
**注意:**
+
UTS插件-标准模式组件的 components 目录下的代码中不应该含有原生平台任何引用对象,这会导致vue原生组件无法跨平台,推荐与原生平台关联的代码都放在utssdk中
+
ios平台需要vue组件主动释放 uts 实例,所以页面触发 unmounted 生命周期时需要调用 this.button?.destroy() 避免内存泄露
+
android平台 native-view 组件不支持border、background、box-shadow属性,可以使用view标签包裹native-view,在view标签设置以上属性
### 页面引用UTS插件-标准模式组件@pagecode
以 native-button 为例, 创建标准模式组件的项目页面可以直接使用 native-button 标签,也可将native-button插件包放置其他项目的uni-modules文件夹中。项目页面即可使用 native-button 标签
```
html
<template>
<view
style=
"flex:1"
>
<native-button
class=
"native-button"
text=
"buttonText"
@
buttonTap=
"ontap"
></native-button>
</view>
</template>
<script>
export
default
{
methods
:
{
ontap
(
e
:
UniNativeViewEvent
)
{
console
.
log
(
"
ontap----------
"
+
e
.
type
)
}
}
}
</script>
<style>
.native-button
{
height
:
100px
;
width
:
200px
;
margin
:
25px
auto
25px
auto
;
}
</style>
```
在hello uni-app x中,有native-button的完整示例。集成native-button的页面在pages/component/native-view/native-view.uvue,native-button组件在uni_modules/native-button/components/native-button/中。
## 总结@sum
通过vue方式开发组件非常直观。它分为几个核心步骤:
1.
在uni_modules/xxx/components/xxx/xxx.uvue文件中,通过标准vue方式定义组件的属性、方式、事件
2.
在uni_modules/xxx/components/xxx/xxx.uvue文件中,提供native-view组件,用于和原生的view绑定。在native-view组件的init事件中,调用utssdk下封装的原生对象的new初始化,将native-view对应的UniNativeViewElement传入
3.
在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,通过uts的方式,定义原生对象,在构造时接收components/xxx/xxx.uvue组件传来的UniNativeViewElement,并创建一个真正的原生view,和UniNativeViewElement绑定。
4.
在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,定义原生对象的各种方法,供components/xxx/xxx.uvue组件在其属性变化和方法调用时调用。
\ No newline at end of file
## 开发UTS插件-标准模式组件
下面我们以一个例子来讲解标准模式组件的开发。
我们开发一个
`native-button`
组件,目标是把Android和iOS的原生button封装成uvue组件。
Android的原生button会带有水波纹效果。uni-app自带的button组件并没有这个效果。
该组件计划提供一个 text属性,用于显示按钮的文字;有一个buttonTap事件用于处理点击。
let's go!
### 新建标准模式组件
HBuilder X 选中你的项目,项目根目录选中
`uni_modules`
目录,右键选择新建
`uni_modules`
插件,弹窗后分类选择 “UTS插件-标准模式组件”,填写组件名称,以下均以
`native-button`
为例
![](
https://web-ext-storage.dcloud.net.cn/doc/uts/uts_plugin/create-uts-vue-component.png
)
创建完毕 HBuilder X 会自动创建一批模版文件,参考:
[
前述目录结构
](
#dir
)
### 标准模式组件功能实现
#### 添加 native-view
上一步创建标准模式组件(名称为native-button)后,HBuilder X 会自动创建components/native-button/native-button.uvue文件。
这个文件是一个标准的uvue组件,符合easycom规范,在这个文件编写组件的属性、事件。
首先在该文件的template区添加
[
native-view 组件
](
../component/native-view.md
)
```
html
<template>
<native-view></native-view>
</template>
```
#### native-view 与 原生对象关联
native-view 组件的用途就是提供一个占位view,并且可以和原生的view进行绑定。
native-view 组件初始化会触发 @init 事件,如下代码在init时创建原生NativeButton对象,在其内部实现了view的绑定。
[
NativeButton
](
#utscode
)
是在utssdk目录的app-android和app-ios目录下的index.uts中定义的原生对象。NativeButton对象内部处理原生view与native-view绑定关联业务。
native-button.uvue代码中用NativeButton对象调用插件相关的API。
native-view 组件在uts中对应着UniNativeViewElement对象,将 UniNativeViewElement 传递给NativeButton对象,进行关联绑定。
::: preview
> 组合式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
></native-view>
</template>
<script
setup
lang=
"uts"
>
//引入 NativeButton 原生对象
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
let
button
:
NativeButton
|
null
=
null
//native-view初始化时触发此方法
function
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 传递给NativeButton对象
button
=
new
NativeButton
(
e
.
detail
.
element
);
}
</script>
```
> 选项式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
></native-view>
</template>
<script
lang=
"uts"
>
//引入 NativeButton 原生对象
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
export
default
{
data
()
{
return
{
button
:
null
as
NativeButton
|
null
}
},
methods
:
{
//native-view初始化时触发此方法
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 实例化NativeButton将element以构造参数传递给NativeButton对象
this
.
button
=
new
NativeButton
(
e
.
detail
.
element
);
}
}
}
</script>
```
:::
#### 组件声明方法
vue中,为组件定义方法很简单,但分选项式和组合式。
选项式中,在 methods 节点中添加updateText方法;组合式中,直接定义function updateText。参考vue文档
[
页面调用vue组件方法
](
https://doc.dcloud.net.cn/uni-app-x/vue/component.html#page-call-component-method
)
native-button组件使用者可调用该updateText方法中更新native-button文字。
但在vue组件的updateText方法中,需再次调用NativeButton的updateText方法,在原生插件中实现按钮文字更新。
::: preview
> 组合式 API
```
ts
<
script
setup
lang
=
"
uts
"
>
//引入 NativeButton 原生对象
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
let
button
:
NativeButton
|
null
=
null
//声明方法
function
updateText
(
value
:
string
)
{
button
?.
updateText
(
value
)
}
<
/script>
```
> 选项式 API
```
ts
methods
:
{
//对外函数
updateText
(
value
:
string
)
{
this
.
button
?.
updateText
(
value
)
}
}
```
:::
#### 组件声明属性props
native-button 声明组件属性props,例如native-button的文案信息text属性,按vue组件规范监听到text属性更新,通过NativeButton对象驱动更新原生view属性,在components/native-button/native-button.uvue编写如下代码,具体参考vue文档
[
vue组件Props规范
](
https://cn.vuejs.org/guide/typescript/composition-api#typing-component-props
)
::: preview
> 组合式 API
```
html
<script
setup
lang=
"uts"
>
//声明属性
const
props
=
defineProps
<
{
text
:
string
}
>
()
//声明方法
function
updateText
(
value
:
string
)
{
button
?.
updateText
(
value
)
}
//监听属性变化
watchEffect
(()
=>
{
// console.log("watchEffect "+props.text)
const
text
=
props
.
text
updateText
(
text
)
})
</script>
```
> 选项式 API
```
html
<script
lang=
"uts"
>
export
default
{
props
:
{
"
text
"
:
{
type
:
String
,
default
:
''
}
},
watch
:
{
"
text
"
:
{
handler
(
newValue
:
string
,
oldValue
:
string
)
{
this
.
value
=
newValue
this
.
button
?.
updateText
(
this
.
value
)
},
immediate
:
true
},
},
}
</script>
```
:::
#### 组件声明事件
native-button 声明事件,例如原生组件触发点击事件@buttonTap, NativeButton对象通过 UniNativeViewElement 的 dispatchEvent 函数触发native-view的 @customClick 自定义事件。native-button.uvue监听native-view的 @customClick 自定义事件实现emit触发声明事件,具体参考
[
vue组件事件规范
](
https://cn.vuejs.org/guide/typescript/composition-api#typing-component-emits
)
::: preview
> 组合式 API
```
html
<template>
<native-view
@
customClick=
"ontap"
></native-view>
</template>
<script
setup
lang=
"uts"
>
//声明事件
const
emit
=
defineEmits
<
{
(
e
:
"
buttonTap
"
,
event
:
UniNativeViewEvent
)
:
void
}
>
()
function
ontap
(
e
:
UniNativeViewEvent
)
{
emit
(
"
buttonTap
"
,
e
)
}
</script>
```
> 选项式 API
```
html
<template>
<native-view
@
customClick=
"ontap"
></native-view>
</template>
<script
lang=
"uts"
>
export
default
{
methods
:
{
ontap
(
e
:
UniNativeViewEvent
)
{
this
.
$emit
(
"
buttonTap
"
,
e
)
}
}
}
</script>
```
:::
**注意:**
目前自定义事件参数仅支持
[
UniNativeViewEvent
](
../component/native-view#uninativeviewevent
)
native-button/components/native-button/native-button.uvue 最终代码如下:
::: preview
> 组合式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
@
customClick=
"ontap"
></native-view>
</template>
<script
setup
lang=
"uts"
>
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
let
button
:
NativeButton
|
null
=
null
//声明属性
const
props
=
defineProps
<
{
text
:
string
}
>
()
//声明事件
const
emit
=
defineEmits
<
{
(
e
:
"
buttonTap
"
,
event
:
UniNativeViewEvent
)
:
void
}
>
()
//声明方法
function
updateText
(
value
:
string
)
{
button
?.
updateText
(
value
)
}
//监听属性变化
watchEffect
(()
=>
{
const
text
=
props
.
text
updateText
(
text
)
})
//native-view初始化时触发此方法
function
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 传递给NativeButton对象
button
=
new
NativeButton
(
e
.
detail
.
element
);
updateText
(
props
.
text
)
}
function
ontap
(
e
:
UniNativeViewEvent
)
{
emit
(
"
buttonTap
"
,
e
)
}
function
onUnmounted
()
{
// iOS平台需要主动释放 uts 实例
button
?.
destroy
()
}
</script>
```
> 选项式 API
```
html
<template>
<native-view
@
init=
"onviewinit"
@
customClick=
"ontap"
></native-view>
</template>
<script
lang=
"uts"
>
import
{
NativeButton
}
from
"
@/uni_modules/native-button
"
;
export
default
{
data
()
{
return
{
button
:
null
as
NativeButton
|
null
,
value
:
""
}
},
props
:
{
"
text
"
:
{
type
:
String
,
default
:
''
}
},
watch
:
{
"
text
"
:
{
handler
(
newValue
:
string
,
oldValue
:
string
)
{
this
.
value
=
newValue
this
.
updateText
(
newValue
)
},
immediate
:
true
},
},
methods
:
{
//native-view初始化时触发此方法
onviewinit
(
e
:
UniNativeViewInitEvent
)
{
//获取UniNativeViewElement 传递给NativeButton插件
this
.
button
=
new
NativeButton
(
e
.
detail
.
element
);
this
.
button
?.
updateText
(
this
.
value
)
},
ontap
(
e
:
UniNativeViewEvent
)
{
this
.
$emit
(
"
buttonTap
"
,
e
)
},
updateText
(
value
:
string
)
{
this
.
button
?.
updateText
(
value
)
}
},
unmounted
()
{
// iOS平台需要主动释放 uts 实例
this
.
button
?.
destroy
()
}
}
</script>
```
:::
#### 实现NativeButton对象@utscode
utssdk目录实现不同平台的原生NativeButton对象,构造参数获取UniNativeViewElement对象与原生view绑定,封装原生view功能关联的API。
::: preview
> Android
```
uts
import { Button } from "android.widget"
export class NativeButton {
$element : UniNativeViewElement;
constructor(element : UniNativeViewElement) {
//接收传递过来的UniNativeViewElement
this.$element = element;
this.bindView();
}
button : Button | null = null;
bindView() {
//通过UniElement.getAndroidActivity()获取android平台activity 用于创建view的上下文
this.button = new Button(this.$element.getAndroidActivity()!); //构建原生view
//限制原生Button 文案描述不自动大写
this.button?.setAllCaps(false)
//监听原生Button点击事件
this.button?.setOnClickListener(_ => {
const detail = {}
//构建自定义UniNativeViewEvent返回对象
const event = new UniNativeViewEvent("customClick", detail)
//触发原生Button的点击事件
this.$element.dispatchEvent(event)
})
//UniNativeViewEvent 绑定 安卓原生view
this.$element.bindAndroidView(this.button!);
}
updateText(text: string) {
//更新原生Button 文案描述
this.button?.setText(text)
}
destroy(){
//数据回收
}
}
```
> iOS
```
uts
import { UIButton, UIControl } from "UIKit"
export class NativeButton {
element : UniNativeViewElement;
button : UIButton | null;
constructor(element : UniNativeViewElement) {
// 接收组件传递过来的UniNativeViewElement
this.element = element;
super.init()
this.bindView();
}
// element 绑定原生view
bindView() {
// 初始化原生 UIButton
this.button = new UIButton(type=UIButton.ButtonType.system)
// 构建方法选择器
const method = Selector("buttonClickAction")
// button 绑定点击回调方法
button?.addTarget(this, action = method, for = UIControl.Event.touchUpInside)
// UniNativeViewElement 绑定原生 view
this.element.bindIOSView(this.button!);
}
updateText(text : string) {
// 更新 button 显示文字
this.button?.setTitle(text, for = UIControl.State.normal)
}
/**
* 按钮点击回调方法
* 在 swift 中,所有target-action (例如按钮的点击事件,NotificationCenter 的通知事件等)对应的 action 函数前面都要使用 @objc 进行标记。
*/
@objc buttonClickAction() {
//构建自定义 UniNativeViewEvent 对象
let event = new UniNativeViewEvent("customClick")
//触发自定义事件
this.element.dispatchEvent(event)
}
destroy() {
// 释放 UTS 实例对象,避免内存泄露
UTSiOS.destroyInstance(this)
}
}
```
:::
更多实现可参考 标准模式组件
[
native-button
](
https://gitcode.net/dcloud/hello-uni-app-x/-/tree/dev/uni_modules/native-button
)
此时一个简单的UTS插件-标准模式组件就完成了,
**注意:**
+
UTS插件-标准模式组件的 components 目录下的代码中不应该含有原生平台任何引用对象,这会导致vue原生组件无法跨平台,推荐与原生平台关联的代码都放在utssdk中
+
绑定原生 view 方法(bindAndroidView、bindIOSView)仅支持调用一次,原生 view 一旦绑定后不支持再次绑定其他 view
+
ios平台需要vue组件主动释放 uts 实例,所以页面触发 unmounted 生命周期时需要调用 this.button?.destroy() 避免内存泄露
+
android平台 native-view 组件不支持border、background、box-shadow属性,可以使用view标签包裹native-view,在view标签设置以上属性
### 页面引用UTS插件-标准模式组件@pagecode
以 native-button 为例, 创建标准模式组件的项目页面可以直接使用 native-button 标签,也可将native-button插件包放置其他项目的uni-modules文件夹中。项目页面即可使用 native-button 标签
```
html
<template>
<view
style=
"flex:1"
>
<native-button
class=
"native-button"
text=
"buttonText"
@
buttonTap=
"ontap"
></native-button>
</view>
</template>
<script>
export
default
{
methods
:
{
ontap
(
e
:
UniNativeViewEvent
)
{
console
.
log
(
"
ontap----------
"
+
e
.
type
)
}
}
}
</script>
<style>
.native-button
{
height
:
100px
;
width
:
200px
;
margin
:
25px
auto
25px
auto
;
}
</style>
```
在hello uni-app x中,有native-button的完整示例。集成native-button的页面在pages/component/native-view/native-view.uvue,native-button组件在uni_modules/native-button/components/native-button/中。
## 总结@sum
通过vue方式开发组件非常直观。它分为几个核心步骤:
1.
在uni_modules/xxx/components/xxx/xxx.uvue文件中,通过标准vue方式定义组件的属性、方式、事件
2.
在uni_modules/xxx/components/xxx/xxx.uvue文件中,提供native-view组件,用于和原生的view绑定。在native-view组件的init事件中,调用utssdk下封装的原生对象的new初始化,将native-view对应的UniNativeViewElement传入
3.
在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,通过uts的方式,定义原生对象,在构造时接收components/xxx/xxx.uvue组件传来的UniNativeViewElement,并创建一个真正的原生view,和UniNativeViewElement绑定。
4.
在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,定义原生对象的各种方法,供components/xxx/xxx.uvue组件在其属性变化和方法调用时调用。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录