Show pageOld revisionsBacklinksFold/unfold allBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ==== tsx component best practice ==== bare bone <code tsx> import { computed, defineComponent, defineProps, type PropType } from 'vue' type ModelType = __MODEL_TYPE__; export default defineComponent({ props: { modelValue: { type: Object as PropType<ModelType>, default: () => ({} as ModelType), }, 'onUpdate:modelValue': { type: Function as PropType<(val: ModelType) => void>, }, }, setup(props) { const modelValue = computed({ get() { return props.modelValue; }, set(val: ModelType) { props['onUpdate:modelValue']?.(val); }, }); return () => <></>; }, }); </code> <code tsx> import { defineComponent } from 'vue' export default defineComponent( <T,>(props: { message: T }) => { return () => <></> }, { props: [] } ) </code> <code tsx> import { defineComponent } from 'vue' export default defineComponent({ setup() { return () => <></> } }) </code> ++++ tsx component | <code tsx> import { defineComponent } from 'vue'; export interface Expose { } export default defineComponent({ name: 'App', props: { modelValue: { type: Object as PropType<FormData>, required: true } }, emits: ['update:modelValue'], setup(props: { a: 1 }, { emit, slots, expose }) { const count = ref(0); const inc = () => { count.value++; }; expose({ ... } satisfies Expose) // https://github.com/vuejs/core/issues/6643#issuecomment-2232546917 return () => ( <div onClick={withModifiers(inc, ['self'])}>{count.value}</div> <h1>{slots.default ? slots.default() : 'foo'}</h1> ); }, }); // In other components import CompA, {Exposed} from "./CompA" const componentRef = ref<ComponentInstance<typeof CompA> & Exposed>() <CompA ref={el => componentRef.value = el}> {{ default: () => 'default', slotA: () => 'slotA' }} </CompA> </code> ++++ ==== tsx table ==== ++++ tsx table | <code tsx> import BaseContainer from '@/components/BaseContainer' import Pagination from '@/components/Pagination' import { ElForm, ElFormItem, ElInput, ElTable, ElTableColumn, ElButton } from 'element-plus' import { defineComponent, onMounted, ref } from 'vue' import {ItemType} from './types' type PaginationConfiguration = Pick<IResponsePage, 'total' | 'pageNum' | 'pageSize'> type QueryParams = Partial<Pick<Item, never>> type Item = ItemType export default defineComponent({ setup() { const loading = ref(false) const tableData = ref<Item[]>([]) const queryParams = ref<QueryParams>({}) const paginationConfig = ref<PaginationConfiguration>({ total: 0, pageNum: 1, pageSize: 10 }) function handleQuerySearch() { getTableData() } function handleQueryReset() { queryParams.value = {} getTableData() } function handleAdd() {} // @ts-expect-error function handleEdit(row: Item) {} // @ts-expect-error function handleDelete(row: Item) {} async function getTableData() { // @ts-expect-error const res = { data: [{}] } loading.value = true // paginationConfig.value.total = loading.value = false } function handleKeydown(e: KeyboardEvent) { if (e.key === 'Enter') handleQuerySearch() } onMounted(() => { getTableData() }) return () => { return ( <BaseContainer fill back> <div class="flex h-full flex-col"> <ElForm model={queryParams.value} class="flex items-center gap-3 w-full flex-wrap"> <ElFormItem label="被征收人编号" prop="personId"> <ElInput v-model={queryParams.value.personId} placeholder="请输入被征收人编号" clearable style="width: 200px" onKeydown={handleKeydown} /> </ElFormItem> <ElFormItem class="ml-auto"> <ElButton type="primary" icon="ElIconSearch" onClick={handleQuerySearch}> 搜索 </ElButton> <ElButton icon="ElIconRefresh" onClick={handleQueryReset}> 重置 </ElButton> </ElFormItem> </ElForm> <div class="flex mb-3"> <div> <ElButton type="primary" icon="ElIconPlus" onClick={handleAdd}> 新增 </ElButton> </div> </div> <ElTable class="flex-[1-1-0]" v-loading={loading.value} data={tableData.value}> <ElTableColumn width="60" type="selection" align="center" /> <ElTableColumn label="序号" width="60" type="index" align="center"> {(scope) => ( <span> {(paginationConfig.value.pageNum - 1) * paginationConfig.value.pageSize + scope.$index + 1} </span> )} </ElTableColumn> <ElTableColumn label="" align="center"> <template> <div>123</div> </template> </ElTableColumn> <ElTableColumn label="" align="center" prop="" /> <ElTableColumn label="操作" align="center" width="100"> {(scope) => ( <div class="flex align-center justify-center flex-wrap"> <ElButton link type="primary" onClick={() => handleEdit(scope.row)} > 编辑 </ElButton> <ElButton link type="danger" onClick={() => handleDelete(scope.row)} > 删除 </ElButton> </div> )} </ElTableColumn> </ElTable> <div class="relative"> <Pagination layout="->, total, sizes, prev, pager, next, jumper" v-model:page={paginationConfig.value.pageNum} v-model:limit={paginationConfig.value.pageSize} total={paginationConfig.value.total} onPagination={() => getTableData()} /> </div> </div> </BaseContainer> ) } } }) </code> ++++ ==== tsx _form ==== ++++ tsx _form | <code tsx> import { computed, defineComponent, PropType } from 'vue' import BaseCard from '@/components/BaseCard/Index' import type { AssessmentObjective } from './types' import { ElForm, ElFormItem } from 'element-plus' const rules = {} export default defineComponent({ props: { modelValue: { type: Object as PropType<AssessmentObjective>, default: () => ({}) } }, emits: ['update:modelValue'], setup(props, { emit }) { const modelValue = computed({ get() { return props.modelValue }, set(val) { emit('update:modelValue', val) } }) return () => ( <ElForm model={modelValue.value} rules={rules} class="flex flex-col gap-3"> <BaseCard title="基础信息"> <div class="grid grid-cols-2 gap-4"> <ElFormItem label="企业名称" prop="companyName"> <span>name</span> </ElFormItem> </div> </BaseCard> </ElForm> ) } }) </code> ++++ ==== tsx add ==== ++++ tsx add | <code tsx> import { defineComponent, ref } from 'vue' import BaseContainer from '@/components/BaseContainer/BaseContainer.vue' import Form from './_Form' import { AssessmentObjective } from './types' import { ElButton } from 'element-plus' export default defineComponent({ setup() { const form = ref<AssessmentObjective>({}) function handleSubmit() {} return () => ( <BaseContainer fill back> {{ default: () => <Form v-model={form.value} />, 'header-options': () => ( <ElButton type="primary" onClick={handleSubmit} icon="ElIconDocument"> 提交 </ElButton> ) }} </BaseContainer> ) } }) </code> ++++ ==== tsx slots type ==== ++++ tsx slots type | <codeprism tsx> const Component = defineComponent({ props: { config: { type: Array as PropType<EntityInfo[]> } }, slots: Object as SlotsType<{ default: ({ foo: string; bar: number }) => JSX.Element }>, setup: (props, { slots }) => { if (props.config == null) throw Error('Config can not be null') const context = createReferenceInstance(props.config) provide(refInjectionKey, context) return () => <>{slots.default && slots.default()}</> } }) const s = new Component().$slots const a = ( <Component> { { default: (scope) => { scope } } as typeof s } </Component> ) </codeprism> ++++ snippets/vue.txt Last modified: 2025/11/05 12:18by lingao