SoFunction
Updated on 2025-04-11

An article summarizes the use of syntactic sugar in Vue3.2

1. Overview

existVue2During the period, the various variables, methods, calculation attributes, etc. defined in the component are stored separately indatamethodscomputedAmong the options, the code written in this way is not convenient for later reference. Finding a business logic requires switching back and forth between each option.vue3.0Combination APIsetupThe function was introduced to solve this problem. It made our logical focus more focused and the syntax was more streamlined, but when we were using itvue3.0When building components, you always need to return the method variables defined outside to<template>, more troublesome.vue3.2The emergence of syntactic sugar and some new APIs have further simplified our code.

What is syntactic sugar?

Syntactic sugar(English: Syntactic sugar) is a British computer scientistPeter LandingA term invented refers to a certain syntax added to a computer language. This syntax has no effect on the function of the language, but is more convenient for programmers to use. Syntax sugar makes the program more concise and has higher readability.

Vue3.2 Syntax Sugar

Let's take a lookvue3.0andvue3.2Comparison of structure of single file component (SFC, i.e. .vue file)

  • vue3.0Components
<template>
    <div>
    </div>
</template>
<script>
export default {
    components: {
    },
    props: {
    },
    setup () {
        return {}
    }
}
</script>
<style lang="scss" scoped>
</style>
  • vue3.2Components
&lt;template&gt;
    &lt;MyTestVue :title="title" @click="changeTitle" /&gt;
&lt;/template&gt;
&lt;script setup&gt;
import MyTestVue from './';
import { ref } from 'vue';
const title = ref('Test it')
const changeTitle = () =&gt; {
     = 'Hello,World'
}
&lt;/script&gt;
&lt;style lang="scss" scoped&gt;
&lt;/style&gt;
  • contrastvue3.0andvue3.2The main change of the version of component template is that it is no longer available in 3.2.setupfunction, instead put it in script tag.

  • The properties and methods we define do not need to be returned in return, but can be used directly in template syntax...

    These are intuitive changes, and we will learn the specific usage next.

2. Introduction to use

1. Component registration

vue3.0Use components in the component option to explicitly register:

<script>
import ComponentA from './'

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

vue3.2 <script setup>In the single-file component, the imported components can be used directly in the template. The components will be automatically registered and there is no need to specify the name of the current component. It will automatically focus on the file name, which means there is no need to write the name attribute.

<script setup>
import ComponentA from './'
</script>

<template>
  <ComponentA />
</template>

statement

existvue3.0middle,propAvailablepropsOptions to declare

&lt;script&gt;
export default {
  props: ['foo'],
  // Or use this method to refer to the type and the default value  // props: {
  //   foo:{
  //     type: String,
  //     default: ''
  //   },
  // },
  setup(props) {
    // setup() receives props as the first parameter    ()
  }
}
&lt;/script&gt;

vue3.2In the component,propsAvailabledefineProps()Macro declare

&lt;script setup&gt;
const props = defineProps(['foo'])
// orconst propsOther = defineProps({
  title: String,
  likes: Number
})

()
&lt;/script&gt;

Note: All props follow the principle of one-way binding. Props change due to the update of the parent component, and naturally flow new state downwards to the child component without being reversed, which means you should not change a prop in the child component.

3. Calculate properties

We generally use computed properties to describe complex logic that depends on responsive states. To put it bluntly, the value of this computed attribute depends on the values ​​of other responsive attributes. If the dependency attribute changes, the value of this computed attribute will be recalculated.

&lt;script setup&gt;
import { ref, computed } from 'vue'

const firstName = ref('John')
const lastName = ref('Doe')

const fullName = computed({
  // getter
  get() {
    return  + ' ' + 
  },
  // setter
  set(newValue) {
    // Note: We are using deconstructed assignment syntax here    [, ] = (' ')
  }
})
&lt;/script&gt;

When called = 'John Doe'hour,setterWill be called, andfirstNameandlastNameWill be updated invue3.2We can directly<template>Use it in the tag, no return is required.

  • Don't make asynchronous requests or change the DOM in the calculation function!
  • A computed attribute will only be recalculated when its responsive dependency is updated. If it relies on a non-responsive dependency, its value will change in time, and the computed attribute will not be updated.
  • Compared to methods, the calculated attribute value is cached based on its responsive dependency, and a computed attribute is recalculated only when its responsive dependency is updated.

4. watch

In the combined API, we can usewatchThe function triggers the callback function every time the responsive state changes.watchThe first parameter can be a different form of "data source": it can be a ref(including computed properties), a responsive object, agetterAn array of functions, or multiple data sources:watch()Is lazy to execute: Callbacks are executed only if the data source changes, for example:

