模板:
<tremplate>
<div ref="element"></div>
</template>
脚本:
export default {
setup() {
const element = ref(null);
return {
element,
};
},
};
这是在vue3中定义ref的正常方式,但使用JavaScript方式。如果我使用TypeScript,我将需要为值element
定义一个类型,对吗?
如何确保值element
的类型正确?
好吧,这将取决于您是否需要键入它并提供成员信息(公共属性、方法等(。如果你这样做了,那么是的,你需要为它定义一个类型;否则,您不必这样做,并且可以简单地使用.value
访问展开的引用,从而将其保留为类型any
(我敢打赌您已经找到了这个(。
但是,如果必须这样做,您需要告诉编译器它是什么,或者它将被分配给什么。为此,您需要使用ref
的第三个重载(没有参数(,并将泛型类型显式设置为所需类型——在您的情况下,您需要HTMLDivElement
(如果您不关心它必须提供的特定成员,则只需要HTMLElement
(。
export default defineComponent({
setup() {
const el = ref<HTMLDivElement>();
onMounted(() => {
el.value // DIV element
});
return {
el
}
}
})
在JavaScript中,您没有类型检查,所以在ref
函数上传递null
和不传递任何内容一样好(这对模板引用来说尤其好(*;从某种意义上说,它甚至可能被认为是误导性的,即展开的值实际上解析为其他但null
。
*当使用组合物API时;反应性参考文献";以及";模板引用";是统一的。我们之所以在挂载的钩子上访问这种特定类型的ref
,是因为DOM元素将在初始渲染后分配给它。
参考文献:
- https://v3.vuejs.org/guide/composition-api-template-refs.html#template-参考文献
<template>
<ChildComponent ref="childRef">
</template>
<script lang="ts" setup>
import ChildComponent from './ChildComponent.vue'
import { ref } from 'vue'
const childRef = ref<InstanceType<typeof ChildComponent>>()
childRef.value.childMethods()
</script>
行不正确:
const el = ref<HTMLDivElement>();
el
不是HTMLDivElement。相反,它是元素的代理。该代理的$el
是实际的HTMLDivElement。虽然我不确定我是否做对了。在一个组件中,我设法将其键入如下:
import { ComponentPublicInstance, defineComponent, ref } from 'vue';
export default defineComponent({
// snipped...
setup() {
const field = ref<ComponentPublicInstance<HTMLInputElement>>();
return {
field,
fun() { field.value.$el.value = 'some value'; }
};
}
// snipped...
});
Vue 3成分API
<template>
<input ref="fileInput" style="display: none;" type="file" @change="onFileSelected" />
<button @click="fileInput?.click()">Pick Files</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const fileInput = ref<HTMLDivElement | null>(null)
function onFileSelected(event: any) { console.log("Event: " + event) }
</script>
第二个例子
<template>
<div ref="coolDiv">Some text</div>
<button @click="changeCoolDiv">Pick Files</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const coolDiv = ref<HTMLDivElement>()
function changeCoolDiv() {
if(coolDiv) {
coolDiv.value // Div element
}
}
</script>
来自Vue 3文档:
默认情况下,使用<script setup>
的组件是关闭的,即通过模板引用或$parent
链检索的组件的公共实例将不会公开内部声明的任何绑定。
要显式公开组件中的属性,请使用defineExpose编译器宏:
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
defineExpose({
a,
b
})
</script>
当父级通过模板引用获得该组件的实例时,检索到的实例的形状将为{ a: number, b: number }
(引用会像普通实例一样自动展开(。
示例代码
从文档:
组件MyModal.vue
:
<script setup lang="ts">
import { ref } from 'vue'
const isContentShown = ref(false)
const open = () => (isContentShown.value = true)
defineExpose({
open
})
</script>
父组件App.vue
:
<script setup lang="ts">
import MyModal from './MyModal.vue'
const modal = ref<InstanceType<typeof MyModal> | null>(null)
const openModal = () => {
modal.value?.open()
}
</script>
import { VNodeRef } from 'vue';
您可以使用VNodeRef。
const swiperRef = ref<VNodeRef>();
如果使用vue-class-component
软件包(此处为beta v8,但与@Component
相同,而不是@Option
(:
<template>
<div ref="element">
<MyOtherComponent ref="otherComponent" />
</div>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component'
import MyOtherComponent from '../MyOtherComponent.vue'
@Options({
components: {
MyOtherComponent,
},
})
export default class MyComponent extends Vue {
$refs!: {
element: HTMLDivElement,
otherComponent: InstanceType<typeof MyOtherComponent>,
}
mounted() {
this.$refs.otherComponent.myOtherComponentMethod()
}
}
</script>