• 技术文章 >web前端 >Vue.js

    Vue3.2中的expose是啥?有什么用?

    青灯夜游青灯夜游2022-07-08 20:14:33转载358
    Vue3.2 中新出的 expose 是做啥用的?下面本篇文章带大家好好了解下Vue3.2的expose工具,希望对大家有所帮助!

    随着Vue 3.2的发布,一个新的组合工具提供给我们,叫做 expose。(学习视频分享:vue视频教程

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

    如果你在开发一个开源的组件或库,你有可能想保持一些内部方法的私有性。在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函数中加入了 propscontext 参数。我们需要有可用的上下文,因为这是 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,它也是值得收藏在我们文件夹中吃灰。

    英文原文:https://www.vuemastery.com/blog/understanding-vue-3-expose/

    【相关视频教程推荐:vuejs入门教程web前端入门

    以上就是Vue3.2中的expose是啥?有什么用?的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:Vue vue3 vue.js
    上一篇:【吐血整理】Vue.js面试题汇总及答案解析(快来收藏) 下一篇:修饰符v-model与.sync有什么区别?差异对比浅析
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• Vue3和Vue2的差异是什么?全方位对比一下!• 什么是Vue CLI?聊聊vue cli的配置和使用• Vue2和Vue3在响应式上有什么区别?简单对比• vue2.0组件之间怎么传值?组件传输方式浅析• 29个Vue经典面试题(附源码级详解)• 【吐血整理】Vue.js面试题汇总及答案解析(快来收藏)
    1/1

    PHP中文网