• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • setup()

    此页面记录了setup组件选项的使用。如果您将 Composition API 与单文件组件一起使用,建议使用<script setup>更简洁。

    在以下情况下,该setup()钩子用作组件中组合 API 使用的入口点:

    • 在没有构建步骤的情况下使用 Composition API;
    • 在 Options API 组件中与基于 Composition-API 的代码集成。

    基本用法

    我们可以使用响应式 API,声明反应状态,并通过从setup()返回对象的属性也将在组件实例上可用(如果使用其他选项):

    <script>
    import { ref } from 'vue'
    
    export default {
      setup() {
        const count = ref(0)
    
        // expose to template and other options API hooks
        return {
          count
        }
      },
    
      mounted() {
        console.log(this.count) // 0
      }
    }
    </script>
    
    <template>
      <button @click="count++">{{ count }}</button>
    </template>
    

    请注意,在模板中访问时,从返回的refssetup会自动浅展开.value,因此您在访问它们时不需要使用。当在组件上访问时,它们也以相同的方式展开this

    setup()本身无权访问组件实例。在setup()内,this的值不存在。您可以从 Options API 访问 Composition-API 公开的值,但反之则不行。


    访问 props

    setup()函数中的第一个参数是props,它是响应式的,并且会在传入新的props时更新。

    export default {
      props: {
        title: String
      },
      setup(props) {
        console.log(props.title)
      }
    }
    

    注意:如果您对props对象进行解构,则被解构的变量将失去反应性。因此建议始终以props.xxx形式访问。

    如果您确实需要解构props,或者需要将props传递给外部函数同时保持反应性,您可以使用toRefs()toRef()实用程序 API 执行此操作:

    import { toRefs } from 'vue'
    
    export default {
      setup(props) {
        // turn `props` into an object of refs, then destructure
        const { title } = toRefs(props)
        // `title` is a ref that tracks `props.title`
        console.log(title.value)
    
        // OR, turn a single property on `props` into a ref
        const title = toRef(props, 'title')
      }
    }
    


    设置上下文 context

    传递给setup()函数的第二个参数是一个设置上下文context对象。上下文对象暴露了其他可能在setup()内部有用的值:

    export default {
      setup(props, context) {
        // Attributes (Non-reactive object, equivalent to $attrs)
        console.log(context.attrs)
    
        // Slots (Non-reactive object, equivalent to $slots)
        console.log(context.slots)
    
        // Emit events (Function, equivalent to $emit)
        console.log(context.emit)
    
        // Expose public properties (Function)
        console.log(context.expose)
      }
    }
    

    上下文对象不是响应式的,可以安全地解构:

    export default {
      setup(props, { attrs, slots, emit, expose }) {
        ...
      }
    }
    

    attrsslots是在组件本身更新时,始终更新的有状态对象。这意味着您应该避免对它们进行解构,并始终将属性引用为attrs.xslots.x

    另请注意,与props不同,attrsslots属性不是响应式的。如果您打算根据对其的更改应用副作用,则应在生命周期onBeforeUpdate挂钩中执行此操作。


    暴露公共属性

    默认状态下,本组件实例的属性方法,不能被父组件访问。expose()函数,可用于显式暴露:

    export default {
      setup(props, { expose }) {
        // make the instance "closed"
        // i.e. do not expose anything to the parent
        expose()
    
        const publicCount = ref(0)
        const privateCount = ref(0)
        // selectively expose local state
        expose({ count: publicCount })
      }
    }
    


    与渲染函数一起使用

    setup()还可以返回一个渲染函数,该函数可以直接使用在同一范围内声明的反应状态:

    import { h, ref } from 'vue'
    
    export default {
      setup() {
        const count = ref(0)
        return () => h('div', count.value)
      }
    }
    

    返回一个渲染函数,可以防止我们返回其他任何东西。在内部这应该不是问题,但是如果我们想通过模板引用将此组件的方法公开给父组件,则可能会出现问题。

    我们可以通过调用expose()来解决这个问题:

    import { h, ref } from 'vue'
    
    export default {
      setup(props, { expose }) {
        const count = ref(0)
        const increment = () => ++count.value
    
        expose({
          increment
        })
    
        return () => h('div', count.value)
      }
    }
    

    然后,该increment方法将通过模板引用在父组件中可用。

    下篇:ref()