Vue3.2 中新出的 expose 是做啥用的?

更新日期: 2022-07-07阅读: 663标签: Vue3

随着vue 3.2的发布,一个新的组合工具提供给我们,叫做 expose。

你是否曾经创建过一个需要向模板提供一些方法和属性的组件,但又希望这些方法对组件是私有的,不能被父类调用?

如果你在开发一个开源的组件或库,你有可能想保持一些内部方法的私有性。在Vue 3.2之前,这并不容易实现,因为所有在选项api中声明的方法或数据等都是公开的,所以模板可以访问它。

组合API也是如此。我们从setup方法中返回的所有东西都可以被父类直接访问。

组合 API

让我们看一个实际的例子。想象一下,我们有一个组件,它创建了一个计数器,每一秒都会更新这个计数器。

MyCounter.vue

<template>
    <p>Counter: {{ counter }}</p>

    <button @click="reset">Reset</button>
    <button @click="terminate">☠️</button>
</template>

<script>
import { ref } from 'vue'

export default {
  setup () {
    const counter = ref(0)

    const interval = setInterval(() => {
      counter.value++
    }, 1000)

    const reset = () => {
      counter.value = 0
    }

    const terminate = () => {
      clearInterval(interval)
    }

    return {
      counter,
      reset,
      terminate
    }
  }
}
</script>

从组合的角度来看,我希望父级组件能够在需要时直接调用reset方法--但我希望保持terminate 函数和 counter 的引用只对组件可用。

如果我们把这个组件实例化到一个父类中,例如 App.vue,并给它附加一个 ref 引用,我们可以很容易地让父类调用 reset 方法,因为当我们从 setup 中返回它时,它已经和 terminate 一起被暴露了。

App.vue

<template>
  <MyCounter ref="counter" />

  <button @click="reset">Reset from parent</button>
  <button @click="terminate">Terminate from parent</button>
</template>

<script>
import MyCounter from '@/components/MyCounter.vue'

export default {
  name: 'App',
  components: {
    MyCounter
  },
  methods: {
    reset () {
      this.$refs.counter.reset()
    },
    terminate () {
      this.$refs.counter.terminate()
    }
  }
}
</script>

如果现在运行这个,并单击重置或终止按钮,两者都可以工作。

让我们明确说明我们要向父类暴露(expose)的内容,以便只有 reset 函数可用。

MyCounter.vue

<script>
import { ref } from 'vue'

export default {
  setup (props, context) {
    const counter = ref(null)

    const interval = setInterval(() => {
      counter.value++
    }, 1000)

    const reset = () => {
      counter.value = 0
    }

    const terminate = () => {
      console.log(interval)
      clearInterval(interval)
    }

    context.expose({ reset })

    return {
      counter,
      reset,
      terminate
    }
  }
}
</script>

这里,我们在setup函数中加入了 props 和 context 参数。我们需要有可用的上下文,因为这是 expose 函数的位置。我们也可以像这样使用重构: { expose }。

接下来,我们使用 context.expose 来声明一个我们想要向实例化这个组件的父类公开的元素对象;在这个例子中,我们只打算让 reset 功能可用。

如果我们再次运行这个例子,并点击 "Terminate from parent" 按钮,我们会得到一个错误。

Uncaught TypeError: this.$refs.counter.terminate is not a function

terminate 功能不再可用,我们的私有API现在也无法访问了。

选项API

上面我们在 composition API 使用 exponse,但在options API中也可以使用这个方法。我们可以把它改写成如下。

//  MyCounter.vue


export default {
  created () { ... },
  data: () => ({ counter: null }),
  methods: {
    reset () { ... },
    terminate () { ... }
  },
  expose: ['reset']
}

注意,我们添加了一个新的选项API属性expose,允许我们传入一个数组,其中字符串'reset'是我们公开的函数的名称。

组合API 渲染功能

创建一个强大脸灵活的组件的方法是利用渲染函数的力量。这对Vue 3来说并不新鲜,但是随着composition API的建立,我们现在可以灵活地从setup方法中直接返回组合API h 函数。

这就产生了一个问题,因为在我们的setup函数中,整个return语句只是包含组件正在创建的节点的 h 方法。

如果在这个时候我们选择向父类 expose 一些东西,我们就会遇到与我们之前看到的相反的问题。没有任何东西被暴露,因为除了dom元素,没有任何东西被返回。

让我们重写 MyCounter.vue 组件来使用这个方法。

<script>
// The template has been deleted
import { ref, h } from 'vue'

