SoFunction
Updated on 2025-04-05

A brief talk about the changes in setup in vue3.0 sfc

Preface

In vue, sfc (single-file component) refers to a special file format with a file suffix named .vue, which allows templates, logic and styles in Vue components to be encapsulated in a single file.

Here is a basic sfc

<script>
export default {
  data() {
    return {
      greeting: 'Hello World!'
    }
  }
}
</script>

<template>
  <p class="greeting">{{ greeting }}</p>
</template>

<style>
.greeting {
  color: red;
  font-weight: bold;
}
</style>

Vue3.0 has launched the setup writing method in the latest SFC proposal. Let's take a look at what changes have been made in the new proposal.

Standard SFC writing

When using TS, standard sfc needs to use defineComponent to perform type inference.

&lt;script lang="ts"&gt;
  import { defineComponent } from 'vue'
  
  export default defineComponent({
    setup() {
      return {
        // The attributes exposed to template      }
    }
  })
&lt;/script&gt;

script-setup

The purpose of the script setup is to enable developers to develop components more efficiently, reduce boilerplate content, and reduce development burden. Just add a setup property to the script tag to turn script into a setup function. At the same time, the defined variables, functions, and imported components will be exposed to the template by default.

Variable exposure

Standard writing

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

export default defineComponent({
  setup() {
    const count = ref(0)
    return {
      count
    }
  }
})
</script>

<template>
  <div>
    parent{{count}}
  </div>
</template>

setup

<script setup lang="ts">
import {ref} from 'vue'
  
const count = ref(0)
</script>

<template>
  <div>
    parent{{count}}
  </div>
</template>

Component Mounting

Standard writing

<script lang="ts">
import { defineComponent } from 'vue'
import child from './childComponent'

export default defineComponent({
  components: {
    child
  },
  setup() {
    // ...
  }
})
</script>

<template>
  <div>
    parent
    <child />
  </div>
</template>

setup

<script setup lang="ts">
import child from './childComponent'
</script>

<template>
  <div>
    parent
    <child />
  </div>
</template>

No need to manually mount components, it can be used in templates, efficient and fast. Other variables, as well as top APIs, such as compute, watch and other attributes, are the same as the original standard writing method.

props

In setup, when subcomponents receive props, they need to use defineProps, which is an API that can only be used in setup syntax. Let’s first look at the standard writing method, how props are received.

Standard writing method

// 
<template>
  <child :count={count} />
</template>
<script lang="ts">
impor {defineComponent,ref} from 'vue'
import child from './childComponent'

export default defineComponent({
  components: {
    child
  },
  setup() {
    const count = ref(0)
    return {
      count
    }
  }
})
</script>
// 
<template>
  child{{count}}
</template>
<script lang="ts">
impor {defineComponent} from 'vue'
export default defineComponent({
  props: ['count'],
  setup(props) {
    return {}
  }
})
</script>

setup writing method, use defineProps

// 
<template>
  <child :count={count} />
</template>
<script setup lang="ts">
impor {ref} from 'vue'
import child from './childComponent'
  
const count = ref<number>(0)
</script>
// 
<template>
  child{{count}}
</template>
<script setup>
defineProps(['count'])
</script>


Note: Using the sfc-setup syntax, you do not need to introduce defineProps

Here we only need to simply declare props, which is a lot more concise in writing.


So how do you do type check for props?

<script setup>
defineProps({
  count: Number,
  title: {
    type: String,
    default: 'header'
  },
  data: {
    type: Object,
    defualt () {
      return {}
    }
  }
})
</script>


How to use TS for type annotation?

&lt;script lang="ts" setup&gt;
interface d {
  name: string  
}
  
defineProps&lt;{
  count: number // The syntax of Number to be replaced with ts  title: string
  data: d
}&gt;()
&lt;/script&gt;


We found that props are not assigned a default value. In the writing method of TS, there are two ways to set the default value for props.

ES6 variable destruction assignment

defineProps returns an object, we can deconstruct the returned object while giving the default value.

&lt;script lang="ts" setup&gt;
interface d {
  name: string  
}
  
const {count = 0, title = 'header', date = { name: 'a' }} = defineProps&lt;{
  count: number // The syntax of Number to be replaced with ts  title: string
  data: d
}&gt;()
&lt;/script&gt;

withDefaults


The official subsequently launched withDefaults to provide default values ​​for props; withDefaults will type check the default values.

&lt;script lang="ts"&gt;
// Don't forget to introduce withDefaultsimpor { withDefaults } from 'vue'
  
interface d {
  name: string  
}
  
const props = withDefaults(defineProps&lt;{
  count: number // The syntax of Number to be replaced with ts  title: string
  data: d
}&gt;(), {
  count: 0,
  title: 'header',
  data: () =&gt; ({name: 'Wang Xiaoer'})
})
&lt;/script&gt;

Custom events

To use events in setup, defineEmits is required, which is also a compiler macro that can only be used in the sfc-setup syntax.

&lt;script setup lang="ts"&gt;
  // Define events and make type annotations at the same time  // Non-TS writing method: const emits = defineEmits(['create'])  const emits = defineEmits&lt;{
    (e: 'create', value: string): void
  }&gt;()
  
  // Trigger event  const addTodo = () =&gt; {
    emits('create', 'hi')
 }
&lt;/script&gt;

Add an official TodoMVC example refactored with Vue3 + ts: /s/vibrant-w…

Summarize

This is the article about the changes in setup in vue3.0 sfc. This is all about this article. For more related contents of setup in vue3.0 sfc, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!