1. Overview
existVue2
During the period, the various variables, methods, calculation attributes, etc. defined in the component are stored separately indata
、methods
、computed
Among 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.0
Combination APIsetup
The 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.0
When building components, you always need to return the method variables defined outside to<template>
, more troublesome.vue3.2
The 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.0
andvue3.2
Comparison of structure of single file component (SFC, i.e. .vue file)
-
vue3.0
Components
<template> <div> </div> </template> <script> export default { components: { }, props: { }, setup () { return {} } } </script> <style lang="scss" scoped> </style>
-
vue3.2
Components
<template> <MyTestVue :title="title" @click="changeTitle" /> </template> <script setup> import MyTestVue from './'; import { ref } from 'vue'; const title = ref('Test it') const changeTitle = () => { = 'Hello,World' } </script> <style lang="scss" scoped> </style>
contrast
vue3.0
andvue3.2
The main change of the version of component template is that it is no longer available in 3.2.setup
function, 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.0
Use 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.0
middle,prop
Availableprops
Options to declare
<script> 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 () } } </script>
vue3.2
In the component,props
AvailabledefineProps()
Macro declare
<script setup> const props = defineProps(['foo']) // orconst propsOther = defineProps({ title: String, likes: Number }) () </script>
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.
<script setup> 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 [, ] = (' ') } }) </script>
When called = 'John Doe'
hour,setter
Will be called, andfirstName
andlastName
Will be updated invue3.2
We 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 usewatch
The function triggers the callback function every time the responsive state changes.watch
The first parameter can be a different form of "data source": it can be a ref
(including computed properties), a responsive object, agetter
An 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 incoming
itemList
When 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 incoming
itemList
When 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>
watch
You can also listen to multiple attributes at the same time:
<script setup> import { ref,watch } from 'vue'; const props = defineProps({ title: String, itemList: { type: Array, default: () => [{ text: 'title', value: 0 }] } }) // Listen to multiple attributes at the same timewatch(() => [,],(newValue,oldValue) => { ('newValue===',newValue); ('oldValue===',oldValue); },{deep:true}) </script>
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,Vue
The 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 incoming
When 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.0
If our child component triggers the parent component's method, our approach:
Subcomponents <script> export default { emits: ['inFocus', 'submit'], setup(props, ctx) { ('submit',params) } } // Or you can deconstruct emitexport default { setup(props,{emit}) { emit('submit',params) } } </script> Parent component <template> <Children @submit="submitHandel"/> </div> </template> <script> export default { name: 'TodoItem', setup(props, { emit }) { const submitHandel = () => { ('The child component calls the submitHandel method of the parent component'); } return { submitHandel, } } }; </script>
vue3.2
In syntax sugar, the event to be triggered by the child component needs to be explicitly passed.defineEmits()
Macro declare
Subcomponents <script setup> const emit = defineEmits(['inFocus', 'submit']) function buttonClick(parmas) { emit('submit', parmas) } </script> Parent component <template> <Children @submit="submitHandel"/> </div> </template> <script setup> const submitHandel = () => { ('The child component calls the submitHandel method of the parent component'); } }; </script>
6.2 The parent component calls the child component method or property
vue3.0
If 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.
<script> // Subcomponentssetup(props, { emit }) { const isShow = ref(false) // The parent component calls this method const showSubComponent = () => { = ! } return { // return showSubComponent, } } </script>
Passed in the parent componentref
Get the child component and access the method exposed by the child component
Parent component <template> <div class="todo-list"> <TodoItemVue :itemList="itemList" @clickItemHandel="clickItemHandel" ref="todoItemVueRef" /> </div> </template> <script> import { ref } from 'vue'; export default { setup(props, { emit }) { //Get child component ref const todoItemVueRef = ref(null) // Methods to call subcomponents const callItemFuncHandel = () => { () } return { todoItemVueRef } } }; </script>
vue3.2
In syntax, the parent component is called the same way, and the child component passesdefineExpose()
Expose methods or attributes
Subcomponents <script setup> const isShow = ref(false) // The parent component calls this methodconst showSubComponent = () => { = ! } //Expose the method through defineExposedefineExpose({ showSubComponent }) </script> Parent component <template> <div class="todo-list"> <TodoItemVue :itemList="itemList" @clickItemHandel="clickItemHandel" ref="todoItemVueRef" /> </div> </template> <script setup> import { ref } from 'vue'; //Get child component ref const todoItemVueRef = ref(null) // Methods to call subcomponents const callItemFuncHandel = () => { () } </script>
Use
existvue3.0
andvue3.2
Created inVuex
There is no difference, but<template>
Use Vuex in templatesstore
There 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) => ((todo) => ), }, 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(() => { commit(ADD_ITEM_LIST, todoItem); ('state===', state); }, 1000); }, }, modules: { }, });
existvue3.0
We usually match the returnDeconstruct, then you can directly
<template>
Used instate
Values in
<template> <div class="todo-item"> <ol> <li v-for="(item,index) in itemList" :key="index" class="todos" @click="clickItem(index)"> {{ }} </li> </ol> </div> </template> <script> export default { name: 'TodoItem', setup(props, { emit }) { return { // Deconstruct ..., clickItem, count, isShow, showSubComponent, } } }; </script>
vue3.2
There is no return in it, we need to display what we want to usestare
Value of
<template> <div class="todo-item"> <ol> <li v-for="(item,index) in itemList" :key="index" class="todos" @click="clickItem(index)"> {{ }} </li> </ol> </div> </template> <script setup> import { useStore } from 'vuex'; const store = useStore() // Use it in <template> after obtainingconst itemList = </script>
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>
triggercallChangeColorHandel
Function, in<style>
In-housev-bind
The responsive state that instructions can be dynamically bound.
3. Summary
Overall, the introduction of setup syntax sugar simplifies the useComposition API
The long-lasting template code means that the code is more concise and readable. And the official introductionvue3.2
The speed of interface rendering and memory usage have been optimized. This article only summarizes the common methods of setup syntax sugar. Morevue3.2
You 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!