IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    初探 Vue 3.0 的组装式 API(三)

    krimeshu发表于 2023-09-24 03:02:00
    love 0

    在基础的响应式数据和事件函数之后,我们再来说说 computed 计算属性 和 watch 监听吧。

    前文:

    • 《初探 Vue 3.0 的组装式 API(一)》
    • 《初探 Vue 3.0 的组装式 API(二)》

    (三)组件属性、计算属性与监听

    1. 组件属性

    通过数据和事件处理的几个例子,大家或许发现了 Vue3 的两个基本变化思路:

    • 开发人员自己动手组装响应式数据;
    • 事件处理对象方法降级为普通函数。

    而这两者都避免了再将各种不同层级的属性、方法绑定到 $vm 上,从而避免了混乱的 this 指向问题。

    以至于我们在 Vue3 的例子里基本没再用到过 this。

    对于父级组件传入的属性值,以前都是通过 this.<属性名> 访问的,在 Vue3 的 setup() 中怎么获取组件属性呢?

    很简单,setup() 函数收到的第一个参数就是传入的属性值了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    export default {
    props: {
    name: String,
    },
    setup(props) {
    const { name } = props;

    return { name };
    },
    };

    不过由于传入的 props 是一个响应式数据,为了确保传入的非引用型数据发生变化时,页面内状态能动态更新,我们还得用 toRefs 从里面解构取值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import { toRefs } from 'vue';

    export default {
    props: {
    name: String,
    },
    setup(props) {
    const { name } = toRefs(props);

    return { name };
    },
    };

    2. 计算属性

    对于间接通过其它数据再计算出来的计算属性,通过 Vue3 的组装 API 实现也很简单:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // sells.js
    import { ref, toRefs, computed } from 'vue';

    export default {
    props: {
    // 库存数量
    totalCount: Number,
    // 售出数量
    sellCount: Number,
    },
    setup(props) {
    const {
    totalCount = ref(0),
    sellCount = ref(0),
    } = toRefs(props);
    // 剩余数量
    const remainCount = computed(() => totalCount.value - sellCount.value);

    return { totalCount, sellCount, remainCount };
    },
    };

    除了实际的业务逻辑之外,computed() 通常还可以用于多个 className 的计算合成,比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    export default {
    props: {
    // 是否禁用状态
    disabled: Boolean,
    },
    setup(props) {
    const { disabled } = toRefs(props);
    const className = computed(() => [
    'sells-list',
    {
    'is-disabled': disabled,
    },
    ]);
    },
    };

    3. 监听

    3.1 watch

    当某个响应数据发生变化时,执行相关处理逻辑,我们就会用到 watch() 了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const { disabledIds } = toRefs(props);
    const selectedId = ref(null);

    // 监听某个数据
    watch(selectedId, (val, oldVal) => {
    // do something
    });
    // 监听多个数据
    watch([selectedId, disabledIds], (val, oldVal) => {
    // 此时传入的 val 和 oldVal 将会是多个数据的数组
    });

    // 监听某个复合条件的结果
    watch(() => selectedId === disabledIds, (val, oldVal) => {
    // 当其中相关值发生改变,但结果不变时,这里不会被触发
    });

    我们还可以使用 watch() 返回的停止器来结束监听:

    1
    2
    3
    4
    5
    const selectedId = ref(null);

    const stopWatch = watch(selectedId, (val) => { });

    stopWatch();

    3.2 watchEffect

    与 watch 不同,watchEffect() 不需要指明监听目标,在它接收一个 effect 函数后,将会立刻执行并分析其中依赖的响应数据,在它们发生变化时再次执行这个 effect 函数。:

    1
    2
    3
    4
    5
    6
    const sellsCount = ref(0);

    watchEffect(() => {
    console.log(`sellsCount: ${sellsCount.value}`);
    });
    // 将会立刻看到输出日志,之后数据变化时再次打印日志

    3.3 回收处理

    如果需要在监听停止的同时,做一些额外的回收处理(比如解除 DOM 事件监听器、清理其它数据等),可以用到 onInvalidate 函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const sellsCount = ref(0);

    watch(sellsCount, (val, oldVal, onInvalidate) => {
    console.log(`sellsCount: ${val}`);
    onInvalidate(() => {
    // 回收处理
    });
    });

    watchEffect((onInvalidate) => {
    console.log(`sellsCount: ${sellsCount.value}`);
    onInvalidate(() => {
    // 回收处理
    });
    });

    下一篇:《初探 Vue 3.0 的组装式 API(四)》



沪ICP备19023445号-2号
友情链接