业务场景,逻辑在子组件内,子组件的数据变更要传递到父组件。仅在初始化时,父组件要传递给子组件一个初始状态(异步的传入),子组件执行状态变更。

    这种情况下,仅第一次需要初始化状态(执行状态变更),此后都是子组件的状态变更提交到父组件。提交后父子组件的状态一致,不需要再手动执行状态变更。
    因此仅需要监听第一次数据变更,手动执行状态变更逻辑。

    最基本的watch实现如下

    1. export default {
    2. data: {
    3. isDone: false,
    4. needWatch: "string",
    5. },
    6. watch: {
    7. needWatch(val) {
    8. if (!isDone) {
    9. // 处理业务逻辑
    10. // 之后变更isDone的状态
    11. this.isDone = true;
    12. }
    13. },
    14. },
    15. };

    上面这种做法的思路是使用isDone作为标志位。监听器始终存在,如果done了,watch中不再执行业务逻辑。

    上面的做法(声明式监听)虽然实现了功能,但监听器一直存在。

    下面使用命令式监听来实现仅监听一次数据变更,在数据变更后,取消监听。
    image.png

    1. export default {
    2. data: {
    3. needWatch: "string",
    4. },
    5. mounted() {
    6. const unwatch = this.$watch("needWatch", function (val) {
    7. // 处理业务逻辑
    8. // 之后调用unwatch, 取消监听
    9. unwatch();
    10. });
    11. },
    12. };

    到这里正文已经完结了。

    补充:
    简单介绍声明式watch的语法。
    vm.$watch( expOrFn, callback, [options] )

    第一个参数是被监听的变量或函数。
    第二个参数是回调函数,业务逻辑应该写在回调函数内。
    第三个参数是配置项,配置项可选。配置项: { immediate: true, deep: true }

    vm.$watch() 返回一个函数unwatch,执行unwatch可以取消监听。

    需要注意,
    如果options中开启了immediate: true,那么不能在第一次回调时取消侦听给定的 property,否则会报错。(下面这种写法会报错)

    1. this.$watch(
    2. needWatch,
    3. function (val) {
    4. doSomething()
    5. unwatch()
    6. },
    7. { immediate: true }
    8. )