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

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

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

    这次再说一说父子组件之间的传值与通信场景。

    前文:

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

    (四)组件通信与跨级传值

    1. emit 与 slots

    Vue3 中从父级向子级传值与 Vue2 一样,就是在模板里创建子组件的标签时,通过 v-bind:/: 指令传值。

    而父组件通过 v-on:/@ 绑定的事件监听器,需要在子组件触发事件时,需要通过 props 之后的第二个参数 context 调用:

    1
    2
    3
    4
    5
    6
    7
    // child.vue
    export default {
    setup(props, context) {
    const onClick = () => context.emit('click-child');
    // ...
    },
    };

    同时,context 中还提供了我们操作子组件时经常需要用到的插槽 slots:

    1
    2
    3
    4
    5
    6
    7
    8
    // parent.vue
    export default {
    setup(props, context) {
    const { slots } = context;
    const children = (slots.default ? slots.default() : []);
    // ...
    },
    };

    顺带一提,由于 context 不是响应式的,所以我们可以直接在参数表中,使用解构赋值取出 emit 和 slots:

    1
    2
    3
    4
    5
    6
    // parent.vue
    export default {
    setup(props, { emit, slots }) {
    // ...
    },
    };

    不过需要注意,slots 的属性值也可能随时发生变化,但它本身并非响应式数据。为了确保你的组件随时获得最新的插槽状态,建议在 onUpdated 中操作其属性值。

    2. 跨级传值

    我们有时会遇到类似这样的需求(比如:Tab 与 TabPane),所有子组件需要根据同一个父组件/祖先组件的状态调整自身的状态,做到跨级数据联动。

    a) Vue2 方案

    在 Vue2 中,是被打散在不同构造参数中的 provide 和 inject 属性实现的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    // tab.vue
    exports default {
    data() {
    return {
    tabState: {
    // ...
    };
    },
    },
    // ...
    provide() {
    // 向子孙组件提供 tabState
    const { tabState } = this;
    return {
    tabState,
    };
    },
    };

    // tab-pane.vue
    exports default {
    // 告知可以注入来自祖先的 tabState
    inject: [ tabState ],
    // ...
    methods: {
    getTabState() {
    // 取用 provide 过来的数据
    const { tabState } = this;
    // ...
    },
    },
    };

    可以看到,又是被打散到不同 data/methods/computed 段落的零散数据,靠 this 强行绑定到一起。

    b) Vue3 方案

    在 Vue3 中,则是通过 provide 和 inject 函数,更直观地组装出来:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // tab.vue
    import { reactive, provide } from 'vue';
    exports default {
    setup() {
    const tabState = reactive({
    // ...
    });
    provide('tabState', tabState);
    // ...
    },
    };

    // tab-pane.vue
    import { inject } from 'vue';
    exports default {
    setup() {
    const tabState = inject('tabState');
    // 还可以传入一个默认值: const tabState = inject('tabState', { });
    // ...
    },
    };

    传入响应式数据后,在子孙组件都可以方便地取到,以至于甚至可以替代很多 Vuex 的使用场景。


    这一系列至此告一段落,Vue3 的组装 API 使用起来还是相对简单的,大部分问题都能查阅官方文档解决。

    如果还有其他问题也欢迎留言联系,或者加入QQ群: 121757667 ,一起讨论和学习!



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