# Vue3教程 - 15 ref与$parent
如果想获取元素和组件的 DOM,可以使用标签的 ref
来实现。
ref
可以添加在普通的 HTML 标签上,也可以添加在组件标签上:
- 添加在普通的HTML标签上,获取的是 DOM 节点;
- 添加在 Vue 组件标签上,获取的是组件实例。
如果在以前,我们会使用 document.getElementById()
的方式来获取到 DOM 元素:
<template>
<div>www.doubibiji.com</div>
<div id="title-div">逗比笔记</div>
<button @click="getDom">获取DOM</button>
</template>
<!-- setup -->
<script lang="ts" setup>
// 获取Dom
function getDom() {
let titleDiv = document.getElementById('title-div')
console.log(titleDiv)
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
但是在 Vue 中不推荐使用这种方式,在 Vue 中,我们会定义很多的组件,一个页面是可能是由不同的人开发的不同的组件,组件的ID 很可能会存在重复的情况,所以使用这种方式,会导致冲突。
# 15.1 普通元素添加ref属性
下面就来介绍使用 ref
属性来获取 DOM。
- 给标签添加一个
ref
属性; - 使用
ref
定义一个变量,这个变量的名称需要和标签中的ref
的属性值相同。
<template>
<div>www.doubibiji.com</div>
<div ref="title">逗比笔记</div>
<button @click="getDom">获取DOM</button>
</template>
<!-- setup -->
<script lang="ts" setup>
import { ref } from 'vue';
// 创建一个title变量,用于存储元素的内容
// 这里的名称需要和标签的ref的名称对应
let title = ref()
// 获取Dom
function getDom() {
// 直接输出title.value
console.log(title.value) // <div>逗比笔记</div>
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
通过 let title = ref()
就可以获取到 ref="title"
的元素。
# 15.2 组件上添加ref属性
同样,ref
属性还可以添加到组件上,可以通过ref
属性获取到组件实例。
定义一个 Person 组件:
<template>
<div>{{ name }}</div>
<div>{{ age }}</div>
</template>
<!-- setup -->
<script lang="ts" setup>
import { ref } from 'vue';
let name = ref('Doubi')
let age = ref(13)
// 导出变量
defineExpose({ name, age })
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这里要解释一下,这里使用了 defineExpose
函数,这个函数的参数是一个对象,作用是导出组件中的数据。
在这里通过 defineExpose
导出的数据,待会在父组件中使用 Person 组件并通过 ref
属性获取 Person 组件实例的时候,可以获取到这些导出的数据。
在父组件中使用 Person 组件并添加 ref
属性:
<template>
<Person ref="person" />
<button @click="changePerson">修改Person</button>
</template>
<!-- setup -->
<script lang="ts" setup>
import { ref } from 'vue';
// 引入person组件
import Person from '@/components/Person.vue';
// 获取到Person组件实例
let person = ref()
function changePerson() {
// 获取组件中的使用defineExpose导出的变量
console.log(person.value.name)
// 修改子组件的值
person.value.name = 'Niubi';
person.value.age = 14;
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
在上面的代码中,引入并使用了 Person 组件,在使用的时候,添加了 ref
属性。在脚本中通过 let person = ref()
获取到的就是组件的实例了。
此时通过 person.value.domain
就可以获取到组件中通过 defineExpose()
函数导出的数据,否则是获取不到的。
这样通过 ref
就实现了在父组件中修改子组件中的数据。
其实在父组件中还可以通过一个 $refs
获取所有带 ref
属性的子元素。
举个栗子:
<template>
<Person ref="p1" />
<Person ref="p2" />
<button @click="getAllChild($refs)">获取所有子组件实例</button>
</template>
<!-- setup -->
<script lang="ts" setup>
import { ref } from 'vue';
// 引入person组件
import Person from '@/components/Person.vue';
function getAllChild(refs: any) {
// refs 是所有子组件列表
for (let key in refs) {
// 获取子组件的属性
console.log('name:', refs[key].name);
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
了解一下。
# 15.3 $parent
上面通过 ref 实现在父组件中修改子组件中的数据,还可以在子组件中,通过 $parent
修改父组件中的数据。
首先在父组件中定义数据:
HomePage.vue
:
<template>
<div>{{ domain }}</div>
<div>{{ title }}</div>
<Person />
</template>
<!-- setup -->
<script lang="ts" setup>
import { ref } from 'vue';
import Person from '@/components/Person.vue';
let domain = ref('www.doubibiji.com');
let title = ref('逗比笔记');
// 导出数据
defineExpose({ domain, title })
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在父组件中使用 defineExpose()
导出数据,这样在子组件中才能获取父组件的数据。
在子组件通过 $parent
来获取父组件,然后获取父组件的数据。
Person.vue
子组件:
<template>
<button @click="changeParentData($parent)">修改父组件数据</button>
</template>
<!-- setup -->
<script lang="ts" setup>
function changeParentData(parent: any) {
console.log('domain:', parent.domain);
parent.domain = 'doubibiji.com';
parent.title = '我的笔记';
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
在子组件中,通过 $parent
获取到父组件,然后传递给函数,在函数中通过父组件修改父组件的数据。
这样通过 $parent
就实现了在子组件中修改父组件中的数据。