export default {
  setup (props, context) {
    const counter = ref(0)

    const interval = setInterval(() => {
      counter.value++
    }, 1000)

    const reset = () => {
      counter.value = 0
    }

    const terminate = () => {
      clearInterval(interval)
    }

    // context.expose({ reset })

    return () => h('div', [
      h('p', `Counter: ${counter.value}`),
      h('button', { onClick: reset }, 'Reset'),
      h('button', { onClick: terminate }, 'Terminate')
    ])
  }
}
</script>

注意,我们在顶部从Vue导入了 h,因为我们需要用它来创建我们的DOM元素。

为了说明问题,暂时注释了context.expose方法。

现在的 return 语句复制了我们之前的 <template> 的DOM结构,如果我们运行这个例子,我们能够正确点击元素上的重置和终止按钮。

然而,如果我们现在点击 "Reset from parent"按钮,我们会遇到一个错误。

Uncaught TypeError: this.$refs.counter.reset is not a function

reset方法不再被暴露,因为它没有被setup函数返回。为了解决这个问题,我们需要取消对context.expose的调用,使其再次可用。

总结

新的 expose 方法是非常直观的,而且很容易在我们的组件中实现。它清除了一些非常重要的组成问题,这些问题在过去甚至需要重写一个完整的组件,所以即使它不是你日常使用的API,它也是值得收藏在我们文件夹中吃灰。

作者:Marina Mosti,译者:前端小智
原文:https://www.vuemastery.com/blog/understanding-vue-3-expose/

链接: https://fly63.com/article/detial/11859

vue3.x 新特性 - CompositionAPI

安装 vue-cli3,在使用任何 @vue/composition-api 提供的能力前,必须先通过 Vue.use() 进行安装,安装插件后,您就可以使用新的 Composition API 来开发组件了。

Vue3数据响应系统

Vue3 就是基于 Proxy 对其数据响应系统进行了重写,现在这部分可以作为独立的模块配合其他框架使用。数据响应可分为三个阶段: 初始化阶段 --> 依赖收集阶段 --> 数据响应阶段

快速进阶Vue3.0

在2019.10.5日发布了Vue3.0预览版源码,但是预计最早需要等到 2020 年第一季度才有可能发布 3.0 正式版。新版Vue 3.0计划并已实现的主要架构改进和新功能:

Vue 3 对 Web 应用性能的改进

有关即将发布的 Vue.js 的第 3 个主要版本的信息越来越多。通过下面的讨论,虽然还不能完全确定其所有内容,但是我们可以放心地认为,它将是对当前版本(已经非常出色)的巨大改进。 Vue 团队在改进框架 API 方面做得非常出色

Vue3 中令人兴奋的新功能

用新的 Vue 3 编写的程序效果会很好,但性能并不是最重要的部分。对开发人员而言,最重要的是新版本将会怎样影响我们编写代码的方式。如你所料,Vue 3 带来了许多令人兴奋的新功能。值得庆幸的是

200 行从零实现 vue3

emmm 用半天时间捋顺了 vue3 的源码,再用半天时间写了个 mini 版……我觉得我也是没谁了,vue3 的源码未来一定会烂大街的,我们越早的去复现它,就……emm可以越早的装逼hhh

从 Proxy 到 Vue 源码,深入理解 Vue 3.0 响应系统

10 月 5 日,尤雨溪在 GitHub 开放了 Vue 3.0 处于 pre-alpha 状态的源码,这次 Vue 3.0 Updates 版本的更新,将带来五项重大改进:速度体积、可维护性、面向原生、易用性

Vue 的数据响应式(Vue2 及 Vue3)

从一开始使用 Vue 时,对于之前的 jq 开发而言,一个很大的区别就是基本不用手动操作 dom,data 中声明的数据状态改变后会自动重新渲染相关的 dom。换句话说就是 Vue 自己知道哪个数据状态发生了变化及哪里有用到这个数据需要随之修改。

在Vue2与Vue3中构建相同的组件

Vue 开发团队终于在今天发布了 3.0-beta.1 版本,也就是测试版。通常来说,从测试版到正式版,只会修复 bug,不会引入新功能,或者删改老功能。所以,如果你对新版本非常感兴趣,或者有新项目即将上马,不妨尝试一下新版本

Vue3中的Vue Router初探

对于大多数单页应用程序而言,管理路由是一项必不可少的功能。随着新版本的Vue Router处于Alpha阶段,我们已经可以开始查看下一个版本的Vue中它是如何工作的。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!