<script setup>
import { ref,watch } from 'vue';

const props = defineProps({
    title: String,
    itemList: {
        type: Array,
        default: () => [{
            text: 'title',
            value: 0
        }]
    }
})

watch(() => ,(newValue,oldValue) => {
    ('newValue===',newValue);
    ('oldValue===',oldValue);
})
</script>

Listen here, when the incomingitemListWhen the number changes, the subsequent callback method will be called. certainlywacth()There is also a third optional parameter:No deep monitoring is enabled, If written here:

<script setup>
import { ref,watch } from 'vue';
...
watch(() => ,(newValue,oldValue) => {
    ('newValue===',newValue);
    ('oldValue===',oldValue);
})
</script>

When the incomingitemListWhen the quantity changes, the callback function will not trigger. The correct way to write it is to add its third parameter.deep:true

<script setup>
import { ref,watch } from 'vue';
...
watch(() => ,(newValue,oldValue) => {
    ('newValue===',newValue);
    ('oldValue===',oldValue);
},{deep:true})
</script>

watchYou can also listen to multiple attributes at the same time:

&lt;script setup&gt;
import { ref,watch } from 'vue';

const props = defineProps({
    title: String,
    itemList: {
        type: Array,
        default: () =&gt; [{
            text: 'title',
            value: 0
        }]
    }
})
// Listen to multiple attributes at the same timewatch(() =&gt; [,],(newValue,oldValue) =&gt; {
    ('newValue===',newValue);
    ('oldValue===',oldValue);
},{deep:true})
  
&lt;/script&gt;

5. watchEffect()

andwatch()The difference between lazy execution is thatwatchEffect()The callback function will be executed immediately. If the function has side effects at this time,VueThe dependencies of side effects will be automatically tracked and the response source will be automatically analyzed. The above example can be rewritten as:

<script setup>
  ...
watchEffect(() => {
    ('itemList===',);
    ('title===',);
})
</script>  

In this example, the callback will be executed immediately. During execution, it will automatically trackBeing a dependency (behaving similarly to computed attributes). Whenever the incomingWhen changes are made, the callback will be executed again.

If you want to clearwatchEffect()The listening, only the displayed call is requiredwatchEffect()The return function is fine, for example:

<script setup>
  ...
const stopEffect = watchEffect(() => {
    ('itemList===',);
    ('title===',);
})
stopEffect()
</script>

watch only tracks explicitly listened data sources. It won't track anything accessed in the callback. Also, the callback is triggered only if the data source does change. We can control the triggering timing of the callback function more accurately. watchEffect will track dependencies during side effects. It automatically tracks all accessible responsive properties during synchronous execution.

6. Component event calls

6.1 Methods of child components calling parent components

vue3.0If our child component triggers the parent component's method, our approach:

Subcomponents
&lt;script&gt;
export default {
  emits: ['inFocus', 'submit'],
  setup(props, ctx) {
    ('submit',params)
  }
}
// Or you can deconstruct emitexport default {
    setup(props,{emit}) {
    emit('submit',params)
  }
}
&lt;/script&gt;
Parent component
&lt;template&gt;
    &lt;Children @submit="submitHandel"/&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  name: 'TodoItem',
  setup(props, { emit }) {
    const submitHandel = () =&gt; {
      ('The child component calls the submitHandel method of the parent component');
    }
    return {
      submitHandel,
    }
  }
};
&lt;/script&gt;

vue3.2In syntax sugar, the event to be triggered by the child component needs to be explicitly passed.defineEmits()Macro declare

Subcomponents
&lt;script setup&gt;
const emit = defineEmits(['inFocus', 'submit'])

function buttonClick(parmas) {
  emit('submit', parmas)
}
&lt;/script&gt;
Parent component
&lt;template&gt;
    &lt;Children @submit="submitHandel"/&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
  const submitHandel = () =&gt; {
    ('The child component calls the submitHandel method of the parent component');
  }
};
&lt;/script&gt;

6.2 The parent component calls the child component method or property

vue3.0If the parent component triggers the child component's method or property, it can be returned directly in the return function. The data is implicitly exposed to the parent component by default.

&lt;script&gt;
// Subcomponentssetup(props, { emit }) {
  const isShow = ref(false)
  // The parent component calls this method  const showSubComponent = () =&gt; {
     = !
  }
  return {
      // return      showSubComponent,
    }
  }
&lt;/script&gt;

Passed in the parent componentrefGet the child component and access the method exposed by the child component

