前言
在Vue 3 + TypeScript项目中,将TypeScript相关的代码分离到单独的文件可以提高代码的可维护性和可复用性。
页面或组件的分离
模板
TestView.vue
1 2 3 4 5 6 7 8 9 10 11 12 13
| <template> <div class="test_view_root"> {{ pageMsg }} </div> </template>
<script lang="ts" setup> import { usePage } from "./TestView";
const { pageMsg } = usePage(); </script>
<style src="./TestView.less" lang="less" scoped></style>
|
TS
TestView.ts
1 2 3 4 5 6 7 8 9 10 11 12
| import { ref, onMounted } from "vue";
export function usePage() { const pageMsg = ref("TestView")
onMounted(() => { console.info('onMounted', pageMsg.value) }) return { pageMsg } }
|
注意
下面的这种方式是不建议的,像onMounted是不会触发的。
在分离的TS中导出
1 2 3 4 5
| export const dataList: TNews[] = reactive([])
onMounted(() => { })
|
在页面中导入
1 2 3
| import { dataList } from './NewsManager'
|
样式
TestView.less
setup语法糖
并不是所有的语法都能在分离的TS中写。
有部分 API 和语法通常是在 <script setup> 中使用,如
defineProps
defineEmits
defineModel
示例
defineProps:用来定义组件接收的 props,支持类型推导,让代码在 TypeScript 环境下类型更安全。
1 2 3 4 5 6 7 8 9 10 11
| <template> <div>{{ message }}</div> </template>
<script setup lang="ts"> import { defineProps } from 'vue';
const props = defineProps({ message: { type: String, default: 'common' } }) </script>
|
defineEmits:用于定义组件可以触发的自定义事件,同样支持类型检查。
1 2 3 4 5 6 7 8 9 10 11
| <template> <button @click="emit('customEvent', 'event data')">触发自定义事件</button> </template>
<script setup lang="ts"> import { defineEmits } from 'vue';
const emit = defineEmits<{ (e: 'customEvent', data: string): void; }>(); </script>
|
defineModel:该 API 用于在组件中创建双向数据绑定,允许子组件和父组件之间进行双向数据同步。
1 2 3 4 5 6 7 8 9 10
| <template> <input v-model="modelValue" /> </template>
<script setup lang="ts"> import { defineModel } from 'vue';
const model = defineModel<string>(); const modelValue = model.value; </script>
|
defineModel
模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <template> <div> <input v-model="modelValue" @input="handleChange($event.target.value)" /> </div> </template>
<script lang="ts" setup> import { defineModel } from 'vue'; import { usePage } from './modelLogic.ts';
// 使用 defineModel 创建双向绑定 const model = defineModel<string>(); const modelValue = model.value;
// 调用封装的逻辑函数 const { handleChange } = usePage(model); </script>
|
分离的TS
1 2 3 4 5 6 7 8 9 10 11 12 13
| import type { Ref } from 'vue'
export function usePage(modelValue: Ref<string | undefined>) { const handleChange = (newValue: string) => { modelValue.value = newValue; };
return { handleChange }; }
|
defineProps
1 2 3 4 5 6 7 8 9 10 11
| interface ReportItem { goodsId: number name: string }
const props = defineProps({ compData: { type: Object as () => ReportItem, required: true } })
const { handleChange } = usePage(props);
|
或者这样写
1 2 3 4 5
| import { defineProps, type PropType } from 'vue'
const props = defineProps({ compData: { type: Object as PropType<ReportItem>, required: true } })
|
分离的TS
1 2 3 4 5 6 7 8 9 10 11
| export function usePage(props: { compData: ReportItem }) { const handleChange = (newValue: string) => { modelValue.value = newValue; };
return { handleChange }; }
|
工具类的分离
将一些通用的工具函数提取到单独的 .ts 文件中。
示例步骤
创建工具函数文件:例如,创建一个名为 utils.ts 的文件,定义一些工具函数。
1 2 3 4
| export function formatDate(date: Date): string { return date.toLocaleDateString(); }
|
在组件中使用工具函数:在组件中引入并使用 formatDate 函数。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <template> <div> <p>Formatted Date: {{ formattedDate }}</p> </div> </template>
<script lang="ts" setup> import { ref } from 'vue'; import { formatDate } from './utils.ts';
const currentDate = ref(new Date()); const formattedDate = formatDate(currentDate.value); </script>
|
通过以上方法,你可以将不同类型的TypeScript代码分离到单独的文件中,使代码结构更加清晰。