Vue3中的expose函数

16,661 阅读3分钟

发现expose函数

今天在看setup script语法糖的时候发现有说到context上的expose函数,然后就查了一下这个函数,发现是在setRef中被使用到,源码中在对ref的value赋值时的代码如下。

value = vnode.component!.exposed || vnode.component!.proxy

不难看懂这句代码的意思,了解到expose是用来维护vue组件封装性的。

我们先看一下vue3中的ref方法:

ref方法用于创建一个响应式的数据,其使用方法大致如下:

1.先从vue中引入

import { ref } from 'vue';

2.使用ref方法创建数据

具体使用方式就是用ref方法包裹原本的数据。对象类型数据推荐使用reactive激活响应式,详情见vue3响应式文档。

const testValue = ref(null);
const numberValue = ref(1);
const booleanValue = ref(false);
const stringValue = ref('string');
const arrVlue = ref([]);

3.返回数据到模板

这一步的目的是让模板能够使用到setup函数中的数据和方法,对于模板无需使用的数据和方法可以不进行返回。

return { testValue, numberValue, booleanValue, stringValue, arrVlue }

以上就是ref方法的使用方式,然后问题就来了,这个ref方法和expose函数有什么关系呢?别急,继续往下看

ref方法还有一种特殊的用法,就是像vue2中的ref一样,用来获取一个确定的vue组件实例。使用的方法就是上面所说,在定义了一个值为null的响应式数据之后,将其返回给模板使用即可。 现有如下情景:

image.png

1.父组件Father.vue

//Father.vue
<template>
  <div @click="handleClick">
    <h2>我是父组件!</h2>
    <Child ref="child"  />
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';
import Child from './Child.vue'

export default defineComponent({
  components: {
      Child
  },
  setup() {
    const child = ref(null)

    const handleClick = () => {
      console.log(child.value);
      child.value.toDo();
    }

    return {
      child,
      handleClick
    }
  }
});
</script>

2.子组件Child.vue

//Child.vue
<template>
  <span>我是子组件</span>
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup(props, context) {
    const data1 = ref(1);
    const data2 = ref('string');

    const toDo = () => {
      console.log('1');
    }
    
    return {
      data1,
      data2,
      toDo
    }
  },
})
</script>

那么点击父组件会打印什么内容呢?结果如下:

image.png

image.png

不难看出child所获取到的就是子组件的实例,可以通过该实例调用其所有方法和访问其所有数据。

这样直接准确的拿到一个组件的实例的确很方便,但是有一个很大的问题——父组件能拿到子组件实例的所有属性和方法,那也就意味着子组件是没有满足封装性的。

为了解决这个问题,可以使用expose方法。

将子组件Child.vue改为如下内容

<template>
  <span>我是子组件</span>
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup(props, context) {
    const data1 = ref(1);
    const data2 = ref('string');

    const toDo = () => {
      console.log('1');
    }

    context.expose({
      data1
    });

    return {
      data1,
      data2,
      toDo
    }
  },
})
</script>

其实也就只是增加了expose的调用,expose接收一个对象,里面包含了所有想从当前组件实例导出的内容,就像封装一个模块一样,只向外暴露一些必要的方法和数据。

再次点击父组件。

image.png

嗯?怎么报错了?看看child.value的内容:

image.png

可以发现child.value中没有vue组件实例的那些属性和方法了,只有写在expose函数中的内容,根本没有toDo方法,那肯定会报错了。

看到这里你应该已经明白expose函数是干什么用的了,使用expose函数来控制组件被ref时向外暴露的对象内容,借此来维护组件的封装性。

写在最后 (^.^)

如果觉得我写的还不错的话,可以赏我个点赞哦^.^

如果有写错的地方、写的不好的地方也请大家指出,供我纠正。

我是CoCoyY1,一个记录自己学习的前端热爱者。