The defineComponent function simply encapsulates the setup function and returns an options object; export function defineComponent(options: unknown) { return isFunction(options) ? { setup: options } : options } The most important thing about defineComponent is that in TypeScript, it gives the component the correct parameter type inference. defineComponent overload function1: direct setup function // overload 1: direct setup function // (uses user defined props interface) export function defineComponent<Props, RawBindings = object>( setup: ( props: Readonly<Props>, ctx: SetupContext ) => RawBindings | RenderFunction ): DefineComponent<Props, RawBindings> 2: object format with no props // overload 2: object format with no props // (uses user defined props interface) // return type is for Vetur and TSX support export function defineComponent< Props = {}, RawBindings = {}, D = {}, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = EmitsOptions, EE extends string = string >( options: ComponentOptionsWithoutProps<Props,RawBindings,D,C,M,Mixin,Extends,E,EE> ): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> 3: object format with array props declaration // overload 3: object format with array props declaration // props inferred as { [key in PropNames]?: any } // return type is for Vetur and TSX support export function defineComponent< PropNames extends string, RawBindings, D, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record<string, any>, EE extends string = string >( options: ComponentOptionsWithArrayProps< PropNames, RawBindings,...> ): DefineComponent< Readonly<{ [key in PropNames]?: any }>, RawBindings,...> 4: object format with object props declaration // overload 4: object format with object props declaration // see `ExtractPropTypes` in ./componentProps.ts export function defineComponent< // the Readonly constraint allows TS to treat the type of { required: true } // as constant instead of boolean. PropsOptions extends Readonly<ComponentPropsOptions>, RawBindings, D, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record<string, any>, EE extends string = string >( options: ComponentOptionsWithObjectProps< PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE> ): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE> Development PracticeApart from the basic usage in unit testing, there are several points to note in the following ParentDialog component: How to write custom components and global components Type constraints for inject, ref, etc. How to write setup and the corresponding h injection problem How to write v-model and scopedSlots in tsx ParentDialog.vue <script lang="tsx"> import { noop, trim } from 'lodash'; import { inject, Ref, defineComponent, getCurrentInstance, ref } from '@vue/composition-api'; import filters from '@/filters'; import CommonDialog from '@/components/CommonDialog'; import ChildTable, { getEmptyModelRow } from './ChildTable.vue'; export interface IParentDialog { show: boolean; specFn: (component_id: HostComponent['id']) => Promise<{ data: DictSpecs }>; } export default defineComponent<IParentDialog>({ // Custom components in tsx still need to register components: { ChildTable }, props: { show: { type: Boolean, default: false }, specFn: { type: Function, default: noop } }, // note: setup must use arrow function setup: (props, context) => { // Fix the problem that 'h' function cannot be automatically injected in tsx // eslint-disable-next-line no-unused-vars const h = getCurrentInstance()!.$createElement; const { emit } = context; const { specFn, show } = props; // Usage of filter const { withColon } = filters; // inject usage const pageType = inject<CompSpecType>('pageType', 'foo'); const dictComponents = inject<Ref<DictComp[]>>('dictComponents', ref([])); // ref type constraint const dictSpecs = ref<DictSpecs>([]); const loading = ref(false); const _lookupSpecs = async (component_id: HostComponent['id']) => { loading.value = true; try { const json = await specFn(component_id); dictSpecs.value = json.data; finally loading.value = false; } }; const formdata = ref<Spec>({ component_id: '', specs_id: '', model: [getEmptyModelRow()] }); const err1 = ref(''); const err2 = ref(''); const _doCheck = () => { err1.value = ''; err2.value = ''; const { component_id, specs_id, model } = formdata.value; if (!component_id) { err1.value = 'Please select a component'; return false; } for (let i = 0; i < model.length; i++) { const { brand_id, data } = model[i]; if (!brand_id) { err2.value = 'Please select a brand'; return false; } if ( formdata.value.model.some( (m, midx) => midx !== i && String(m.brand_id) === String(brand_id) ) ) { err2.value = 'Brand duplicate'; return false; } } return true; }; const onClose = () => { emit('update:show', false); }; const onSubmit = async () => { const bool = _doCheck(); if (!bool) return; const params = formdata.value; emit('submit', params); onClose(); }; // note: In tsx, globally registered components such as element-ui still need to use kebab-case format???? return () => ( <CommonDialog class="comp" title="New" width="1000px" labelCancel="Cancel" labelSubmit="OK" vLoading={loading.value} show={show} onClose={onClose} onSubmit={onSubmit} > <el-form labelWidth="140px" class="create-page"> <el-form-item label={withColon('Component type')} required={true} error={err1.value}> <el-select class="full-width" model={{ value: formdata.value.component_id, callback: (v: string) => { formdata.value.component_id = v; _lookupSpecs(v); } }} > {dictComponents.value.map((dictComp: DictComp) => ( <el-option key={dictComp.id} label={dictComp.component_name} value={dictComp.id} /> ))} </el-select> </el-form-item> {formdata.value.component_id ? ( <el-form-item labelWidth="0" label="" required={true} error={err2.value}> <child-table list={formdata.value.model} onChange={(v: Spec['model']) => { formdata.value.model = v; }} onError={(err: string) => { err3.value = err; }} scopedSlots={{ default: (scope: any) => ( <p>{ scope.foo }</p> ) }} /> </el-form-item> ) : null} </el-form> </CommonDialog> ); } }); </script> <style lang="scss" scoped> </style> Summary
This is the end of this article about the role of Vue3 defineComponent. For more information about the role of Vue3 defineComponent, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: Using MySQL database in docker to achieve LAN access
>>: MySQL 8.0.18 installation and configuration graphic tutorial
illustrate: Using mysqldump –all-databases will e...
Description Solution VMware 15 virtual machine br...
A jQuery plugin every day - jQuery plugin to impl...
Table of contents Preparation Deployment process ...
Prerequisite: The web developer plugin has been in...
MySQL variables include system variables and syst...
The custom encapsulation code of the vue button c...
Table of contents 1. Overview 1. Explain statemen...
This article shares the specific code for WeChat ...
First, let's take a look at the relative leng...
1. Drop-down list example The code is as follows:...
This article shares the specific code of JQuery t...
This article is from the Apache Spark Meetup held...
This article example shares the specific code for...
Table of contents 1. Limit props to type lists 2....