Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Composition functions support andthis value changes #416

Open
Labels
@ktsn

Description

@ktsn

Summary

  • Composition functions are available in class property initializers by wrappingsetup helper.
    • Class property initializers are handled insetup function under the hood.
  • Only$props (and its derived prop values),$attrs,$slots and$emit are available onthis in class property initializers.

Example:

<template>  <div>Count: {{ counter.count }}</div>  <button@click="counter.increment()">+</button></template><script lang="ts">import {ref,reactive,onMounted }from'vue'import {Vue,setup }from'vue-class-component'function useCounter () {const count=ref(0)function increment () {count.value++  }onMounted(()=> {console.log('onMounted')  })return {count,increment  }}exportdefaultclassCounterextendsVue {  counter=setup(()=>useCounter())}</script>

Details

Prior to v7, class component constructor is initialized indata hook to collect class properties. In v8, it will be initialized insetup hook so that the users can use composition function in class property initializer.

The above class component definition is as same as following canonical component definition.

functionuseCounter(){constcount=ref(0)functionincrement(){count.value++}onMounted(()=>{console.log('onMounted')})return{    count,    increment}}exportdefault{setup(){return{counter:useCounter()}}}

setup helper

Wrapping a composition function withsetup helper is needed because we need to delay the invocation of the composition function. Let's see the following example:

functionusePost(postId){constpost=ref(null)watch(postId,asyncid=>{post.value=awaitfetch('/posts/'+id)},{immediate:true})return{    post}}classAppextendsVue{postId='1'// DO NOT do thispost=usePost(toRef(this,'postId'))}

In the above example,this.postId will be referred bywatch helper to track reactive dependencies immediately but it is not reactive value at that moment. Then the watch callback won't be called whenpostId is changed.

setup helper will delay the invocation untilthis.postId become a proxy property to the actual reactive value.

setup unwrapping

As same assetup in the Vue core library,setup in Vue Class Component unwrapsref values. The unwrapping happens shallowly:

// The returned value is:// {//    count: { value: 0 },//    nested: {//      anotherCount: { value: 1 }//    }// }functionuseCount(){constcount=ref(0)constanotherCount=ref(1)return{    count,nested:{      anotherCount}}}classCounterextendsVue{// counter will be:// {//    count: 0, <-- unwrapped//    nested: {//      anotherCount: { value: 1 }//    }// }// The shallow ref (count) is unwrapped while the nested one (anotherCount) retainscounter=setup(()=>useCount())}

In addition, if you return a single ref insetup helper, the ref will also be unwrapped:

// The returned value is: { value: 42 }functionuseAnswer(){constanswer=ref(42)returnanswer}classAnswerextendsVue{// answer will be just 42 which is unwrappedanswer=setup(()=>useAnswer())}

Available built in properties onthis

Since the class constructor is used insetup hook, only following properties are available onthis.

  • $props
    • All props are proxied onthis as well. (e.g.this.$props.foo ->this.foo)
  • $emit
  • $attrs
  • $slots

Example using$props and$emit in a composition function.

functionuseCounter(props,emit){functionincrement(){emit('input',props.count+1)}return{    increment}}exportdefaultclassAppextendsVue{counter=setup(()=>{returnuseCounter(this.$props,this.$emit)})}

Alternative Approach

Another possible approach is using super class and mixins.

import{ref}from'vue'import{setup}from'vue-class-component'constSuper=setup((props,ctx)=>{constcount=ref(0)functionincrement(){count.value++}return{    count,    increment}})exportdefaultclassAppextendsSuper{}

Pros

  • Can define properties directly onthis.

Cons

  • Need duplicated props type definition.

    // Props type definition for setupinterfaceProps{foo:string}constSuper=setup((props:Props)=>{/* ... */})exportdefaultclassAppextendsSetup{// Another definition for foo prop to use it in the class  @Propfoo!:string}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp