idref.md 4.6 KB
Newer Older
D
DCloud_LXH 已提交
1 2 3 4 5 6
# 组件标志

开发者会遇到很多与组件标志有关的概念:id、ref、Element、NodeRef、context、ComponentPublicInstance...

上述概念,其实都是为了给组件一个标记,通过标记拿到组件的上下文对象,然后操作这个对象的方法。

W
wanganxp 已提交
7
但因为平台不同,制造了不同的概念。id在web和小程序中存在,NodeRef是小程序的概念、ref和ComponentPublicInstance是vue的概念。uni-app中这些皆而有之。
D
DCloud_LXH 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

我们以video为例,解释这些概念的相同和差别之处。

## web开发中
### 内置html标签
html内置标签有id属性,通过document.getElmenetById("")可以返回一个Element。可以进一步调用Element的方法
```html
<video id="vid" src="uni.mp4"></video>
<script>
    document.getElementById("vid").play() //js写法
	(document.getElementById("vid") as HTMLVideoElement).play(); //ts写法。只有HTMLVideoElement才有play方法
</script>
```

### vue自定义组件@vuecomponent
W
wanganxp 已提交
23
vue框架中组件有ref属性,选项式中通过this.refs可以返回一个组件实例ComponentPublicInstance,组合式则是定义一个同名的ref()变量。得到组件实例可以进一步调用组件的属性和方法。
D
DCloud_LXH 已提交
24 25 26

对于html内置元素,在web中一般不通过ref获取。ref更多是服务于自定义的vue组件。

W
wanganxp 已提交
27 28
但在uni-app x中,ref获取内置组件时,App和Web平台得到的是UniElement。获取非内置组件才是vue组件实例。

D
DCloud_LXH 已提交
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
假使有一个vue组件,其有一个方法getSome(),那么用法是:\
template区:
```html
<component1 ref="c1"></component1>
```
scrip区:
```js
this.$refs.c1.getSome() //js写法
this.$refs["c1"].getSome() //与上一行等价
(this.$refs["c1"] as ComponentPublicInstance).getSome() //ts或uts写法,必须明确类型才能调用其方法和属性
```

## 小程序中
### 小程序内置组件
小程序的内置组件有id属性,有多种方式获取组件上下文对象:
1. 通过uni.createXXXContext来获取,比如uni.createVideoContext()
template区:
```html
<video id="vid" src="uni.mp4"></video>
```

scrip区:
```js
uni.createVideoContext('vid').play()
```

2. 通过uni.createSelectorQuery(),传入选择器,拿到返回的NodesRef,然后再.context,异步获取到组件的上下文对象
```js
  uni.createSelectorQuery().select('.the-video-class').context(function(res){
    console.log(res.context) // 节点对应的 Context 对象。如:选中的节点是 <video> 组件,那么此处即返回 VideoContext 对象
  }).exec()
```

W
wanganxp 已提交
62 63
一般推荐使用第1种方法,也就是createXXContext方式。这种方式简洁并且可以跨平台。

D
DCloud_LXH 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
### vue自定义组件
uni-app编译到小程序时,vue组件的用法与web相同,具体[见上](#vuecomponent)

## uni-app x中

uni-app x中,web、小程序、vue这3类概念都支持,所以id、ref、Element、NodeRef、context、ComponentPublicInstance这些概念都存在。

分为如下几类:

### 内置组件
内置组件都支持Element。

为了与小程序api拉齐,也有部分组件同时支持context,如video。

不涉及小程序api拉齐的一些组件未提供context,比如`<unicloud-db>`组件只有Element。

#### Element方式

uni-app x提供了[uni.getElementById](../api/get-element.md)方法,返回的是[Element](../dom/element.md)类型。

通用的元素操作方法,比如getAttribute、setStyle,在Element上就可以操作。

86 87
但是由于本方法不与页面绑定,获取的是栈顶页面的element,所以可能发生预期外的情况,[详见](../api/get-element.md)

W
wanganxp 已提交
88
UniVideoElement 继承自 UniElement,拥有video专用的一批方法。
D
DCloud_LXH 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

template区:
```html
<video id="vid" src="uni.mp4"></video>
```
script区:
```uts
(uni.getElementById("vid") as UniVideoElement).play() //注意没有document对象,getElementById方法在uni下。务必确保vid存在,否则as会崩溃
uni.getElementById<UniVideoElement>("vid")!.play() //泛型写法
```

#### context方式
script区:
```uts
uni.createVideoContext("vid")!.play()
```

#### NodeRef方式
uni-app x 虽然支持 `uni.createSelectorQuery()` API,传入选择器,可以拿到返回的NodesRef。但无法继续获取.context子对象。无法通过这种方式拿到context。

#### ref方式
110 111 112

其实`this.$refs`获取到的内置组件,通过as也可以转换为Element。

W
wanganxp 已提交
113
`uni.getElementById`相比,`this.$refs`方式与调用页面绑定。
114

D
DCloud_LXH 已提交
115 116 117 118 119 120 121 122 123
script区:
```js
(this.$refs['vid'] as UniVideoElement).play(); //但一般ref用于vue自定义组件
```


### vue自定义组件

uni-app x中vue组件的用法与web相同,具体[见上](#vuecomponent)