uts-component.md 9.0 KB
Newer Older
杜庆泉's avatar
杜庆泉 已提交
1 2
# UTS 组件开发

杜庆泉's avatar
杜庆泉 已提交
3 4 5
本文旨在帮助开发者,使用UTS开发Uni-App平台组件功能。


杜庆泉's avatar
杜庆泉 已提交
6
## 前置条件
杜庆泉's avatar
杜庆泉 已提交
7

杜庆泉's avatar
杜庆泉 已提交
8 9
继续阅读文档前,开发者需要了解以下前置条件:

杜庆泉's avatar
杜庆泉 已提交
10 11
+ HBuilderX 3.6.15 及之后版本

杜庆泉's avatar
杜庆泉 已提交
12 13
+ 了解Vue 组件基本概念

杜庆泉's avatar
杜庆泉 已提交
14 15
+ 目前仅支持nvue

杜庆泉's avatar
杜庆泉 已提交
16
## UTS组件简介
杜庆泉's avatar
杜庆泉 已提交
17

杜庆泉's avatar
杜庆泉 已提交
18
#### 为什么使用组件
杜庆泉's avatar
杜庆泉 已提交
19

杜庆泉's avatar
杜庆泉 已提交
20
组件是一种独立,可复用的UI单元,用于单独封装和承担一定的代码逻辑,组件化可以降低项目的工程复杂度,提升可维护性
杜庆泉's avatar
杜庆泉 已提交
21

杜庆泉's avatar
杜庆泉 已提交
22
组件与插件的区别在于:前者倾向于以标签的形式 对外提供UI封装,后者倾向于以函数/类 的形式 对外提供功能封装。如果你的需求更倾向于封装能力,请移步 [UTS插件开发](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
杜庆泉's avatar
杜庆泉 已提交
23

杜庆泉's avatar
杜庆泉 已提交
24
组件一般适用于组件非全屏的场景,如果需要封装的UI始终是全屏,那么可以考虑通过开发原生实现
杜庆泉's avatar
杜庆泉 已提交
25

杜庆泉's avatar
杜庆泉 已提交
26

杜庆泉's avatar
杜庆泉 已提交
27
#### 为什么使用UTS开发组件
杜庆泉's avatar
杜庆泉 已提交
28

杜庆泉's avatar
杜庆泉 已提交
29
UTS组件,即:使用UTS语言在uni平台进行组件开发的技术。
杜庆泉's avatar
杜庆泉 已提交
30

杜庆泉's avatar
杜庆泉 已提交
31

杜庆泉's avatar
杜庆泉 已提交
32
UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语法,各终端不同的本地产出物。
杜庆泉's avatar
杜庆泉 已提交
33

杜庆泉's avatar
杜庆泉 已提交
34
在Android平台会被编译为会被渲染为Android原生View实例,IOS或其他终端平台也是如此。
杜庆泉's avatar
杜庆泉 已提交
35

杜庆泉's avatar
杜庆泉 已提交
36

杜庆泉's avatar
杜庆泉 已提交
37 38 39 40 41 42 43
|				|uts组件					|uni原生组件				|Vue组件				|
|:------		|:--------				|:-------- 				|:-------			|
|开发语言		|uts					|java/object-c			|js/ts				|
|组件载体		|系统原生View对象		|系统原生View对象		|WebView内部标签		|


为了兼容前端开发者的门槛,UTS组件结构采用了类Vue组件的语法,[关于Vue组件](https://cn.vuejs.org/guide/essentials/component-basics.html),但是具体的函数上会有定制,我们会在下一个章节详细介绍
杜庆泉's avatar
杜庆泉 已提交
44 45


杜庆泉's avatar
杜庆泉 已提交
46
## 3 如何开发组件
杜庆泉's avatar
杜庆泉 已提交
47

杜庆泉's avatar
杜庆泉 已提交
48
>本章节提到全部示例源码可以在Hello UTS 中找到
杜庆泉's avatar
杜庆泉 已提交
49 50


杜庆泉's avatar
杜庆泉 已提交
51
#### 3.1 创建组件
杜庆泉's avatar
杜庆泉 已提交
52

杜庆泉's avatar
杜庆泉 已提交
53
UTS组件的创建过程与UTS插件一样。
杜庆泉's avatar
杜庆泉 已提交
54

杜庆泉's avatar
杜庆泉 已提交
55
选中 项目目录/uni_modules 右键 新建组件  TODO
杜庆泉's avatar
杜庆泉 已提交
56

杜庆泉's avatar
杜庆泉 已提交
57
![目录结构](https://native-res.dcloud.net.cn/images/uts/component/image1.png)
杜庆泉's avatar
杜庆泉 已提交
58 59


杜庆泉's avatar
杜庆泉 已提交
60 61 62
组件的入口文件是index.vue,具体规范会在下一个章节介绍

另外 组件允许存在入口文件:index.uts 对外提供函数能力,具体参考 UTS 插件介绍
杜庆泉's avatar
杜庆泉 已提交
63 64 65 66 67



#### 3.2 示例代码简介

杜庆泉's avatar
杜庆泉 已提交
68 69 70

下面是一个组件源码 index.vue 完整示例:

D
DCloud_LXH 已提交
71
```ts
杜庆泉's avatar
杜庆泉 已提交
72 73 74 75 76 77 78

    export default {
		/**
		 * 组件名称,也就是开发者使用的标签
		 */
        name: "xxx-view",
        /**
杜庆泉's avatar
杜庆泉 已提交
79
         * 组件涉及的事件声明,只有声明过的事件,才能被正常发送
杜庆泉's avatar
杜庆泉 已提交
80 81
         */
        emits: ['bindended'],
杜庆泉's avatar
杜庆泉 已提交
82 83 84
		/**
		 * 属性声明,组件的使用者会传递这些属性值到组件
		 */
杜庆泉's avatar
杜庆泉 已提交
85 86
        props: {
            /**
杜庆泉's avatar
杜庆泉 已提交
87
             * 字符串类型 属性:path  默认值:""
杜庆泉's avatar
杜庆泉 已提交
88
             */
杜庆泉's avatar
杜庆泉 已提交
89
            "path": {
杜庆泉's avatar
杜庆泉 已提交
90 91 92 93
                type: String,
                default: ""
            },
        },
杜庆泉's avatar
杜庆泉 已提交
94 95 96
		/**
		 * 组件内部变量声明
		 */
杜庆泉's avatar
杜庆泉 已提交
97 98 99 100
        data() {
            return {
            }
        },
杜庆泉's avatar
杜庆泉 已提交
101 102 103
		/**
		 * 属性变化监听器实现
		 */
杜庆泉's avatar
杜庆泉 已提交
104
        watch: {
杜庆泉's avatar
杜庆泉 已提交
105 106 107 108
			
            "path": {
                handler(newPath: string) {
					// 这里处理属性newPath 的更新逻辑
杜庆泉's avatar
杜庆泉 已提交
109
                },
杜庆泉's avatar
杜庆泉 已提交
110 111
				//创建时是否通过此方法更新属性,默认值为false  
                immediate: false 
杜庆泉's avatar
杜庆泉 已提交
112 113
            },
        },
杜庆泉's avatar
杜庆泉 已提交
114 115 116 117 118
		
		/**
		 * 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
		 * ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
		 */
杜庆泉's avatar
杜庆泉 已提交
119 120
		expose: ['publicMethod'],
        methods: {
杜庆泉's avatar
杜庆泉 已提交
121 122 123
			/**
			 * 对外公开的组件方法
			 */
杜庆泉's avatar
杜庆泉 已提交
124 125 126 127 128
			publicMethod() {
				doSth(paramA: string) {
					// 这是组件的自定义方法
				}
			},
杜庆泉's avatar
杜庆泉 已提交
129 130 131
			/**
			 * 内部使用的组件方法
			 */
杜庆泉's avatar
杜庆泉 已提交
132
			privateMethod() {
杜庆泉's avatar
杜庆泉 已提交
133
				doSthInner(paramA: string) {
杜庆泉's avatar
杜庆泉 已提交
134 135 136 137 138
					// 这是组件的自定义方法
				}
			}
            
        },
杜庆泉's avatar
杜庆泉 已提交
139 140 141 142 143 144 145
		
		/**
		 * 组件被创建,组件第一个生命周期,
		 * 在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑
		 * [可选实现]
		 */
        created() { 
杜庆泉's avatar
杜庆泉 已提交
146 147

        },
杜庆泉's avatar
杜庆泉 已提交
148 149 150 151 152 153
		/**
		 * 对应平台的view载体即将被创建,对应前端beforeMount  
		 * [可选实现]
		 */
        NVBeforeLoad() {
			
杜庆泉's avatar
杜庆泉 已提交
154
        },
杜庆泉's avatar
杜庆泉 已提交
155 156 157 158 159 160 161 162
		/**
		 * 创建原生View,必须定义返回值类型
		 * 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
		 * (Android需要明确知道View类型,需特殊校验) 
		 * todo 补充IOS平台限制
		 * [必须实现]
		 */
        NVLoad(): View {
杜庆泉's avatar
杜庆泉 已提交
163 164 165
            let viewInstance = new View($androidContext)
            return aView
        },
杜庆泉's avatar
杜庆泉 已提交
166 167 168 169 170 171
		/**
		 * 原生View已创建 
		 * [可选实现]
		 */
        NVLoaded() {
			
杜庆泉's avatar
杜庆泉 已提交
172
        },
杜庆泉's avatar
杜庆泉 已提交
173 174 175 176 177 178
		/**
		 * 原生View布局完成  
		 * [可选实现]
		 */
        NVLayouted() {
            
杜庆泉's avatar
杜庆泉 已提交
179
        },
杜庆泉's avatar
杜庆泉 已提交
180 181 182 183 184
		/**
		 * 原生View将释放  
		 * [可选实现]
		 */
        NVBeforeUnload() {
杜庆泉's avatar
杜庆泉 已提交
185
        },
杜庆泉's avatar
杜庆泉 已提交
186 187 188 189 190 191
		/**
		 * 原生View已释放,这里可以做释放View之后的操作  
		 * [可选实现]
		 */
        NVUnloaded() {
			
杜庆泉's avatar
杜庆泉 已提交
192
        },
杜庆泉's avatar
杜庆泉 已提交
193 194 195 196 197
		/**
		 * 组件销毁  
		 * [可选实现]
		 */
        unmounted() { 
杜庆泉's avatar
杜庆泉 已提交
198
        }
杜庆泉's avatar
杜庆泉 已提交
199 200 201 202 203 204 205 206 207
		/**
		 * 自定组件布局尺寸 
		 * [可选实现]
		 */
		doMeasure(size: UTSSize): UTSSize {
			size.width = 120.0.toFloat()
			size.height = 800.0.toFloat()
			return size
		}
杜庆泉's avatar
杜庆泉 已提交
208 209 210 211
    }

```

杜庆泉's avatar
杜庆泉 已提交
212
index.vue可以分为以下几类:
杜庆泉's avatar
杜庆泉 已提交
213

杜庆泉's avatar
杜庆泉 已提交
214
+ 配置:
杜庆泉's avatar
杜庆泉 已提交
215

杜庆泉's avatar
杜庆泉 已提交
216 217 218
	name:组件的使用标签,可以省略,若省略则默认为组件名称
	
	emits:组件允许的消息事件名称,如果没有组件消息,不需要配置
杜庆泉's avatar
杜庆泉 已提交
219

杜庆泉's avatar
杜庆泉 已提交
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
+ 属性:
	
	props:需要由组件的使用者提供,比如一个Image组件,会需要一个path属性作为图像路径来源
	
	watch:属性的监听实现,用来监听属性数据更新。
	
+ 数据:	

	data:组件内部数据定义,用于组件内部逻辑处理,不对外暴露

+ 方法:

	methods:组件方法定义,可以通过与expose组合使用,区分对内方法和对外方法
	
	expose:与methods 字段配合使用,用以区分组件对内方法和对外方法


+ 生命周期:

	组件需要重点处理 内存创建/销毁,View载体创建/销毁 过程中的资源管理,具体参考3.4章节
	
+ 内置对象:
	
	为了方便组件开发者,UTS组件内置了部分变量与函数,具体参考3.5章节


#### 3.4 生命周期 

组件开发者需要重点关注生命周期


![生命周期](https://native-res.dcloud.net.cn/images/uts/component/image2.png)

+ created:

组件被创建,组件第一个生命周期,在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑

+ NVBeforeLoad:

组件对应平台的view载体 即将被创建

+ NVLoad:

[必须实现]

组件 view载体的创建实现

开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型


+ NVLayouted:

组件对应平台的view载体,布局完成

+ NVBeforeUnload:

view载体即将被卸载

资源回收

+ NVUnloaded:

view载体已经被卸载

资源回收

+ unmounted:

view载体被回收

资源回收

+ doMeasure:

doMeasure 用于告诉排版系统,组件自身需要的宽高,具体的调用时机由排版系统决定。

一般情况下,组件的宽高应该是由终端系统的排版引擎决定,组件开发者不需要实现此函数。

但是部分场景下,组件开发者需要自己维护宽高,则需要开发者重写此函数



#### 3.5 内置对象和函数

为了方便组件开发者使用,UTS 组件内部内置了下列对象:

|变量名			|类型		|简介					|平台限制	|
|:-------		|:--------	|:--------				|:---		|
|$el			|对象		|当前View实例对象		|全部平台	|
|$androidContext|对象		|当前组件上下文			|仅android	|
|emit("event")	|函数		|发送已注册的事件		|全部平台	|








## 4 使用组件


#### 4.1 注意事项:

1. 需要自定义基座方能使用

2 不需要引用,直接使用自定义标签

```js
 <xxx-view  :propA="自定义属性值" ref="当前组件标签">
 </xxx-view>
杜庆泉's avatar
杜庆泉 已提交
331 332
```

杜庆泉's avatar
杜庆泉 已提交
333 334 335
#### 4.2 属性


杜庆泉's avatar
杜庆泉 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355

组件的开发者,声明属性
```
props: {
	/**
	 * 属性A:propA  需要声明属性类型和默认值
	 */
	"propA": {
		type: String,
		default: ""
	},
},
```

组件使用者,使用属性
```js
 <xxx-view  :propA="自定义属性值" >
 </xxx-view>
```

杜庆泉's avatar
杜庆泉 已提交
356 357 358
#### 4.3 方法


杜庆泉's avatar
杜庆泉 已提交
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
组件的开发者,定义公开方法

```
methods: {
	publicMethod() {
		doSth(paramA: string) {
			// 这是组件的自定义方法
		}
	}
}
```
组件使用者,使用方法

```js
 // 布局代码
杜庆泉's avatar
杜庆泉 已提交
374
 <xxx-view  ref="customTag" >
杜庆泉's avatar
杜庆泉 已提交
375 376
 </xxx-view>
 // 调用代码
杜庆泉's avatar
杜庆泉 已提交
377
 this.$refs["customTag"].doSth('参数')
杜庆泉's avatar
杜庆泉 已提交
378 379 380
```


杜庆泉's avatar
杜庆泉 已提交
381
## 5 快速体验
杜庆泉's avatar
杜庆泉 已提交
382 383


杜庆泉's avatar
杜庆泉 已提交
384
开发者可以使用[Hello UTS](https://gitcode.net/dcloud/hello-uts) 快速体验UTS 组件开发
杜庆泉's avatar
杜庆泉 已提交
385

杜庆泉's avatar
杜庆泉 已提交
386
使用HX 3.6.16 版本 - 选择 Hello UTS - 自定义基座包。
杜庆泉's avatar
杜庆泉 已提交
387

杜庆泉's avatar
杜庆泉 已提交
388
查看:三方SDK-Lottie动画示例,对应的源码实现:~/uni_modules/uts-animation-view
杜庆泉's avatar
杜庆泉 已提交
389 390 391 392



## 常见问题