foreword
Now, Vue3 has become the default version. Compared with Vue2, Vue3 has changed a lot. From the original combination API to option API. So the code style changes are relatively large. Why is there an options API? I personally think very good! .
To use Vue3, you must know setup, because setup is the stage for combined API performances. And after Vue3.2, the official quit the setup syntactic sugar, which makes us more comfortable when writing code! ! !
install volar
If your VScode has vuter
a plug-in installed before, please disable or uninstall it first, and then install it volar
. Because vuter
the plug-in is for Vue2, and the writing method of Vue3 is different from Vue3, especially after using setup syntax sugar, so there may be errors (compilation will not) or something when writing code. volar
The plugin is for Vue3. No error will be reported after installation, and there will be prompts. And click the small icon in the upper right corner, you can also display the html code, js code and css code separately, which is very good! ! !
Variables and methods in Vue3
previous usage
Through this example, we can know that the HTML template in Vue3 no longer needs a root tag , the data does not need to be data
defined in , and the method does not need to be methods
defined in . Moreover, the data and methods required in the template must be returned in setup
( return) .
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
</template>
<script>
import {
ref } from 'vue'
export default {
setup() {
let count = ref(0)
const increment = () => {
count.value ++
}
return {
count,
increment
}
}
}
</script>
Current usage (syntactic sugar for setup)
In <script setup>, you need to add the setup attribute to the script tag , so you no longer need to write the setup function, and the variables and methods used in the template do not need to return (return) . After comparing the codes, do you think there is something wrong?
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
</template>
<script setup>
import {
ref } from 'vue'
let count = ref(0)
const increment = () => {
count.value ++
}
</script>
Using components in Vue3
previous usage
// App.vue
<template>
<demo />
</template>
<script>
import Demo from './components/Demo.vue'
export default {
components: {
Demo }
}
</script>
Current usage (syntactic sugar for setup)
In <script setup>, you only need to import the component to use it in the template, and you no longer need to register the component yourself.
// App.vue
<template>
<demo />
</template>
<script setup>
import Demo from './components/Demo.vue'
</script>
Receive Props in Vue3 --> defineProps()
previous usage
The method of passing data to components remains unchanged. When receiving, you need to define the receiving in props. The first parameter received by the setup function is called props.
// App.vue
<template>
<demo msg="hi Demo, I'm your father!"/>
</template>
<script setup>
import Demo from './components/Demo.vue'
</script>
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
<h3>{
{
msg}}</h3>
</template>
<script>
import {
ref } from 'vue'
export default {
props: {
msg: {
type: String
}
},
setup(props) {
let count = ref(0)
const increment = () => {
count.value ++
}
console.log(props.msg)
return {
count,
increment
}
}
}
</script>
Current usage (syntactic sugar for setup)
In <script setup>, we do not have the opportunity to write the setup function, so we cannot receive the parameters passed when it is called. So there is a new API defineProps
which is a function. defineProps
Returns an object containing all props that can be passed to the component.
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
<h3>{
{
msg}}</h3>
</template>
<script setup>
import {
ref, defineProps } from 'vue'
const props = defineProps(['msg'])
console.log(props.msg)
let count = ref(0)
const increment = () => {
count.value ++
}
</script>
Inject custom events in Vue3 --> defineEmits()
previous usage
When a child component injects a custom event to the parent component, it needs to emits
define the event to be passed. The second parameter in the setup function is the context object ( we will not introduce it in detail here ), and then call emit
the method through this object to inject custom events.
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
<h3>{
{
msg}}</h3>
</template>
<script>
import {
ref } from 'vue'
export default {
props: {
msg: {
type: String
}
},
emits: ['hanlde-count'],
setup(props, centext) {
let count = ref(0)
const increment = () => {
count.value ++
centext.emit('hanlde-count', count.value)
}
console.log(props.msg)
return {
count,
increment
}
}
}
</script>
// App.vue
<template>
<demo
msg="hi Demo, I'm your father!"
@hanlde-count="hanldeCount"
/>
</template>
<script>
import Demo from './components/Demo.vue'
export default {
components: {
Demo },
setup() {
const hanldeCount = count => {
console.log(count)
}
return{
hanldeCount
}
}
}
</script>
Current usage (syntactic sugar for setup)
In <script setup>, when a child component wants to emit a custom event, it needs to defineEmits
define a custom event.
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
<h3>{
{
msg}}</h3>
</template>
<script setup>
import {
ref, defineProps, defineEmits } from 'vue'
const props = defineProps(['msg'])
const emit = defineEmits(['hanlde-count'])
console.log(props.msg)
let count = ref(0)
const increment = () => {
count.value ++
emit('hanlde-count', count.value)
}
</script>
The parent component in Vue3 gets the data or method of the component --> defineExpose()
previous usage
In subcomponents, when exposing component variables or methods, you don’t need to do other operations, you just need to ensure the variables or methods setup
in the function . return
Because script
all code in the tag expost default
is exposed using . In the parent component, you need to add ref
attributes to the child component, and then get the variables and methods of the child onMounted
component in the life cycle function .dom
Note: To obtain dom, it must be onMounted
obtained in the declaration cycle, because the page is not rendered, so do not obtain dom
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
<h3>{
{
msg}}</h3>
</template>
<script>
import {
ref } from 'vue'
export default {
props: ['msg'],
emits: ['hanlde-count'],
setup(props, context) {
let count = ref(0)
const name = ref('vernin')
const increment = () => {
count.value ++
context.emit('hanlde-count', count.value)
}
return {
count,
increment,
name
}
}
}
</script>
// App.vue
<template>
<demo
ref="demo"
msg="hi Demo, I'm your father!"
@hanlde-count="hanldeCount"
/>
</template>
<script>
import Demo from './components/Demo.vue'
import {
ref, onMounted } from 'vue'
export default {
components: {
Demo },
setup() {
const demo = ref(null) // 记得把 demo return 出去
// 错误写法:setup 函数无法获取dom -- setup相对于vue2的created钩子
// console.log(demo.value.name) // 报错
// console.log(demo.value.count) // 报错
// 正确写法:
onMounted(() => {
console.log('子组件Demo的count:', demo.value.count)
console.log('子组件Demo的name:', demo.value.name)
})
const hanldeCount = count => {
console.log(count)
}
return {
demo,
hanldeCount
}
}
}
</script>
Current usage (syntactic sugar for setup)
In <script setup>, there is no write export default
exposure. In order to specify the variables or methods to be exposed in the component, you need to use defineExpose
the variable. In the parent component, it is also ref
obtained by giving the child component properties.
// components/Demo.vue
<template>
<h2>Vue3.2中setup语法糖的使用</h2>
<button @click="increment">舔我 {
{
count }} 次了</button>
<h3>{
{
msg}}</h3>
</template>
<script setup>
import {
ref, defineProps, defineEmits, defineExpose } from 'vue'
const props = defineProps(['msg'])
const emit = defineEmits(['hanlde-count'])
let count = ref(0)
const increment = () => {
count.value ++
emit('hanlde-count', count.value)
}
const name = ref('vernin')
defineExpose({
name,
count
})
</script>
// App.vue
<template>
<demo
ref="demo"
msg="hi Demo, I'm your father!"
@hanlde-count="hanldeCount"
/>
</template>
<script setup>
import Demo from './components/Demo.vue'
import {
ref, onMounted } from 'vue'
const demo = ref(null)
onMounted(() => {
console.log('子组件Demo的count:', demo.value.count)
console.log('子组件Demo的name:',demo.value.name)
})
const hanldeCount = count => {
console.log(count)
}
</script>
Summarize
Comparing the setup syntax sugar with the setup function, we can easily see that using syntax sugar makes the code much cleaner and there will not be so many object nesting. There is no need to do any extra return, and the code is simplified a lot.
As I said earlier 要使用Vue3,那必须得会setup
, it’s actually not the case. Vue3 is also compatible with Vue2’s writing method, and it doesn’t have to be used setup
. However, after using setup, especially using setup syntax sugar, I have to say that it is really cool~~~
Finally, look at the advantages of the official combined API and the comparison chart between the official optional API and the combined API
- More flexible code organization
- More flexible code organization
- better type inference
- Smaller production packages