How to write vue3 syntax in actual development of vue3+ts

The development of vue3 syntax

  1. Vue3's support for composition api in earlier versions (before 3.0.0-beta.21) can only be used in the component option setup function.
  2. Added experimental feature <script setup> in version 3.0.0-beta.21. If you use it, you will be prompted that <script setup> is still in the experimental feature stage.
  3. The experimental status of <script setup> was removed in version 3.2.0. From then on, <script setup> was declared to be officially used and became one of the stable features of the framework.

So we will start using the writing method after 3.2.0 now.

Advantage

Compared with the component option setup function, <script setup> has the following advantages:

  1. Less and more concise code, no need to use return {} to expose variables and methods, no need to actively register when using components;
  2. Better Typescript support, using pure Typescript to declare props and throw events will no longer be as lame as in the option api;
  3. Better runtime performance;
    Of course, <script setup> also has its own shortcomings, such as the need to learn additional APIs.

Composition API type constraints

<script setup lang="ts">
import {
    
     ref, reactive, computed } from 'vue'
 
type User = {
    
     
  name: string
  age: number
}
 
// ref
const msg1 = ref('')  //  会默认约束成 string 类型,因为ts类型推导
const msg2 = ref<string>('')  //  可以通过范型约束类型
const user1 = ref<User>({
    
     name: 'tang', age: 18 })  //  范型约束
const user2 = ref({
    
    } as User)  // 类型断言
 
// reactive
const obj = reactive({
    
    })
const user3 = reactive<User>({
    
     name: 'tang', age: 18 })
const user4 = reactive({
    
    } as User)
 
// computed
const msg3 = computed(() => msg1.value)
const user5 = computed<User>(() => {
    
    
  return {
    
     name: 'tang', age: 18 }
})
</script>

compiler macro

Compiler macros include: defineProps, defineEmits, withDefaults, defineExpose, etc.

The compiler macro can only be used within the <script setup> block, does not need to be imported, and will be compiled together when processing the <script setup> block.

The compiler macro must be used at the top level of <script setup> and cannot be referenced in local variables of <script setup>

defineProps

There is no component configuration item in the <script setup> block, which means there is no props option. You need to use defineProps to declare props-related information. The object received by defineProps is the same as the value of component option props.

I quoted pug here. If you need to install it, you can use it directly. <template lang="pug">
The advantage is that it can reduce the amount of code and the hierarchy is clear

npm install pug
// componentA.vue 组件
<template lang="pug">
div
    div {
    
    {
    
    `我的名字是${
      
      name},今年${
      
      age}`}}
    div(v-for="item in list",:key="item.name") {
    
    {
    
    `我的名字是${
      
      item.name},今年${
      
      item.age}`}}
</template>
<script setup lang="ts">
interface item {
    
    
    name: string,
    age: string
}
const props = defineProps<{
    
    
    name: string,
    age: string,
    list?: item[] // ?非必传参数
}>()
</script>
// home.vue 页面
<template lang="pug">
.mainBg
    componentA(:name="name",:age="age", :list="list")
</template>

<script lang="ts" setup>
import {
    
     ref } from 'vue';
import componentA from '@/components/componentA.vue';
let name = ref('')
const age = ref('')
const list = ref(
    [
        {
    
    
            name: '张三',
            age: '20'
        },
        {
    
    
            name: '李四',
            age: 18
        },
        {
    
    
            name: '王五',
            age: 25
        },
    ]
)
<style lang="scss">
.mainBg {
    
    
    padding: 10px;
}
</style>

At this time, you can see that the name and age in TS writing have no defined default values
Page effect
Insert image description here
Vue3 provides us with the compilation of withDefaults Container macro to provide default values ​​for props

// componentA.vue 组件
<template lang="pug">
div
    div {
    
    {
    
    `我的名字是${
      
      name},今年${
      
      age}`}}
    div(v-for="item in list",:key="item.name") {
    
    {
    
    `我的名字是${
      
      item.name},今年${
      
      item.age}`}}
</template>
<script setup lang="ts">
interface item {
    
    
    name: string,
    age: string
}
interface Props {
    
    
    name: string,
    age: string,
    list?: item[]
}
const props = withDefaults(defineProps<Props>(),{
    
    
    name: "小cc",
    age: "18",
    list: ()=> []
})
</script>

