vue组件传值

58 阅读1分钟

1.父向子传值

props传值方式

<!-- 根据一个变量的值动态传入 --> 
<BlogPost :title="post.title" />

props是单向数据流,即父传给子,但子不能修改父。

2.子向父传值

2.1 emit触发

子组件中触发事件

<button @click="$emit('increaseBy', 1)"> Increase by 1 </button>

父组件中定义事件

<MyButton @increase-by="increaseCount" />

2.2 ref

父组件可以通过 ref 主动获取子组件的属性或者调用子组件的方法

父组件

//template中定义ref
 <ResourceAllocation ref="childFormRef" :errors.sync="state.errors" />
   
 // js中
   const childFormRef = ref(null);
  (childFormRef as any).value.setFormErr(err);

子组件

   //定义了一个错误处理的事件
   const setFormErr = async (err: IFetchResponse) => {
        formErrHandle(state, err);
    };
    //定义了一个表单提交事件
   const submit = async () => {
        const {hasError, errors} = await (form.value as any).submit();
        return {
            hasError,
            errors,
            formData: {...state.formData}
        };
   };

2.3.sync 和 v-model(.sync在vue3中好像被废弃了)

2.3.1 v-model 用于在表单输入元素或组件上创建双向绑定 cn.vuejs.org/guide/compo…

子组件:方式1

<!-- CustomInput.vue -->
<script>
    export default {
      props: ['modelValue'], emits: ['update:modelValue'] 
    }
</script>
<template>
    <input 
      :value="modelValue" 
      @input="$emit('update:modelValue', $event.target.value)"
     />
</template>
<CustomInput v-model="searchText" />

另一种在组件内实现 v-model 的方式是使用一个可写的,同时具有 getter 和 setter 的计算属性。get 方法需返回 modelValue prop,而 set 方法需触发相应的事件:

子组件:方式2(工作中常用)

<!-- CustomInput.vue -->
<script> 
export default { 
    props: ['modelValue'],
    emits: ['update:modelValue'], 
    computed: {
         value: 
          { 
              get() { 
                     return this.modelValue 
               }, 
               set(value) { 
                    this.$emit('update:modelValue', value)
                }
           } 
      } 
   }
</script> 
<template> 
   <input v-model="value" />
</template>

3.兄弟组件传值(todo 下面内容待补充)

eventbus

vuex

自定义事件 CustomEvent ,清除副作用?

1.在子应用中注册事件

import {computed, watch} from '@vue/composition-api';

export const notifyRootApp = (key: string, payload: any) => {

    const event = new CustomEvent('afe:notifyRootApp', {

        detail: {

            key,

            payload

        }

    });

    window.dispatchEvent(event);

};
2.点击确定需要把表单数据传给后端发送ajax请求

确定和取消的事件应该放在子应用里面,

那点击主应用通知子应用触发事件

(点击了确定,告诉子应用当前我在创建报告页我点了哈,你该去执行确定事件了,点击了取消,告诉子应用我点了哈,你该去执行取消事件了)

export const useRootAppNotify = (

    handleCreatReportConfirmCallBack,

    handleCreatReportCancelCallBack,

    handleAddVersionConfirmCallBack,

    handleAddVersionCancelCallBack

) => {

    console.log('useOceanAppNotify');
    const NOTIFY_EVENT = "afe:notifyChildApp"

    const listenerFn = (e: any) => {

        console.log('addEventListener');

        try {

            const {key, payload}: TAfeNotify = e.detail;

            if (key === 'btnIsClicked') {

                if (payload.isConfirmBtnClicked) {

                    if (payload.pageName === 'CreateReport') {

                        handleCreatReportConfirmCallBack?.();

                    } else {

                        handleAddVersionConfirmCallBack?.();

                    }

                } else {

                    if (payload.pageName === 'CreateReport') {

                        handleCreatReportCancelCallBack?.();

                    } else {

                        handleAddVersionCancelCallBack?.();

                    }

                }

            }

        } finally {

            //

        }

    };

    onMounted(() => {

        window.addEventListener(NOTIFY_EVENT, listenerFn);

    });

    onBeforeUnmount(() => {

        window.removeEventListener(NOTIFY_EVENT, listenerFn);

    });

};

4.多层嵌套组件传值

provide / inject

注意provide提供的数据并不是响应式的,为保证注入方和供给方之间的响应性链接,我们需要使用 computed() 函数提供一个计算属性

使用 Symbol 作注入名,我们通常推荐在一个单独的文件中导出这些注入名 Symbol