Ala*_*lan 8 vue.js vuejs3 vue-composition-api
我是 Vue Composition API 的新手,需要使用document.querySelector
. 但是,它并没有按预期工作。如果我写
<nav class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed">
<script setup>
import { ref } from "vue";
const observer = new IntersectionObserver(handleIntersection);
const target = document.querySelector(".home-menu");
observer.observe(target);
console.log(target);
Run Code Online (Sandbox Code Playgroud)
target
是null
。阅读文档,我看到了该ref
属性,如果我
<nav ref="navbar" class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed">
<script setup>
import { ref } from "vue";
const target = ref("navbar");
console.log(target);
Run Code Online (Sandbox Code Playgroud)
记录一个对象。
是ref
在 Composition API 中获取 DOM 元素的方式吗?
我现在可以target
在我的观察者对象中使用吗?
它相当于吗querySelector
?
我试过
import { ref } from "vue";
const observer = new IntersectionObserver(handleIntersection);
const target = ref("navbar");
observer.observe(target);
Run Code Online (Sandbox Code Playgroud)
但得到这个错误:
未捕获类型错误:IntersectionObserver.observe:参数 1 未实现接口 Element。
Dar*_*kes 14
document.querySelector
返回的原因null
是 DOM 还不包含该元素。该script setup
函数在组件创建时运行,因此组件的 DOM 尚未创建。
您可以使用onMounted
生命周期挂钩在组件安装后运行代码。我创建了一个游乐场来演示这一点。
来自生命周期文档:
例如,
onMounted
钩子可用于在组件完成初始渲染并创建 DOM 节点后运行代码
那么有两种方法可以实现你想要的。您可以使用继续使用querySelector
,也可以使用模板引用。就我个人而言,我将模板引用用于静态元素(例如导航栏等)和querySelector
动态选择。
模板引用是常规的 Vue 引用,但通过属性将其连接到元素或子组件,ref
您可以获得对该元素或组件的直接引用。
如果将其连接到一个元素,则该值将是该元素;如果将其连接到子组件,则该值将是该组件的组件实例;如果没有任何东西与之连接,则该值为null
。
创建一个参考:
const navbar = ref(null);
Run Code Online (Sandbox Code Playgroud)
这将用于引用该元素。
通过将元素上的属性设置ref
为用于模板引用的名称,将模板引用连接到元素:
<nav ref="navbar" ...>
Run Code Online (Sandbox Code Playgroud)
解释模板参考文档:
ref
是一个特殊属性。它允许我们在安装后获取对特定 DOM 元素或子组件实例的直接引用。
安装组件时连接观察者:
onMounted(() => {
observer.observe(navbar.value);
})
Run Code Online (Sandbox Code Playgroud)
再次解释一下文档:请注意,您只能在安装组件后
才能访问 ref 。如果您在此之前尝试访问,则会出现. 这是因为该元素直到第一次渲染后才存在!navbar
null
或者(见下文),在卸载组件时断开观察者的连接:
onBeforeUnmount(() => {
observer.disconnect();
})
Run Code Online (Sandbox Code Playgroud)
请注意,我认为这在技术上没有必要,因为当组件被销毁时,观察者应该被垃圾收集。
你可以摆弄我在 SFC Playground 中做的这个实验,尝试创建内存泄漏。
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
const el = ref(null);
const observer = new IntersectionObserver((entries, observer) => {
console.log(entries)
});
onMounted(() => {
observer.observe(el.value)
})
// Probably optional
onUnmounted(() => {
observer.disconnect()
})
</script>
<template>
<div ref="el">
I'm the target!
</div>
</template>
Run Code Online (Sandbox Code Playgroud)
querySelector
或者,您仍然可以使用querySelector
. 同样的生命周期注意事项也适用。
<nav class="home-menu ...">
Run Code Online (Sandbox Code Playgroud)
onMounted(() => {
const target = document.querySelector(".home-menu");
observer.observe(target);
})
Run Code Online (Sandbox Code Playgroud)
<script setup>
import { onMounted, onUnmounted } from "vue";
const observer = new IntersectionObserver((entries, observer) => {
console.log(entries)
});
onMounted(() => {
const target = document.querySelector(".target");
observer.observe(target);
})
// Probably optional
onUnmounted(() => {
observer.disconnect()
})
</script>
<template>
<div class="target">
I'm the target!
</div>
</template>
Run Code Online (Sandbox Code Playgroud)
这是生命周期文档中的图表:
console.log(target)
记录对象的原因是因为 Vue ref是一个对象。实际值是通过value
属性访问的。
这样做的技术原因是,Vue 可以检测何时访问该属性,并发挥其反应魔法;包括完全重新分配值的情况。
您可以使用该ref
方法,调用与模板中声明的 ref 同名的变量:
const navbar = ref(null);
Run Code Online (Sandbox Code Playgroud)
但是,您应该等待组件安装后才能观察到:
onMounted(() => {
observer.observe(target);
})
Run Code Online (Sandbox Code Playgroud)
卸载组件时还记得断开连接:
onBeforeUnmount(() => {
observer.disconnect();
})
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
18219 次 |
最近记录: |