详细分析Vue3中的watch和onMounted基本知识以及差异(附Demo)

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 加载数据,并在模板中显示结果

  1. 使用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 }
);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农研究僧

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值