uts-vue-component.md 11.3 KB
Newer Older
shutao-dc's avatar
shutao-dc 已提交
1
## uts组件标准模式
2

shutao-dc's avatar
shutao-dc 已提交
3
使用vue组件开发规范,通过uts插件封装原生平台view提供给native-view组件,实现组件特定功能及UI展示。
4 5 6 7 8

## 前置条件

继续阅读文档前,开发者需要了解以下前置条件:

9
+ 了解 [uts语法](https://doc.dcloud.net.cn/uni-app-x/uts/)[uts原生插件](https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin.html)
shutao-dc's avatar
shutao-dc 已提交
10 11
+ 了解 [vue组件](https://uniapp.dcloud.net.cn/tutorial/vue3-components.html)
+ 了解 [native-view组件](https://doc.dcloud.net.cn/uni-app-x/component/native-view.html)
12

shutao-dc's avatar
shutao-dc 已提交
13
## uts组件-标准模式目录结构
14

15 16
<pre v-pre="" data-lang="">
<code class="lang-" style="padding:0">
shutao-dc's avatar
shutao-dc 已提交
17
┌─components                      // vue组件代码,该文件夹不强制放在此处, 可选
18
|   ├─xxxxxx                      // vue组件名称文件夹  xxxxxx代替组件名称
shutao-dc's avatar
shutao-dc 已提交
19
|       ├─xxxxxx.uvue             // vue组件uts代码 xxxxxx代替组件名称
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
├─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>
41 42
</pre>

shutao-dc's avatar
shutao-dc 已提交
43
如上所示,uts组件-标准模式的目录结构与UTS插件基本相同,差别在于components目录,vue组件代码存放components目录下。
44 45 46

其他目录文件详情可参考[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)

shutao-dc's avatar
shutao-dc 已提交
47
## 开发uts组件
48

shutao-dc's avatar
shutao-dc 已提交
49
### 构建uts组件-标准模式模版
50

shutao-dc's avatar
shutao-dc 已提交
51
HBuilder X 选中你的项目,项目根目录选中uni_modules目录,右键选择新建uni_modules插件,弹窗后分类选择 “uts组件-标准模式”,填写组件名称,以下均已 native-button 为例
52

shutao-dc's avatar
shutao-dc 已提交
53
//截图
54

shutao-dc's avatar
shutao-dc 已提交
55
创建完毕 HBuilder X 会自动构建模版文件,参考:`uts组件-标准模式目录结构`
56

shutao-dc's avatar
shutao-dc 已提交
57
### uts组件-标准模式代码编写
58

shutao-dc's avatar
shutao-dc 已提交
59
#### 添加 native-view
60

shutao-dc's avatar
shutao-dc 已提交
61
构建uts组件后,HBuilder X 会自动创建components/native-button/native-button.uvue文件,在该文件编写代码添加 native-view 标签
62

shutao-dc's avatar
shutao-dc 已提交
63
```ts
64
<template>
65
	<native-view></native-view>
66 67 68
</template>
```

shutao-dc's avatar
shutao-dc 已提交
69 70 71
#### native-view 与 原生对象关联

native-view 初始化会触发 @init 事件,此时创建NativeButton对象,native-button.uvue代码中用NativeButton对象调用插件相关的API。将 UniNativeViewElement 传递给NativeButton对象对象,进行关联绑定
72

shutao-dc's avatar
shutao-dc 已提交
73
[NativeButton](#NativeButton对象)是在utssdk目录构建的原生对象。NativeButton对象内部处理原生view与native-view绑定关联业务
74 75

```ts
76 77 78 79
<template>
	<native-view @init="onviewinit"></native-view>
</template>
... ...
shutao-dc's avatar
shutao-dc 已提交
80
	//引入 NativeButton 原生对象
81 82 83 84 85 86 87 88 89 90
	import { NativeButton } from "@/uni_modules/native-button";
	export default {
		data() {
			return {
				button: null as NativeButton | null
			}
		},
		methods: {
			//native-view初始化时触发此方法
			onviewinit(e : UniNativeViewInitEvent) {
shutao-dc's avatar
shutao-dc 已提交
91
				//获取UniNativeViewElement 实例化NativeButton将element以构造参数传递给NativeButton对象
92 93 94 95 96 97
				this.button = new NativeButton(e.detail.element);
			}
		}
	}
```

shutao-dc's avatar
shutao-dc 已提交
98
#### 组件声明方法
99 100 101

在 methods 节点中添加updateText方法,native-button组件使用者可调用该方法更新native-button文案。 [页面调用组件方法](https://doc.dcloud.net.cn/uni-app-x/vue/component.html#page-call-component-method)

102
```ts
103 104 105 106 107 108 109 110
methods: {
	//对外函数
	updateText(value: string) {
		this.button?.updateText(value)
	}
}
```

shutao-dc's avatar
shutao-dc 已提交
111
#### 组件声明props
112

shutao-dc's avatar
shutao-dc 已提交
113
native-button 声明props,例如native-button的文案信息text属性,按vue规范监听到text属性更新,通过NativeButton对象驱动更新原生view属性,在components/native-button/native-button.uvue编写如下代码,具体参考[vue组件Props规范](https://cn.vuejs.org/guide/components/props.html)
114 115 116 117 118 119 120 121 122

```html
<script lang="uts">
	export default {
		props: {
			"text": {
				type: String,
				default: ''
			}
123
		},
124 125 126 127 128 129 130 131 132 133 134
		watch: {
			"text": {
				handler(newValue : string, oldValue : string) {
					this.value = newValue
					this.button?.updateText(this.value)
				},
				immediate: true
			},
		},
	}
</script>
135 136
```

shutao-dc's avatar
shutao-dc 已提交
137
#### 组件声明事件
138

shutao-dc's avatar
shutao-dc 已提交
139
native-button 声明事件,例如原生组件触发点击事件@buttonTap, NativeButton对象通过 UniNativeViewElement 的 dispatchEvent 函数触发native-view的 @customClick 自定义事件。native-button.uvue监听native-view的 @customClick 自定义事件实现this.$emit触发声明事件,具体参考[vue组件事件规范](https://cn.vuejs.org/guide/components/events.html)
140 141

```html
142 143 144
<template>
	<native-view @customClick="ontap"></native-view>
</template>
145 146 147 148 149 150
<script lang="uts">
	export default {
		methods: {
			ontap(e: UniNativeViewEvent) {
				this.$emit("buttonTap", e)
			}
151 152
		}
	}
153
</script>
154 155 156
```

native-button/components/native-button/native-button.uvue 最终代码如下:
157 158

```html
159
<template>
160 161
	<native-view @init="onviewinit" @customClick="ontap"></native-view>
</template>
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
<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)
			},
193 194
			ontap(e: UniNativeViewEvent) {
				this.$emit("buttonTap", e)
195 196 197 198 199 200 201 202 203
			},
			updateText(value: string) {
				this.button?.updateText(value)
			}
		},
		unmounted() {
			// iOS平台需要主动释放 uts 实例
			this.button?.destroy()
		}
204
	}
205 206 207
</script>
```

shutao-dc's avatar
shutao-dc 已提交
208
#### 实现NativeButton对象
209

shutao-dc's avatar
shutao-dc 已提交
210
utssdk目录实现不同平台的原生NativeButton对象,构造参数获取UniNativeViewElement对象与原生view绑定,封装原生view功能关联的API。
211

212
::: preview
213

214
> Android
215

216
```html
217 218 219 220 221 222
import { Button } from "android.widget"

export class NativeButton {
	$element : UniNativeViewElement;

	constructor(element : UniNativeViewElement) {
shutao-dc's avatar
shutao-dc 已提交
223
		//接收传递过来的UniNativeViewElement
224 225 226 227 228
		this.$element = element;
		this.bindView();
	}

	button : Button | null = null;
229
	bindView() {
230
		//通过UniElement.getAndroidActivity()获取android平台activity 用于创建view的上下文
231 232 233 234
		this.button = new Button(this.$element.getAndroidActivity()!);  //构建原生view
		//限制原生Button 文案描述不自动大写
		this.button?.setAllCaps(false)
		//监听原生Button点击事件
235
		this.button?.setOnClickListener(_ => {
236 237 238 239 240 241
			const detail = {}
			//构建自定义UniNativeViewEvent返回对象
			const event = new UniNativeViewEvent("customClick", detail)
			//触发原生Button的点击事件
			this.$element.dispatchEvent(event)
		})
242 243 244 245
		//UniNativeViewEvent 绑定 安卓原生view
		this.$element.bindAndroidView(this.button!);
	}

246
	updateText(text: string) {
247 248 249 250 251 252 253 254 255 256
		//更新原生Button 文案描述
		this.button?.setText(text)
	}

	destroy(){
		//数据回收
	}
}
```

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
> iOS

```html
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)
	}
}
```

:::

shutao-dc's avatar
shutao-dc 已提交
311
更多实现可参考 UTS组件 [native-button](https://gitcode.net/dcloud/hello-uni-app-x/-/tree/dev/uni_modules/native-button)
312

shutao-dc's avatar
shutao-dc 已提交
313
此时一个简单的标准模式UTS组件就完成了,
314 315

**注意:**
shutao-dc's avatar
shutao-dc 已提交
316
+ UTS组件的 components 目录下的代码中不能含有原生平台任何引用对象,这会导致vue原生组件无法跨平台,与原生平台关联的代码都应放在UTS插件中
317
+ ios平台需要vue组件主动释放 uts 实例,所以页面触发 unmounted 生命周期时需要调用 this.button?.destroy() 避免内存泄露
shutao-dc's avatar
shutao-dc 已提交
318
+ android平台 native-view 组件不支持border、background、box-shadow属性,可以使用view标签包裹native-view,在view标签设置以上属性
319

shutao-dc's avatar
shutao-dc 已提交
320
### 页面引用uts组件
321

shutao-dc's avatar
shutao-dc 已提交
322
以 native-button 为例, 创建uts组件的项目页面可以直接使用 native-button 标签,也可将native-button插件包放置其他项目的uni-modules文件夹中。项目页面即可使用 native-button 标签
323

324 325
```html
<template>
326
	<view style="flex:1">
327 328 329 330 331 332
		<native-button class="native-button" text="buttonText" @buttonTap="ontap"></native-button>
	</view>
</template>

<script>
	export default {
333 334 335
		methods: {
			ontap(e : UniNativeViewEvent) {
			  console.log("ontap----------"+e.type)
336 337 338 339 340 341
			}
		}
	}
</script>

<style>
342 343 344 345
	.native-button {
		height: 100px;
		width: 200px;
		margin: 25px auto 25px auto;
346
	}
347 348
</style>
```