Parent component
&lt;template&gt;
  &lt;div class="todo-list"&gt;
    &lt;TodoItemVue :itemList="itemList" @clickItemHandel="clickItemHandel" ref="todoItemVueRef" /&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
  import { ref } from 'vue';
  export default {
  setup(props, { emit }) {
    //Get child component ref    const todoItemVueRef = ref(null)
    // Methods to call subcomponents    const callItemFuncHandel = () =&gt; {
        ()
    }
    return {
     todoItemVueRef
    }
  }
};
&lt;/script&gt;

vue3.2In syntax, the parent component is called the same way, and the child component passesdefineExpose()Expose methods or attributes

Subcomponents
&lt;script setup&gt;
const isShow = ref(false)
// The parent component calls this methodconst showSubComponent = () =&gt; {
     = !
}
//Expose the method through defineExposedefineExpose({
    showSubComponent
})
&lt;/script&gt; 
Parent component
&lt;template&gt;
  &lt;div class="todo-list"&gt;
    &lt;TodoItemVue :itemList="itemList" @clickItemHandel="clickItemHandel" ref="todoItemVueRef" /&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script setup&gt;
  import { ref } from 'vue';
  //Get child component ref  const todoItemVueRef = ref(null)
  // Methods to call subcomponents  const callItemFuncHandel = () =&gt; {
      ()
  }
&lt;/script&gt;

Use

existvue3.0andvue3.2Created inVuexThere is no difference, but<template>Use Vuex in templatesstoreThere are nuances.

import { createStore } from 'vuex';
import { ADD_ITEM_LIST, REDUCE_ITEM_LIST, CHANGE_ITEM_LIST_ASYNC } from './constants';

export default createStore({
  state: {
    itemList: [
      { text: 'Learn JavaScript', done: true },
      { text: 'Learn Vue', done: false },
      { text: 'Build something awesome', done: false },
    ],
  },
  getters: {
    doneItemList: (state) =&gt; ((todo) =&gt; ),
  },
  mutations: {
    // Use the ES2015-style computed attribute naming function to use a constant as the function name    [ADD_ITEM_LIST](state, item) {
      ('Add data', item);
      (item);
    },
    [REDUCE_ITEM_LIST](state) {
      ('Reduce data');
      ();
    },
  },
  actions: {
    [CHANGE_ITEM_LIST_ASYNC]({ commit, state }, todoItem) {
      /// Simulate network requests      setTimeout(() =&gt; {
        commit(ADD_ITEM_LIST, todoItem);
        ('state===', state);
      }, 1000);
    },
  },
  modules: {
  },
});

existvue3.0We usually match the returnDeconstruct, then you can directly<template>Used instateValues ​​in

&lt;template&gt;
  &lt;div class="todo-item"&gt;
    &lt;ol&gt;
      &lt;li v-for="(item,index) in itemList" :key="index" class="todos" @click="clickItem(index)"&gt;
        {{  }}
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
  export default {
  name: 'TodoItem',
  setup(props, { emit }) {
    return {
      // Deconstruct      ...,
      clickItem,
      count,
      isShow,
      showSubComponent,
    }
  }
};
&lt;/script&gt;

vue3.2There is no return in it, we need to display what we want to usestareValue of

&lt;template&gt;
  &lt;div class="todo-item"&gt;
    &lt;ol&gt;
      &lt;li v-for="(item,index) in itemList" :key="index" class="todos" @click="clickItem(index)"&gt;
        {{  }}
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script setup&gt;
import { useStore } from 'vuex';
const store = useStore()
// Use it in <template> after obtainingconst itemList = 
&lt;/script&gt;

8. v-bind in <style>

<style>In-housev-bind: Used in SFC<style>Dynamic CSS values ​​that enable component state-driven in the tag

<script setup>
import { ref, watchEffect } from 'vue';
const color = ref('black')
const callChangeColorHandel = () => {
  if( === 'black') {
     = 'red'
  }else {
     = 'black'
  }
}
</script>
<style lang="scss" scoped>
.todo-list {
  color: v-bind(color);
}
</style>

triggercallChangeColorHandelFunction, in<style>In-housev-bindThe responsive state that instructions can be dynamically bound.

3. Summary

Overall, the introduction of setup syntax sugar simplifies the useComposition APIThe long-lasting template code means that the code is more concise and readable. And the official introductionvue3.2The speed of interface rendering and memory usage have been optimized. This article only summarizes the common methods of setup syntax sugar. Morevue3.2You can check the new features in the official document.

Some references:

Vue3.2

Vuex

This is the end of this article about the use of Vue3.2 syntactic sugar. For more information about the use of Vue3.2 syntactic sugar, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!