1. 前言
用于处理不同的场景
- watch 用于数据变化的监听,可以在数据发生变化时执行代码,而 onMounted 用于组件初次渲染后的操作
- watch 是响应式的,可以监听一个或多个数据源的变化,而 onMounted 只会在组件首次渲染时调用一次
1. watch
watch 是 Vue 3 的一个响应式 API,用于监听数据的变化
当被监听的数据发生变化时,watch 允许你执行相应的代码逻辑
适用于如下场景:
- 需要在数据变化时执行副作用,如调用 API、更新其他数据、进行计算等
-处理复杂的数据变化逻辑或异步操作
import { ref, watch } from 'vue';
export default {
setup() {
const count = ref(0);
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});
return { count };
},
};
第一个参数是需要监听的数据源,可以是一个响应式数据(ref、reactive)或函数
第二个参数是回调函数,当数据源发生变化时执行
2. onMounted
用于在组件挂载到 DOM 后执行某些逻辑,类似于 Vue 2 中的 mounted 钩子
- 参数:是一个回调函数,在组件挂载后调用
- 场景:需要在组件初次渲染完成后执行操作,如数据获取、初始化操作、与 DOM 交互等
import { onMounted } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('Component is mounted');
});
},
};
3. Demo
watch:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="count++">Increment</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const count = ref(0);
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});
return { count };
},
};
</script>
onMounted:
<template>
<div>
<p>Welcome to the Vue app!</p>
</div>
</template>
<script>
import { onMounted } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('Component is mounted');
});
},
};
</script>
综合使用:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="count++">Increment</button>
</div>
</template>
<script>
import { ref, watch, onMounted } from 'vue';
export default {
setup() {
const count = ref(0);
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});
onMounted(() => {
console.log('Component is mounted');
});
return { count };
},
};
</script>
3. 实战
举例一些实战中用到的Demo
在组件挂载后从 API 加载数据,并在模板中显示结果
- 使用watch
<template>
<el-button
type="primary"
:disabled="formType === 'detail'"
plain
@click="handleSaveRefresh(formData.id)"
v-hasPermi="['dangerous:appointment-commission:enterSiteRefresh']"
>
<Icon icon="ep:document" class="mr-5px" /> 保存当前页
</el-button>
集装箱数量:{{ totalItemCount }}
</template>
<script setup>
import { ref, onMounted } from 'vue';
import AppointmentCommissionApi from 'path-to-your-api'; // 请根据实际路径修改
const totalItemCount = ref(0);
const formData = ref({
id: 1, // 假设你有一个ID,如果是动态的,请根据实际情况设置
value: {
list: []
}
});
onMounted(async () => {
const data = await AppointmentCommissionApi.getEnterSiteListByAppointmentId(formData.value.id);
totalItemCount.value = data.length;
});
const handleSaveRefresh = (id) => {
// 你的保存刷新逻辑
};
</script>
watch结合watchEffect
watchEffect 用于实时更新 totalItemCount
<template>
<el-button
type="primary"
:disabled="formType === 'detail'"
plain
@click="handleSaveRefresh(formData.id)"
v-hasPermi="['dangerous:appointment-commission:enterSiteRefresh']"
>
<Icon icon="ep:document" class="mr-5px" /> 保存当前页
</el-button>
集装箱数量:{{ totalItemCount }}
</template>
<script setup>
import { ref, watch, watchEffect } from 'vue';
import AppointmentCommissionApi from 'path-to-your-api'; // 请根据实际路径修改
const formData = ref({
id: 1, // 假设你有一个ID,如果是动态的,请根据实际情况设置
value: {
list: []
}
});
const totalItemCount = ref(0);
const fetchData = async (id) => {
try {
console.log('Fetching data for ID:', id); // 打印 ID
const data = await AppointmentCommissionApi.getEnterSiteListByAppointmentId(id);
console.log('Data:', data); // 打印返回的数据
formData.value.list = data;
totalItemCount.value = data.length;
} catch (error) {
console.error('Error fetching data:', error);
}
};
// 使用 watch 监听 formData.value.id 的变化
watch(
() => formData.value.id,
(newId) => {
if (newId) {
fetchData(newId);
}
},
{ immediate: true } // 立即执行一次,以确保初始数据加载
);
// 使用 watchEffect 实时更新 totalItemCount
watchEffect(() => {
totalItemCount.value = formData.value.list.length;
});
const handleSaveRefresh = (id) => {
// 你的保存刷新逻辑
};
</script>
如果有多个监听,也可使用多个watch
// 使用 watch 监听 formData.value.id 的变化
watch(
() => formData.value.id,
(newId) => {
if (newId) {
fetchData(newId);
}
},
{ immediate: true } // 立即执行一次,以确保初始数据加载
);
// 使用 watch 深度监听 formData.value.list 的变化
watch(
() => formData.value.list,
(newList) => {
totalItemCount.value = newList.length;
},
{ deep: true }
);