Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
你丑我先上
unidocs-zh
提交
d816ee63
U
unidocs-zh
项目概览
你丑我先上
/
unidocs-zh
与 Fork 源项目一致
Fork自
DCloud / unidocs-zh
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
unidocs-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
d816ee63
编写于
1月 10, 2023
作者:
杜庆泉
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
文档完善进行中
上级
8c94b979
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
392 addition
and
75 deletion
+392
-75
docs/plugin/uts-component.md
docs/plugin/uts-component.md
+392
-75
未找到文件。
docs/plugin/uts-component.md
浏览文件 @
d816ee63
...
...
@@ -95,13 +95,13 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
用户如果在开发组件的同时,存在一些与组件无关的能力需要对外暴露,可以在index.uts中进行实现
大多数情况下,我们只需要开发一个index.vue 即可,如果存在多个组件,可以新建多个
*
.vue文件
大多数情况下,我们只需要开发一个index.vue 即可,如果存在多个组件,可以新建多个
xxx
.vue文件
关于
index.vue 的源码规范
会在下一个章节介绍
关于
index.vue 源码如何编写,我们
会在下一个章节介绍
####
UTS组件源码解析
####
index.vue源码结构
下面是一个组件源码 index.vue 完整示例:
...
...
@@ -286,7 +286,7 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
```
index.vue可以分为以下几类:
index.vue
要素
可以分为以下几类:
+
配置:
...
...
@@ -313,16 +313,16 @@ index.vue可以分为以下几类:
+
生命周期:
组件需要重点处理 内存创建/销毁,View载体创建/销毁 过程中的资源管理,具体参考
3.4
章节
组件需要重点处理 内存创建/销毁,View载体创建/销毁 过程中的资源管理,具体参考
生命周期
章节
+
内置对象:
为了方便组件开发者,UTS组件内置了部分变量与函数,具体参考
3.5
章节
为了方便组件开发者,UTS组件内置了部分变量与函数,具体参考
内置对象与函数
章节
#### 生命周期
组件开发者需要重点关注
生命周期
组件开发者需要重点关注
组件的生命周期,以便进行初始化和资源回收
```
mermaid
graph TD;
...
...
@@ -375,6 +375,10 @@ doMeasure 用于告诉排版系统,组件自身需要的宽高,具体的调
## 简单View的示例
本章节以 一个极简的组件开发为例,介绍说明UTS组件开发流程
#### 创建插件
在HBuilder X 中选中Uni-App项目下 uni_modules目录
...
...
@@ -414,35 +418,17 @@ todo 目前还没有创建界面
//原生提供以下属性或方法的实现
export
default
{
/**
* 组件名称,也就是开发者使用的标签
*/
name
:
"
uts-hello-view
"
,
/**
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
*/
emits
:
[
'
buttonClick
'
],
/**
* 属性声明,组件的使用者会传递这些属性值到组件
*/
props
:
{
/**
* 字符串类型 属性:buttonText 需要设置默认值
*/
"
buttonText
"
:
{
type
:
String
,
default
:
"
点击触发
"
}
},
/**
* 属性变化监听器实现
*/
watch
:
{
"
buttonText
"
:
{
/**
* 这里监听属性变化,并进行组件内部更新
*/
handler
(
newButtonText
:
string
)
{
if
(
this
.
$el
!=
null
)
{
let
button
=
this
.
$el
!
.
findViewWithTag
(
"
centerButton
"
)
as
Button
...
...
@@ -454,18 +440,15 @@ todo 目前还没有创建界面
},
},
NVLoad
():
LinearLayout
{
//必须实现
let
contentLayout
=
new
LinearLayout
(
$androidContext
)
let
button
=
new
Button
(
$androidContext
)
button
.
setText
(
"
点击触发
"
);
button
.
setTag
(
"
centerButton
"
);
contentLayout
.
addView
(
button
,
LinearLayout
.
LayoutParams
(
500
,
500
));
button
.
setOnClickListener
(
new
ButtonClickListsner
())
return
contentLayout
},
}
...
...
@@ -481,16 +464,49 @@ todo 目前还没有创建界面
```
上面的代码,我们自定义了一个 名为
<uts-hello-view/>
的UTS 组件,该组件对外提供了一个包含按钮的简单UI实现,并且对外暴露了一个名为
`buttonText`
字符串属性,用来构建按钮上的文案
接下来,我们在下面章节介绍在uni-app项目中如何使用它
#### 使用组件
打开任意 componet.nvue文件
>> 需要注意的是,UTS组件默认全局注册,无需使用者手动配置
我们在uni-app项目中新建 componet.nvue 页面,
直接使用
`uts-hello-view`
标签,并且定义
`buttonText`
文本内容即可看到效果。
点击按钮,可以在控制台看到组件内部实现的日志输出
```
js
<
uts
-
hello
-
view
buttonText
=
"
点击按钮内容
"
style
=
"
width:375px;height: 375px;background-color: aqua;
"
><
/uts-hello-view>
<
template
>
<
div
>
<
text
>
UTS
view组件
<
/text
>
<
uts
-
hello
-
view
buttonText
=
"
点击按钮内容
"
style
=
"
width:375px;height: 375px;background-color: aqua;
"
><
/uts-hello-view
>
<
/div
>
<
/template
>
<
script
>
<
/script
>
<
style
>
<
/style>
```
#### 运行和测试
在当前示例中,不涉及第三方依赖,使用标准基座直接运行即可
## 包含第三方SDK的示例
本章节以lottie动画组件为例,介绍包含三方SDK的UTS组件开发过程
#### 创建插件
在HBuilder X 中选中Uni-App项目下 uni_modules目录
...
...
@@ -518,70 +534,371 @@ UTS组件建议使用远程依赖的方式集成,如果需要以AAR的形式
~/uni_modules/uts-animation-view/utssdk/app-android/libs目录
依赖的配置原则与UTS插件一致
[
UTS插件依赖说明
](
https://uniapp.dcloud.net.cn/plugin/uts-for-android.html#_3-4-%E5%A2%9E%E5%8A%A0libs%E4%BE%9D%E8%B5%96%E8%B5%84%E6%BA%90
)
#### 编写逻辑
打开index.vue,键入下面的组件源码:
#### 使用组件
```
ts
<
template
>
<
view
class
=
"
defaultStyles
"
>
<
/view
>
<
/template
>
<
script
lang
=
"
uts
"
>
import
Animator
from
'
android.animation.Animator
'
import
TextUtils
from
'
android.text.TextUtils
'
import
View
from
'
android.view.View
'
import
LottieAnimationView
from
'
com.airbnb.lottie.LottieAnimationView
'
import
LottieDrawable
from
'
com.airbnb.lottie.LottieDrawable
'
import
FileInputStream
from
'
java.io.FileInputStream
'
import
{
UTSAndroid
}
from
"
io.dcloud.uts
"
;
class
CustomAnimListener
extends
Animator
.
AnimatorListener
{
comp
:
UTSComponent
<
LottieAnimationView
>
constructor
(
com
:
UTSComponent
<
LottieAnimationView
>
)
{
super
();
this
.
comp
=
com
}
override
onAnimationStart
(
animation
:
Animator
|
null
)
{}
override
onAnimationEnd
(
animation
:
Animator
|
null
,
isReverse
:
Boolean
)
{
this
.
comp
.
emit
(
"
bindended
"
)
}
override
onAnimationEnd
(
animation
:
Animator
|
null
)
{}
override
onAnimationCancel
(
animation
:
Animator
|
null
)
{}
override
onAnimationRepeat
(
animation
:
Animator
|
null
)
{}
}
//原生提供以下属性或方法的实现
export
default
{
name
:
"
uts-animation-view
"
,
/**
* 当播放到末尾时触发 ended 事件(自然播放结束会触发回调,循环播放结束及手动停止动画不会触发)
*/
emits
:
[
'
bindended
'
],
props
:
{
/**
* 动画资源地址,目前只支持绝对路径
*/
"
path
"
:
{
type
:
String
,
default
:
""
},
/**
* 动画是否循环播放
*/
"
autoplay
"
:
{
type
:
Boolean
,
default
:
false
},
/**
* 动画是否自动播放
*/
"
loop
"
:
{
type
:
Boolean
,
default
:
false
},
/**
* 是否隐藏动画
*/
"
hidden
"
:
{
type
:
Boolean
,
default
:
false
},
/**
* 动画操作,可取值 play、pause、stop
*/
"
action
"
:
{
type
:
String
,
default
:
"
stop
"
}
},
data
()
{
return
{
}
},
watch
:
{
"
path
"
:
{
handler
(
newPath
:
string
)
{
if
(
this
.
$el
!=
null
){
let
lottieAnimationView
=
this
.
$el
!
if
(
!
TextUtils
.
isEmpty
(
newPath
))
{
if
(
newPath
.
startsWith
(
"
http://
"
)
||
newPath
.
startsWith
(
"
https://
"
))
{
lottieAnimationView
.
setAnimationFromUrl
(
newPath
)
}
else
{
// 默认是static了
var
realJsonPath
=
UTSAndroid
.
getResourcePath
(
newPath
)
lottieAnimationView
.
setAnimation
(
new
FileInputStream
(
realJsonPath
),
newPath
)
}
}
if
(
this
.
autoplay
)
{
lottieAnimationView
.
playAnimation
()
}
}
},
immediate
:
false
//创建时是否通过此方法更新属性,默认值为false
},
"
loop
"
:
{
handler
(
newLoop
:
Boolean
)
{
if
(
this
.
$el
!=
null
){
if
(
newLoop
)
{
this
.
$el
!
.
repeatCount
=
Int
.
MAX_VALUE
}
else
{
// 不循环则设置成1次
this
.
$el
!
.
repeatCount
=
0
}
if
(
this
.
autoplay
)
{
this
.
$el
!
.
playAnimation
()
}
}
},
immediate
:
false
//创建时是否通过此方法更新属性,默认值为false
},
"
autoplay
"
:
{
handler
(
newValue
:
boolean
)
{
if
(
this
.
$el
!=
null
){
if
(
newValue
)
{
this
.
$el
!
.
playAnimation
()
}
}
},
immediate
:
false
//创建时是否通过此方法更新属性,默认值为false
},
"
action
"
:
{
handler
(
newAction
:
string
)
{
if
(
newAction
==
"
play
"
||
newAction
==
"
pause
"
||
newAction
==
"
stop
"
)
{
if
(
this
.
$el
!=
null
){
if
(
this
.
action
==
"
play
"
)
{
this
.
$el
!
.
playAnimation
()
}
else
if
(
this
.
action
==
"
pause
"
)
{
this
.
$el
!
.
pauseAnimation
()
}
else
if
(
this
.
action
==
"
stop
"
)
{
this
.
$el
!
.
cancelAnimation
()
this
.
$el
!
.
clearAnimation
()
}
}
}
else
{
// 非法入参,不管
}
},
immediate
:
false
//创建时是否通过此方法更新属性,默认值为false
},
"
hidden
"
:
{
handler
(
newValue
:
boolean
)
{
if
(
this
.
$el
!=
null
){
if
(
newValue
)
{
this
.
$el
!
.
visibility
=
View
.
GONE
}
else
{
this
.
$el
!
.
visibility
=
View
.
VISIBLE
}
}
},
immediate
:
false
//创建时是否通过此方法更新属性,默认值为false
},
},
methods
:
{
setRepeatMode
(
repeat
:
string
)
{
if
(
this
.
$el
!=
null
){
if
(
"
RESTART
"
==
repeat
)
{
this
.
$el
!
.
repeatMode
=
LottieDrawable
.
RESTART
}
else
if
(
"
REVERSE
"
==
repeat
)
{
this
.
$el
!
.
repeatMode
=
LottieDrawable
.
RESTART
}
}
},
privateMethod
()
{
//如何定义不对外暴露的API? 暂不支持,需在export外写
}
},
created
()
{
//创建组件,替换created
},
NVBeforeLoad
()
{
//组件将要创建,对应前端beforeMount
//可选实现,这里可以提前做一些操作
},
NVLoad
():
LottieAnimationView
{
//创建原生View,必须定义返回值类型(Android需要明确知道View类型,需特殊校验)
//必须实现
let
lottieAnimationView
=
new
LottieAnimationView
(
$androidContext
)
return
lottieAnimationView
},
NVLoaded
()
{
//原生View已创建
//可选实现,这里可以做后续操作
if
(
this
.
$el
!=
null
){
this
.
$el
!
.
repeatMode
=
LottieDrawable
.
RESTART
;
this
.
$el
!
.
visibility
=
View
.
GONE
this
.
$el
!
.
repeatCount
=
0
this
.
$el
!
.
addAnimatorListener
(
new
CustomAnimListener
(
this
))
}
},
NVLayouted
()
{
//原生View布局完成
//可选实现,这里可以做布局后续操作
},
NVBeforeUnload
()
{
//原生View将释放
//可选实现,这里可以做释放View之前的操作
},
NVUnloaded
()
{
//原生View已释放
//可选实现,这里可以做释放View之后的操作
},
unmounted
()
{
//组件销毁
//可选实现
}
}
<
/script
>
<
style
>
/* 定义默认样式值, 组件使用者没有配置时使用 */
.
defaultStyles
{
width
:
750
rpx
;
height
:
240
rpx
;
}
<
/style
>
#### 使用组件的注意事项
```
1.
需要自定义基座方能使用
上面的代码我们实现了一个支持lottie动画播放的 UTS组件,标签名称为
<uts-animation-view
/>
,
2 不需要引用,直接使用自定义标签
对外提供了下列属性和方法
```
js
<
xxx
-
view
:
propA
=
"
自定义属性值
"
ref
=
"
当前组件标签
"
>
<
/xxx-view>
```
|属性 |类型 |默认值 |描述 |
|:--- |:-- |:-- |:--- |
|
`path`
|string ||
`lottie`
资源路径,支持本地地址和
`http`
协议下的网络地址|
|
`loop`
|boolean|false |动画是否循环播放|
|
`autoplay`
|boolean|true |动画是否自动播放|
|
`action`
|string |play |动画操作,可取值 play、pause、stop|
|
`hidden`
|boolean|true |是否隐藏动画|
|
`bindended`
|event | |当播放到末尾时触发 ended 事件|
|
`setRepeatMode`
|function| |设置动画的重复方式,RESTART:重新开始播放,REVERSE,反向播放|
#### 使用组件属性
#### 使用组件
新建 lottie.nvue 页面,引用自定义 uts-animation-view 组件,并编写测试用例
组件的开发者,声明属性
```
props: {
/**
* 属性A:propA 需要声明属性类型和默认值
*/
"propA": {
type: String,
default: ""
},
},
```
<template>
<div>
<button @tap="changeUrl">播放本地动画资源</button>
<button @tap="changeServerUrl">播放远程动画资源</button>
<button @tap="changeAutoPlay">测试AutoPlay</button>
<button @tap="changeLoop">测试Loop</button>
<button @tap="changeAction(1)">测试action play</button>
<button @tap="changeAction(2)">测试action pause</button>
<button @tap="changeAction(3)">测试action stop</button>
<uts-animation-view ref="animView" :path="animUrl" :autoplay="autoplay" :loop="loop" :action="action"
:hidden="hidden" @bindended="testAnimEnd" @click="lottieClickTest" @longpress="lottieLongpressTest"
:style="{width:widthNum+'rpx',height:heightNum+'px',background:yanse}">
</uts-animation-view>
</div>
</template>
<script>
export default {
data() {
return {
hidden: false,
autoplay: false,
action: "play",
loop: false,
yanse: "red",
widthNum: 750,
heightNum: 200,
comShow: true,
animUrl: "/static/anim_a.json"
}
},
methods: {
changeAutoPlay: function() {
this.autoplay = !this.autoplay
},
changeUrl: function() {
if (this.animUrl == "/static/anim_a.json") {
this.animUrl = "/static/anim_b.json"
} else {
this.animUrl = "/static/anim_a.json"
}
},
changeServerUrl: function() {
this.animUrl = "https://b.bdstatic.com/miniapp/images/lottie_example_one.json"
},
changeAction: function(type) {
if (type == 1) {
this.action = "play"
} else if (type == 2) {
this.action = "pause"
} else if (type == 3) {
this.action = "stop"
}
},
changeLoop: function() {
this.loop = !this.loop
},
testAnimEnd: function(res) {
console.log("testAnimEnd");
},
changeRepeat: function(res) {
let repeatConfig = {
count: 3,
mode: "restart"
}
this.$refs["animView"].updateRepeatConfig(repeatConfig, function(res) {
console.log(res);
});
},
lottieClickTest: function(res) {
console.log("lottieClickTest");
console.log(res);
},
lottieLongpressTest: function(res) {
console.log("lottieClickTest");
console.log(res);
},
}
}
</script>
组件使用者,使用属性
```
js
<
xxx
-
view
:
propA
=
"
自定义属性值
"
>
<
/xxx-view>
```
#### 使用组件方法
上面的代码实现了一个名为
组件的开发者,定义公开方法
#### 运行和测试
```
methods: {
publicMethod() {
doSth(paramA: string) {
// 这是组件的自定义方法
}
}
}
```
组件使用者,使用方法
```
js
// 布局代码
<
xxx
-
view
ref
=
"
customTag
"
>
<
/xxx-view
>
// 调用代码
this
.
$refs
[
"
customTag
"
].
doSth
(
'
参数
'
)
```
在当前例子中,需要下载额外的第三方依赖,需要自定义基座方能使用
点击页面中的测试按钮,即可看到
## 快速体验
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录