生命周期和模板引用
Vue处理所有的DOM更新,都归功于响应式和声明式渲染;当需要手动更新DOM的时候,我们需要用到模板引用--也就是指向一个DOM元素的ref属性,通过它来实现模板引用。
<p ref="demo">I love China!</p> //ref属性
要访问这个引用时,需要声明一个同名的ref:
const demo =ref(null)
这里注意一下,赋初值要赋为null,因为当<script setup>执行的时候,DOM元素还不存在。模板引用ref只能在组件挂载后访问,要在挂载后执行代码,要用到onMounted()函数:
import {onMounted} from 'vue'
onMounted(()=>{
//此时组件已挂载
})
这被称为生命周期钩子——它允许我们注册一个在组件的特定生命周期调用的回调函数。还有一些其他的钩子如 onUpdated 和 onUnmounted
。有关更多生命周期细节:生命周期钩子 | Vue.js (vuejs.org)
下面是一个简单的例子,添加一个onMounted钩子,通过demo.value访问<p>,可以进行一些DOM操作,比如修改它的内容:
<script setup>
import { ref,onMounted } from 'vue'
const demo = ref(null)
onMounted(()=>{demo.value.textContent="I love chengdu!"})
</script>
<template>
<p ref="demo">I love China!</p>
</template>
结果如下:
侦听器
当我们需要响应的执行一些"副作用"的时候,比如,当数字改变时我们需要将数字输出到控制台,我们就可以使用侦听器来实现它:
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newCount) => {
//console.log() 就是一个副作用,当count的值发生改变时,就会将新的值打印到控制台
console.log('new count is: ${newCount}')
})
watch()
可以直接侦听一个 ref,并且只要 count
的值改变就会触发回调。当然也可以侦听其他类型的数据源,更多细节见:侦听器 | Vue.js (vuejs.org)
一个更为常见的例子是当 Id改变时抓取新的数据,并且在浏览器渲染:
<script setup>
import { ref, watch } from 'vue'
const todoId = ref(1)
const todoData = ref(null)
//async关键字用于声明一个异步函数 await需和async一同使用不可以单独使用,
async function fetchData() {
todoData.value = null //每次触发回调函数的时候,给todoData重新赋值
const res = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}` //json格式的数据的网址
)
todoData.value = await res.json()
//这个意思是要等res.json()执行完成后,才会进行赋值
}
fetchData() //在组件被挂载的时候会调用该函数,使在页面上有相应的显示,而不会是一片空白
watch(todoId, fetchData) //当todoId改变的时候,会调用fetchData()函数
</script>
<template>
<p>Todo id: {{ todoId }}</p>
<button @click="todoId++" v-bind:disabled="!todoData">Fetch next todo</button>
<!--当disabled为false的时候按钮被启用,为true的时候则被禁用-->
<p v-if="!todoData">Loading...</p> <!--当!todoData为真值时才会渲染,这样写可以在页面显示一个Loading的模样,每一次点击按钮都会出现,因为在fetchData()函数里给todoData重新赋值了,调用完函数后todoData就变成了true即执行下面的v-else了-->
<pre v-else>{{ todoData }}</pre>
</template>
通过按钮来改变要抓取数据的id,进而抓取新的数据。
效果图如下: