vue3之watch多个源

watchAPI 与选项式 API this.$watch (以及相应的 watch 选项) 完全等效。watch 需要侦听特定的数据源,并在单独的回调函数中执行副作用。默认情况下,它也是惰性的——即回调仅在侦听源发生变化时被调用。

  • 与 watchEffect 相比,watch 允许我们:

    • 惰性地执行副作用;
    • 更具体地说明应触发侦听器重新运行的状态;
    • 访问被侦听状态的先前值和当前值。

API:

watch(WatcherSource, Callback, [WatchOptions])

interface WatchOptions extends WatchEffectOptions {
  immediate?: boolean // 默认:false
  deep?: boolean
}

watch单个源: 

setup() {
  const showNav = ref(true);
  watch(
    showNav,
    () => {
      const [search] = document.getElementsByClassName('search');
      if (search) search.style.height = !showNav.value ? '100%' : 'calc(100% - 0.7rem)';
    },
    { immediate: true },
  );
}

watch多个源:

import { useStore } from 'vuex';
import { ref } from 'vue';

setup() {
  const store = useStore();

  const showNav = ref(true);
  const user = JSON.parse(window.localStorage.getItem('user') || null);

  watch(
    [showNav, user],
    ([sNVal, uNVal]) => {
      const [search] = document.getElementsByClassName('search');
      if (search) search.style.height = !sNVal.value ? '100%' : 'calc(100% - 0.7rem)';

      if (uNVal && Object.keys(uNVal).length) {
        setInterval(() => {
          store.dispatch('announce/notification');
        }, 6000);
      }
    },
    { immediate: true },
  );
}

 

在 setup 中 watch props 的某个属性:

export default {
  props: {
    partParams: [Object]
  },
  setup (props) {
    /** resAPI */
    function getDictionaryInfoByCon ({ dicName, dicType }) {
      const payload = {
        dicName,
        dicType,
        page: pageContain.page,
        rows: pageContain.rows
      };

      fetchDictionaryInfoByCon(payload).then(({ data: resData }) => {
        const { status, obj, total } = resData;

        if (status === 200) {
          const info = obj.map((i, index) => ({ key: index, dicId: i.dicId, dicName: i.dicName, dicType: i.dicType, dicKey: i.dicKey, dicValue: i.dicValue, dicSymbol: i.dicSymbol }));

          preDataSource.value = Object.assign([], info);
          dataSource.value = Object.assign([], info);

          pageContain.total = total;
        }
      });
    }

    /**  focal point  */
    watch(() => props.partParams, (newVal) => {
      getDictionaryInfoByCon({ dicName: newVal.dicName, dicType: newVal.dicType });
    }, { immediate: true });
  }
}

 

监听数组变化 :

  1. 将数组定义为响应式数据ref时,如果不加上deep:true,watch是监听不到值的变化的。
  2. 将数组定义为响应式数据ref,加上deep:true,watch可以检测到数据的变化,但老值和新值一样,即不能获取老值。
  3. 将数组定义为响应式对象时,不作任何处理,watch可以检测到数据的变化,但老值和新值一样。
  4. 将数组定义为响应式对象时,把watch的数据源写成函数的形式并通过扩展运算符克隆一份数组返回,可以在监听的同时获得新值和老值。

最佳实践:watch的数据源写成函数的形式并通过扩展运算符克隆一份数组返回,在监听的同时获得新值和老值。

setup() {
    const testArr = ref([]);

    const pushTest = (val) => {
      testArr.value.push(val);
    }

    const popTest = () => {
      testArr.value.pop();
    }

    /** 数组监听的实践- ref, 且加上deep: true */
    watch(testArr, (newVal) => {
      console.log('newVal', newVal);
    }, { deep: true });

    return { testArr, pushTest, popTest }
  },
setup() {
    const testArr = reactive([]);

    const pushTest = (val) => {
      testArr.push(val);
    }

    const popTest = () => {
      testArr.pop();
    }

    /** 数组监听的最佳实践- reactive且源采用函数式返回,返回拷贝后的数据 */
    watch(() => [...testArr], (newVal, oldVal) => {
      console.log('newVal', newVal);
      console.log('oldVal', oldVal);
    });
    
    return { testArr, pushTest, popTest }
  },

 

 监听对象变化:

  1. 把对象定义为响应式对象reactive时,采用函数形式的返回,如果不加上deep:true,watch是监听不到值的变化的。
  2. 把对象定义为响应式对象reactive时,加上deep:true,watch可以检测到数据的变化,但老值和新值一样,即不能获取老值。
  3. 把watch的数据源写成函数的形式并通过深拷贝克隆(这里用了lodash库的深拷贝)一份对象返回,在监听的同时获得新值和老值。

最佳实践:把数据定义成响应式对象reactive,把watch的数据源写成函数的形式并通过深拷贝克隆一份对象返回,在监听的同时获得新值和老值。

<script>
import { reactive, watch } from 'vue';
import _ from 'lodash';

export default {
  name: 'TestDemo',
  setup () {
    const objReactive = reactive({user: {name: 'aa', age: '18'}, brand: 'Channel'});
    
    /** 对象深度监听的最佳实践- reactive且源采用函数式返回,返回深拷贝后的数据 */
    watch(() => _.cloneDeep(objReactive), (newVal, oldVal) => {
      console.log('newVal', newVal);
      console.log('oldVal', oldVal);
    })
  }
}
</script>

参考文献:

Computed 与 watch | Vue.js

Vue3中watch的最佳实践 - 掘金

vue3的Watch监听事件的使用 - 掘金

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 中,你可以使用 `watch` 函数来观察多个响应式属性的变化。`watch` 函数接受一个要观察的具体属性或一个包含多个属性的数组,以及一个回调函数。 以下是在 Vue 3 中使用 `watch` 函数观察多个属性的示例: ```javascript import { watch, reactive } from 'vue'; const app = { setup() { const state = reactive({ count1: 0, count2: 0 }); watch([() => state.count1, () => state.count2], ([newCount1, newCount2], [oldCount1, oldCount2]) => { console.log(`count1 changed from ${oldCount1} to ${newCount1}`); console.log(`count2 changed from ${oldCount2} to ${newCount2}`); }); return { state }; } }; // 在组件或应用中使用 app.setup() 初始化 ``` 在上面的例子中,我们创建了一个名为 `app` 的对象,它包含了 `setup` 方法。在 `setup` 方法中,我们使用 `reactive` 函数创建了一个响应式的 `state` 对象,并定义了两个属性 `count1` 和 `count2`。 然后,我们使用 `watch` 函数来观察 `count1` 和 `count2` 属性的变化。注意传递给 `watch` 函数的第一个参数是一个包含两个箭头函数的数组,每个箭头函数返回对应属性的值。第二个参数是一个回调函数,它接收两个参数:新的属性值和旧的属性值。 当 `count1` 或 `count2` 的值发生变化时,回调函数会被触发,并打印出属性的变化信息。 请注意,以上示例是在 Vue 3 中使用 Composition API 来定义组件的,如果你使用的是 Vue 2,请使用 `Vue.watch` 方法来观察多个属性的变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值