README.md 13.2 KB
Newer Older
W
wanganxp 已提交
1
# 组件概述
D
DCloud_LXH 已提交
2

W
wanganxp 已提交
3
## 组件定义
D
DCloud_LXH 已提交
4

5
- 组件是视图层的基本组成单元。
W
wanganxp 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
- 组件是一个单独且可复用的UI及配套功能模块的封装。

我们知道js逻辑可以封装为函数或类库。而对于页面上可视的元素,则可以将ui、样式、逻辑一起封装为组件。

组件涉及较多的概念,包括组件名称、开头和闭合标签、组件属性、组件属性值、组件事件、组件vue指令、组件text内容、子组件。

我们先看一个简单的例子:
```vue
<component-name property1="value" property2="value">
	content
</component-name>
```

上面的代码,是一个组件,组件名为component-name,这个组件有2个属性,property1和property2,这2个属性的属性值都是"value",组件的text内容为"content"

然后我们看一个全面但有些复杂的示例,这段示例融合了组件的各种概念:

```vue
<template>
  <view></view>
	<view>
		<text v-if="titleShow" :style="'color:' + titleColor">{{title}}</text> <!-- text组件的text绑定了响应式变量title、v-if指令绑定了titleShow、style绑定了titleColor-->
	</view>
	<image src="http://www.noexit.jpg" @error="imgerror"/>
	<scroll-view >
		<button type="primary" @click="buttonClick_changeText">修改文字内容</button>
		<button @click="buttonClick_showHide">点击让文字组件显示或消失</button>
		<button @click="buttonClick_changeColor">修改文字颜色</button>
	</scroll-view>
</template>
<script setup>
  let title = ref("Hello world") //定义一个响应式变量title,默认赋值为hello world
	const buttonClick_changeText = () => {
		title.value = "新文字内容" //对响应式变量title的.value属性赋值,界面上文字会自动同步修改
	}
	
	let titleShow = ref(true) //决定标题文字是否显示
	const buttonClick_showHide = () => {
		titleShow.value = !titleShow.value //对响应式变量的.value属性赋值,界面上文字组件的v-if指令绑定了titleShow,所以会动态显示消失
	}
	
	let titleColor = ref("black") //定义一个响应式变量titleColor,默认为黑色
	const buttonClick_changeColor = () => {
		titleColor.value = "red" //对响应式变量的.value属性赋值,界面上文字组件的style属性绑定了titleColor,所以会变为红色
	}
	
	const imgerror = (event : ImageErrorEvent) => { // image组件加载失败时触发
		console.log(event.type, event.detail); //错误的详情
	}
</script>
```

所有组件,都写在template标签下面。

- 组件的名称和开始/结束标签
每个组件,都有开始和结束标签。\
标签由尖括号包裹,它有开始标签和结束标签。结束标签的`<`后面用`/`来表示结束。结束标签也称为闭合标签。
比如上面例子中template节点下第一个子节点 <view></view> ,view 表示这个组件的名称,<view>为开始标签,</view>为闭合标签。这是一个空的view视图组件。

如果标签没有text内容或子组件,可以写成 自闭合标签,即只写 开始标签,并且 开始标签 以 `/>` 结尾。\
比如上面例子中的 `<image src="http://www.noexit.jpg" @error="imgerror"/>`

- 组件内容text
指组件的内容区,即组件的开始标签和闭合标签之间的文字内容。\
比如上面例子中button组件中的“修改文字内容”。\
uni-app x中只有button、text组件等少数组件支持内容区,具体需查阅每个组件文档。

- 子组件
组件的内容区可以不是文字,而是下级组件。\
比如上面例子中view组件的子组件是text组件,而scroll-view组件下面有3个button子组件。\
并非所有组件都支持子组件,一般视图组件肯定是支持子组件的,其他组件需要查阅组件的文档说明。

- 组件属性
组件开始标签的组件名称后面,以空格分割的、以等号赋值的,不以v-或@开头的普通属性。\
比如上面例子中button组件的[type属性](../component/button.md),它定义了组件的一些控制参数,这是由组件作者给使用者提供的自定义参数。\

- 组件属性值
在属性名后面用=号赋值的内容。\
比如上面例子中button组件的type属性,其属性值为primary,`type="primary"`,即表示一个主按钮。\

- 事件
组件在发生某些事件后触发的函数。\
比如上面例子中button组件的click事件。`@click="buttonClick_changeText"`\
buttonClick_changeText 是script里定义的一个函数。\
事件区别于普通属性名的特征是以@开头,事件值指向一个函数(选项式指向一个method)。\
很多事件还有event参数。\
比如上面例子中image组件的error事件,绑定到imgerror函数,它有一个参数event对象,类型是ImageErrorEvent。接下来的代码打印了event对象的2个属性。

- vue指令
vue提供的一批特殊写法的属性,它们以v-开头,比如上面例子中text组件的v-if指令,绑定了一个titleShow的响应式变量,根据变量的true或false可以决定text组件是否显示。详见[vue指令](./built-in.md)\
有一种特殊指令`v-bind`,一种把属性值变成script以便绑定响应式变量的写法,它的完整写法是 v-bind:普通属性名 = "属性值",
但它更常见的写法是简写为在普通属性前面加个冒号,比如上面例子中text组件的:style,`:style="'color:' + titleColor"`\
这个写法的意思是,text组件的style样式中,color属性的值绑定到了script定义的响应式变量titleColor上,修改这个响应式变量的值,text组件的文字颜色就会跟着变化。\
绑定后属性值的内容变成了script,而不再是普通字符串。所以在属性值里写字符串需要再加单引号。


组件们,有公共的属性和事件,[详见](../component/common.md),也有组件特有的属性和事件,详见每个组件的文档。

每个组件可以有多个属性、指令、事件,用空格分割。它们赋值的=号,前后可以允许0个或1个空格。

所有组件与属性名都是**小写**,单词之间以连字符`-`连接。

## 组件的分类

uni-app x文档规范中有一批标准组件,同时也支持扩展自定义组件。

### 1. 标准组件
- 1.1 内置组件
内置在uni-app x引擎中,开发者无需在代码中引用和注册的,可以直接使用。比如view、text、button...
- 1.2 ext组件
在app平台,对于不太常用、体积又大的官方基础组件,虽然其文档在uni-app x的官方文档中,但并没有内置到uni-app x引擎中。需要开发者下载ext组件到项目下才能使用。\
出现这种情况一般是由于小程序规范里内置了该组件,而App端又不常用。(为了多端兼容,uni的组件规范是参考小程序组件规范制定的)\
比如[animation-view组件](./animation-view.md)\
除了ext组件,还有ext api,它们情况类似,详细介绍:[ext插件](https://uniapp.dcloud.net.cn/api/extapi.html)

### 2. 自定义组件

标准组件只是一些基础组件。开发者还可以自行扩展组件,封装UI和逻辑,称为自定义组件。

这类组件需要手动下载到项目中,或者自行在项目下编写。

自定义组件,按开发方式分类,又有2种:前端uvue组件 和 原生uts组件

- 2.1 前端uvue组件
即开发者自己按照vue组件规范编写的uvue文件。这种组件一般由前端工程师编写。详见[uvue组件模型介绍](../vue/component.md)
- 2.2 原生uts组件
这是一种App平台专用的扩展机制。
由Android或iOS的原生开发者,按照uts插件的组件规范编写,把原生的view嵌入到uvue页面上,它在编写时贴近但不完全是vue组件开发规范。\
不过对于组件的使用者来讲,用法就是标准的uvue组件了。详见[uts组件开发指南](../plugin/uts-component.md)\
uts原生组件,下载组件到项目后(或自己按规范编写),在页面template里直接引用即可。无需导入注册组件。

对于前端uvue组件,又有2种引用方式。
1. 传统vue组件:
需要先import、注册,然后再在页面template中使用。[详见](../vue/component.md#manual-import-component)
2. easycom组件
easycom组件是uni-app提供的一种易用方式,它通过一个路径规范让编译器知道组件的位置,实现自动的import和注册。详见[easycom组件规范](../vue/component.md#easycom)
142

W
wanganxp 已提交
143
在uni插件市场([https://ext.dcloud.net.cn/](https://ext.dcloud.net.cn/)),下载的组件基本都是easycom组件规范或uts原生组件规范,都是在页面里可以直接引用的。
144

W
wanganxp 已提交
145
插件市场的功能较多,可以看介绍了解:[详见](https://uniapp.dcloud.net.cn/plugin/plugin-ext-introduction.html)
146

W
wanganxp 已提交
147 148 149
## 其他组件概念
- datacom
`datacom`是一种数据驱动的组件,只需要给出符合格式的数据就可以使用。它是uvue组件的子类,尤其适合云端一体组件。详见:[datacom介绍](https://uniapp.dcloud.net.cn/component/datacom.html)
D
DCloud_LXH 已提交
150

W
wanganxp 已提交
151 152 153
- uni_modules
`uni_modules`是uni-app生态的包管理方案。非内置组件,可以放在项目下任意位置,也可以封装在`uni_modules`下。一般对外提供的成熟组件都应该封装在`uni_modules`下。\
如果还不了解`uni_modules`,那务必需要阅读:[uni_modules介绍](https://uniapp.dcloud.net.cn/plugin/uni_modules.html)
154 155


W
wanganxp 已提交
156 157 158
## 组件的编写
- 前端uvue组件的开发指南:[详见](../vue/component.md)
- uts原生组件的开发指南:[详见](../plugin/uts-component.md)
D
DCloud_LXH 已提交
159

W
wanganxp 已提交
160 161 162
组件开发完毕后可发布到插件市场,插件作者指南:[详见](https://uniapp.dcloud.net.cn/plugin/publish.html)

<!-- TODO下面这段应该挪走 -->
D
DCloud_LXH 已提交
163 164
## 调用组件方法@methods

D
DCloud_LXH 已提交
165
需要把组件分为 内置组件、easycom组件、非easycom组件,这3种组件有不同的方法调用方式。[详情](../vue/component.md#page-call-component-method)
D
DCloud_LXH 已提交
166 167 168 169 170

### 内置组件的方法调用或设置属性

> 3.93+ 支持

D
DCloud_LXH 已提交
171
使用 `this.$refs` 获取组件并as转换为组件对应的element类型,通过 `.`操作符 调用组件方法或设置属性。[详情](../vue/component.md#call-builtin-component-method)
D
DCloud_LXH 已提交
172 173 174 175 176

### easycom组件调用方法或设置属性@method_easycom

> 3.97+ 支持 uni_modules 目录下的组件

D
DCloud_LXH 已提交
177
easycom组件,用法和内置组件一样。也是使用 `this.$refs` 获取组件并转换为组件的类型,通过 `.`操作符 调用组件方法或设置属性。[详情](../vue/component.md#call-easycom-component-method)
D
DCloud_LXH 已提交
178 179 180 181 182

### 其它自定义组件的方法调用使用callMethod@$callMethod

如果不是内置组件,也不是easycom组件,那么无法使用`.`操作符了。

D
DCloud_LXH 已提交
183
此时需使用 `this.$refs` 获取组件实例,然后通过 `$callMethod` 调用组件的方法。也就是把组件的方法名、参数,当做callMethod的参数来传递。此时也就没有`.`操作符那样的代码提示和校验了。[详情](../vue/component.md#call-component-method)
D
DCloud_LXH 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210

## 如何开发同时兼容 uni-app x 和 uni-app 的组件

目前有两种方案:

- 目录下同时提供uvue,vue文件,分别适配 uni-app x 和 uni-app

组件作者在 uvue 和 vue 文件中可以自由使用各自的特性,比如 vue 中可以任意使用 js 或 ts 来书写代码,

如果部分组件逻辑被抽离为单独的文件,需要分别命名为各自环境支持的文件类型,导入时不同平台支持的文件类型也不同,

比如 uvue 文件目前不支持引入js或ts,而 vue 文件不能引入 uts 文件

对于现有的 uni-app 组件,通过新建 uvue 文件来渐进式支持 uni-app x,可以避免对已有 uni-app 项目造成影响

- 仅提供一个vue文件,同时适配 uni-app x 和 uni-app

该方案,需要script节点配置lang="ts",这样才可以在 uni-app 项目中正常书写带有类型的代码,而在 uni-app x 项目中,则会忽略 lang="ts",当做 uts 代码编译。

当需要区分平台或项目类型时,可以使用对应的条件编译。

<!-- 比如,当需要在 css 中区分原生渲染和webview渲染时

可以通过 APP-UVUE(表示在 uni-app x 项目app端的Android和iOS原生渲染)、APP-NVUE(表示在 uni-app 项目app端的nvue页面原生渲染) 区分,

`#ifdef APP-UVUE || APP-NVUE` 可以表示原生渲染,使用 `ifndef` 则可以取反表示为webview渲染,如 `#ifndef APP-UVUE || APP-NVUE`
 -->
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
211 212 213 214 215
比如通过 UNI-APP-X 来区分项目类型,更多条件编译见:[详情](https://uniapp.dcloud.net.cn/tutorial/platform.html)


### vue 与 uvue 不同文件后缀的优先级 @priority

W
wanganxp 已提交
216
新建组件时(注意不是新建页面),默认组件的后缀名为.uvue,但也支持.vue。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229

.vue里面写uvue的语法,可以正常被.uvue页面引用和编译。

.vue里写条件编译,可以制作同时满足uni-app和uni-app x的组件。

.vue中适用于uni-app x的条件编译区域内的代码,必须符合uni-app x的规范。如果使用uni-app x不支持的、uni-app js引擎版特有的功能,会报错。

当你手动import或easycom手动配置规则,可以指定文件名后缀。比如`import PageHead from '@/components/page-head.uvue'`

但如果未明确指定组件后缀名的情况,且同一个组件目录下即存在.vue文件、又存在.uvue文件,
此时 `vue` 组件和 `uvue` 组件的优先级如下:
-`uni-app x` 中,优先使用 `uvue` 组件,如果不存在 `uvue` 组件,则使用 `vue` 组件。
-`uni-app` 中,只支持使用 `vue` 组件。