目录
  • [Vue3] defineExpose要在方法声明定义以后使用
    • defineExpose的使用
    • 总结
  • 扩展:vue3 defineExpose

    defineExpose要在变量和方法声明定义之后再使用,否则浏览器的控制台会输出很多警告,并且最终将该页面卡死。

    [Vue3] defineExpose要在方法声明定义以后使用

    Vue3中的setup默认是封闭的,如果要从子组件向父组件暴露属性和方法,需要用到defineExpose.

    defineProps, defineEmits一样,这三个函数都是内置的,不需要import.

    不过defineProps, defineEmits都会返回一个实例,而defineExpose是无返回值的.

    const props = defineProps({})
    const emit = defineEmits([])
    defineExpose({})

    defineExpose的使用

    子组件Child.vue

    <template>
    	{{ name }}
    </template>
    
    <script setup>
    import { ref } from 'vue'
    
    const name = ref("Nicholas.")
    const sayName = ()=>{
        console.log("my name is "+name.value)
    }
    
    defineExpose({
    	name,
    	sayName
    });
    </script>

    父组件Father.vue

    <template>
    	<Child ref="child"></Child>
    </template>
    
    <script setup>
    import { ref, onMounted } from 'vue'
    const child = ref(null)
    onMounted(()=>{
        console.log(child.value.name)	// "Nicholas"
        child.value.sayName()			// "my name is Nicholas"
    })
    </script>

    总结

    向外暴露的时候变量会自动解包,比如上面子组件的name:ref<String>暴露到父组件的时候自动变成了name:String.

    注:defineExpose一定要在变量和方法声明定义之后再使用。

    不知道以后会不会有修改,不过在2023/02/17,如果defineExpose写在变量和函数前面,那么浏览器的控制台会输出很多警告,并且最终将该页面卡死。

    Vue3  defineExpose要在方法声明定义以后使用的教程

    扩展:vue3 defineExpose

    vue3使用 setup 语法糖后如何在父组件用ref调用子组件的方法

    什么是setup语法糖

    • 更少的样板内容,更简洁的代码。
    • 能够使用纯 Typescript 声明 props 和抛出事件。
    • 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
    //要使用这个语法,需要将 setup attribute 添加到 <script> 代码块上:
    <script setup>
    console.log('hello script setup')
    //里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行。
    </script>

    当我们的组件使用这种语法时,是不可以用setup()这种语法的写法获取子组件的数据或方法
    为了在 script setup 组件中明确要暴露出去的属性,使用 defineExpose 编译器宏:

    <script setup>
    import { ref } from 'vue'
    
    const a = 1
    const b = ref(2)
    
    defineExpose({
      a,
      b
    })
    //当父组件通过模板 ref 的方式获取到当前组件的实例,获取到的实例会像这样 { a: number, b: number } (ref 会和在普通实例中一样被自动解包)
    
    </script>

    下面是vue3 使用setup()后 父组件获取子组件的方法

    1、父组件

    template中

    <Table ref="eleTable" @handle="handleFun"></Table>
    import {  ref  } from 'vue'

    2、子组件

    setup() { 
       //ref方法
        const eleTable = ref()  //eleTable是页面ref后面对应的名字
        const clickSon = () => {
          eleTable.value.changeShowText() //调用子组件的方法
          let arr = eleTable.value.tableData //获取子组件 setup 里面定义的变量
        }
    }

    使用语法糖之后的写法

    父组件

    <FastreplySettingTable
                  ref="FastreplySettingTableRef"
                  v-if="sysStore.msgList"
                  :groupType="Math.abs(state.currentTab - 1)"
                  :currentTab="state.currentTab"
                ></FastreplySettingTable>
    
    
    <script>
       const FastreplySettingTableRef = ref();
       
       //该方法是一个点击事件
       function sendEvent(action) {
         if (FastreplySettingTableRef) {
         //拿到FastreplySettingTableRef组件里的dispatchEvent方法 并且穿一些参数
        FastreplySettingTableRef.value.dispatchEvent({ action, groupType: Math.abs(state.currentTab - 1) })
      }
    }
    </script>
    

    子组件

    import {
      getCurrentInstance,
      onMounted,
      reactive,
      onBeforeUnmount,
      defineProps,
      defineEmits,
      computed,
      onBeforeMount,
      onUnmounted,
      watch,
      ref,
      //这里必须引入
      defineExpose
    } from "vue";
    // 希望被父组件调用到的方法
    //这个方法必须写在defineExpose 上面才会生效
    const dispatchEvent = ({ action, groupType }) => {
      switch (action) {
        case 'tabClick': {
          state.searchKeyword = '',
            state.activeGroup = 'all'
    
        }; break;
        case 'addfastMsg': {
          //上报
          openMask('addfastMsg');
          // state.DialogTitle = state.groupType ? "快捷消息管理-添加团队内容" : "快捷消息管理-添加个人内容"
          // spiderReport.paq(props.groupType ? "快捷消息管理-添加团队内容" : "快捷消息管理-添加个人内容");
        }; break;
        default: {
          // state.[action](groupType);
        }
      }
    }
    defineExpose({
      dispatchEvent
    })
    
    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。