Vue+TS+默认组合式API

对于前端的开发,我一直有在关注,Vue的写法有点多,是好事还是坏事,我也搞不懂了,几种写法我也都试了一试,可能是TS的原因,觉得并不是很完美,默认的写法对TS兼容性应该是最好的,兼容的场景还是蛮多的,但是监听自定义事件的时候,没有提示。

<script setup lang="ts">的写法监听自定义事件的提示十分友好,但这种写法访问子组件里的属性时也不友好。但是转念想一想,组件之间应该是独立的,况且Vue也提供了父子组件交互的方法,父组件直接操作子组件这种行为并不推荐。这种写法代码的简洁度很高,按常理来说,代码越少越易维护。自己斟酌。

我是期望前端发展如后端的springboot一样,写法规范统一起来,不管从维护上,还是开发上都能减少一些没有必要的工作量。

默认组合式API写法

响应式

简单的响应式

<template>
    <h3>{{ name}}</h3>
    <h3>{{sum}}</h3>
</template>
<script lang="ts">
import { defineComponent, toRefs, reactive, computed, watch, ref } from 'vue';

export default defineComponent({
    name: 'HelloWorld',

    setup() {
        // 定义
        const sum = ref(200)
        const name = ref('hahahahah')
        // 使用第一步
        return {
            sum,name
        }

    }
})
</script>

复杂的响应式

<template>
    <!-- 使用 -->
    <h3>{{user.name}}</h3>
    <h3>{{user.age}}</h3>
    <h3>{{user.sex}}</h3>
</template>
<script lang="ts">
import { defineComponent, toRefs, reactive, computed, watch, ref } from 'vue';

export default defineComponent({
    name: 'HelloWorld',
    setup() {
        // 定义一个变量
        const user = reactive({
            name: '小红',
            age: 23,
            sex: '男'
        })
        // 导出才能在模板中使用
        return {
            user
        }
    }
})
</script>
<style scoped>
</style>

一些小妙招

不想在return中写太多的感觉没啥意义的代码,这时候我们就可以这样写

<template>
    <!-- 使用 -->
    <h3>{{ user.name }}</h3>
    <h3>{{ user.age }}</h3>
    <h3>{{ user.sex }}</h3>

    <h3>{{ sum }}</h3>

    <button type="button" @click="sunc('233')">按钮</button>
</template>
<script lang="ts">
import { defineComponent, toRefs, reactive, computed, watch, ref } from 'vue';
export default defineComponent({
    name: 'HelloWorld',
    setup() {
        const data = reactive({
            user: {
                name: '小红',
                age: 23,
                sex: '男'
            },
            // 可以写任意变量,就不需要在return中写了
            sum: 200,
            // 函数也可以在这里面写
            sunc(id:string):void {
                console.log('id=' + id);
            },
            // 计算属性也可以在这里写,就不需要在return里面写很多代码了。
        })
        return {
            // 解构导出,访问的时候不需要带上data
            ...toRefs(data)
        }
    }
})
</script>
<style scoped>
</style>

监听事件

关于监听的API还挺多的,这里不过多介绍,只介绍常见的。

简单的监听

setup() {
       const fastName = ref('3222')
       watch(fastName,(newVal,oldVal)=>{
           console.log(newVal +'---'+oldVal);
       })
       return {
           fastName
       }
   }

侦听一个Getter函数

setup() {
    // 使用reactive定义的不能直接data.user.name来监听。
    const data = reactive({
        user: {
            name: '小红',
            age: 23,
            sex: '男'
        },
        // 可以写任意变量,就不需要在return中写了
        sum: 200
    })
    // 使用这种方式就是可以监听得到。
    watch(() => data.user.name, (newVal, oldVal) => {
        console.log(newVal + '---' + oldVal);
    })
    return {
        // 解构导出,访问的时候不需要带上data
        ...toRefs(data)
    }
}

监听多个源

setup() {
    const fooRef = ref("foo")
    const barRef = ref("bar")
    watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
        console.log('newVal = ' + foo+ '-' + bar+',,,oldVal' + prevFoo+ '-' + prevBar);
    })
}

定义Props

简单的定义

父组件传值时会有类型校验。

export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: {
        type: String,
        
    },
  },
  setup(props,ctx) {
  }
})

高端的定义

interface Book {
  title: string
  author: string
  year: number
}
export default defineComponent({
  name: 'HelloWorld',
  props: {
    // 普通变量
    msg: {
      type: String,
      // 默认值
      default: () => ('这是默认值'),
      // 校验
      validator: (msg: String) => {
        return msg.length > 3
      }
    },
    // 对象变量
    book: {
        // 要使用PropType来定义变量
      type: Object as PropType<Book>,
      // 请务必使用箭头函数
      default: () => ({
        title: '这是一个错误'
      }),
      validator: (book: Book) => !!book.title
    }
  },
})

自定义事件

props和自定义事件都属于组件化常用的,自定义事件的历史包袱过重,在setup的写法中得到了解决,这个组合式API中没啥好的办法

// 这里传入第二个参数
setup(props, ctx) {
    const aaaa = reactive({
      changeTaa() {
        // 抛出事件,事件名为del
        ctx.emit('del', 233)
      },
    })
    return {
      ...toRefs(aaaa)
    }
  }


<!-- 监听部分 -->
<HelloWorld ref="model" @del="testEmit"/>

// 当在子组件中抛出事件此方法就会被触发,我们还可以用这个方法返回值来给子组件传递数据。工欲善其事必先利其器,半吊子很难的啦。

testEmit(id:string) {
    console.log('自定义事件触发了');
    console.log('id='+id);
}

到这,常用的组合式API的写法其实就已经差不多了。

封面

集原美Sky train


Vue+TS+默认组合式API
https://wangijun.com/2021/11/29/vue-03/
作者
无良芳
发布于
2021年11月29日
许可协议