Vue3的几种不同写法

1,570 阅读2分钟

简简单单写写不同风格的vue3代码,后续会带来不同写法具体分析,本文默认是TS写法

一、选项式

官方:使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 datamethods 和 mounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例

个人:和vue2写法一样,但不完全一样

import { defineComponent } from 'vue'
import type { PropType } from 'vue'

interface Book {
  title: string
  author: string
  year: number
}

export default defineComponent({
  props: {
    book: {
      // 提供相对 `Object` 更确定的类型
      type: Object as PropType<Book>,
      required: true
    },
    // 也可以标记函数
    callback: Function as PropType<(id: number) => void>
  },
  mounted() {
    this.book.title // string
    this.book.year // number

    // TS Error: argument of type 'string' is not
    // assignable to parameter of type 'number'
    this.callback?.('123')
  }
})

选项式 API 中对 props 的类型推导需要用 defineComponent() 来包装组件

虽然vue3只是选项式写法,但是例如filter过滤器vue3中不支持,所以不能按照vue2那种写法,可以封装一个方法,所以选择这种写法的时候,要考察一下vue2的那种写法,在vue3中是不支持的

二、组合式

vue3组合式有三种写法:setup函数、setup语法糖、tsx(jsx)

setup函数

<script lang="ts">
import { defineComponent, ref } from 'vue'
import { IUseTodo, useTodo } from '../../hooks'

export default defineComponent({
    name: 'Todoinput',
    setup () {
        const todoValue = ref<string>('')
        const { setTodo }: IUseTodo = useTodo()

        /**
         * 添加数据:输入框输入数据,点击回车添加数据
         */
        const setTodoValue = (e: KeyboardEvent): void => {
            if (e.keyCode === 13 && todoValue.value.trim().length) {
                setTodo(todoValue.value)
                todoValue.value = ''
            }
        }

        return {
            todoValue,
            setTodoValue
        }
    }
})
</script>

setup语法糖

<script setup lang="ts">
import { PropType } from 'vue'
import { ITodo, TODO_STATUS } from '@/typings'

interface IStatusState {
    DOING: TODO_STATUS;
    FINISHED: TODO_STATUS;
    WILLDO: TODO_STATUS
}

const statusState: IStatusState = {
    DOING: TODO_STATUS.DOING,
    FINISHED: TODO_STATUS.FINISHED,
    WILLDO: TODO_STATUS.WILLDO
}

const props = defineProps({
    item: {
        type: Object as PropType<ITodo>,
        required: true
    }
})

type emitType = {
    (e: 'removeTodo', id: number): void
    (e: 'setStatus', id: number): void
    (e: 'setDoing', id: number): void
}

const emit = defineEmits<emitType>()

const removeTodo = (id: number): void => {
    emit('removeTodo', id)
}
const setStatus = (id: number): void => {
    emit('setStatus', id)
}
const setDoing = (id: number): void => {
    emit('setDoing', id)
}
</script>

TSX

import { defineComponent, PropType } from 'vue'
import { ITodo } from '@/typings'
import TodoItem from '../TodoItem/index'
import { IUseTodo, useTodo } from '@/hooks'

export default defineComponent({
    name: 'TodoList',
    props: {
        todoList: Array as PropType<ITodo[]>
    },
    components: {
        TodoItem
    },
    setup () {
        const {
            removeTodo,
            setStatus,
            setDoing
        }: IUseTodo = useTodo()

        return {
            removeTodo,
            setStatus,
            setDoing
        }
    },

    render () {
        const {
            todoList,
            removeTodo,
            setStatus,
            setDoing
        } = this
        return (
            <div>
                {
                    todoList?.map((item: ITodo) => {
                        return (
                            <todo-item key={item.id} item={item} onRemoveTodo={removeTodo} onSetStatus={setStatus} onSetDoing={setDoing}/>
                        )
                    })
                }
            </div>
        )
    }
})

简单比较

setup函数setup语法糖TSX
变量需要return不需要return1、render方式需要2、在setup中写dom不需要
方法需要return不需要return1、render方式需要2、在setup中写dom不需要
组件需要注册不需要注册需要注册
传参propsdefinePropsprops
事件emitdefineEmitsemit

使用体验

setup入口函数方式比较基础,setup语法糖使用比较简便,新增了一些API,也省去好多代码,两者社区活跃度较高

tsx写法与react相似,tsx有vue和@type/nodes版本要求

代码组织方面,合理使用hooks,其实代码不会很乱~

有问题请指出,共同进步!!!