Insert image description here

Define the default value here and save it. Look at the page and find that the default value is still not displayed.
This is because when we use ref to assign values ​​​​to name and age on the home page, ' ' So he regarded empty as the default value and did not display the default value given in withDefaults. At this time, we write name and age as
let name = ref() const age = ref()< /span>
Insert image description here
There is another situation when the parameters passed are empty when no default value is defined for props
Insert image description here
Insert image description here
Insert image description here

defineEmits

Similarly, there is no component configuration item emits in the <script setup> block. You need to use the defineEmits compiler macro to declare emits-related information.

// componentA.vue 组件
<template lang="pug">
div
    div {
    
    {
    
    `我的名字是${
      
      name},今年${
      
      age}`}}
    //- div(v-for="item in list",:key="item.name") {
    
    {`我的名字是${item.name},今年${item.age}`}}
    el-button(type="primary",@click="setName") 向父组件发送 name
    el-button(type="primary",@click="setAge") 向父组件发送 age
</template>
<script setup lang="ts">
interface item {
    
    
    name: string,
    age: string
}
interface Props {
    
    
    name: string,
    age: string,
    list?: item[]
}
const props = withDefaults(defineProps<Props>(),{
    
    
    name: "小cc",
    age: "18",
    list: ()=> []
})
const emits = defineEmits<{
    
    
    (e: 'changeName', value: string) : void,
    (e: 'changeAge', value: string) : void,
}>()
const setName = () => {
    
    
    emits('changeName', '小橙子')
}
const setAge = () => {
    
    
    emits("changeAge", "28")
}
</script>
// home.vue
<template lang="pug">
.mainBg
    componentA(:name="name",:age="age", :list="list", @changeName="changeName",@changeAge="changeAge")
</template>

<script lang="ts" setup>
import {
    
     ref } from 'vue';
import componentA from '@/components/componentA.vue';
let name = ref('')
const age = ref('')
const list = ref(
    [
        {
    
    
            name: '张三',
            age: '20'
        },
        {
    
    
            name: '李四',
            age: 18
        },
        {
    
    
            name: '王五',
            age: 25
        },
    ]
)
const changeName = (val: string) => {
    
    
    name.value = val
}
const changeAge = (val: string) => {
    
    
    age.value = val
}
<style lang="scss">
.mainBg {
    
    
    padding: 10px;
}
</style>

Insert image description here
after click
Insert image description here

defineExpose

In Vue3, any binding declared in <script setup> will not be exposed by default, that is, the binding declared by the component instance cannot be obtained through the template ref.

Vue3 provides the defineExpose compiler macro, which can explicitly expose variables and methods declared in the components that need to be exposed.

In this case, when the parent component of the scene needs to directly call the method inside the subcomponent or modify the value in the subcomponent, the method or value needs to be exposed through defineExpose to operate.

// componentB.vue
<template lang="pug">
div
    h1 组件B
    h1 {
    
    {
    
    msg}}
</template>
<script setup lang="ts">
import {
    
    ref} from 'vue'

const msg = ref('今天天气不怎么好')

const changeMsg = (v: string) => {
    
    
    msg.value = v
}

// 对外暴露的属性 需要用ref 调用子组件方法是需要把方法暴露出去
defineExpose({
    
    
  msg,
  changeMsg,
})
</script>
<template lang="pug">
.mainBg
    el-button(type="primary",@click="handleChangeMsg") 组件B
    componentB(ref="root")
</template>

<script lang="ts" setup>
import {
    
     ref } from 'vue';
import componentB from '@/components/componentB.vue';
const root = ref<any>(null)
const handleChangeMsg = () => {
    
    
    root.value.changeMsg("果然 下雨了")
}
</script>


<style lang="scss">
.mainBg {
    
    
    padding: 10px;
}
</style>

Insert image description here
Insert image description here
If you comment out defineExpose
Insert image description here
Insert image description here
Since this method is not exposed, this method cannot be found changeMsg is not a function

Guess you like

Origin blog.csdn.net/double_Fly_/article/details/125218204