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
system: CentOS 7 RPM packages: mysql-community-cl...
introduce Vue Router is the official routing mana...
Docker-machine is a Docker management tool offici...
MySQL service 8.0.14 installation (general), for ...
According to null-values, the value of null in My...
Question: After the computer restarts, the mysql ...
Preface meta is an auxiliary tag in the head area...
Preface When my team was developing the tax syste...
Installed Docker V1.13.1 on centos7.3 using yum B...
1. COUNT(*) and COUNT(COL) COUNT(*) usually perfo...
Refer to the tutorial on setting up FTP server in...
I recently used nginx in a project, and used Java...
view: Views in MySQL have many similarities with ...
1. Naming conventions 1. Database names, table na...
accomplish This effect is difficult to replicate ...