Custom components, for example:
1. Encapsulate custom components
<!-- src/components/ --> <script lang="ts"> import type { IDataItem } from "../type/customlist"; // IProps cannot be imported directly from the outside, there will be an error at present, and may be supported in the future (someone mentioned the issue)export interface IProps { title?: string; data: Array<IDataItem>; } </script> <script setup lang="ts"> import { onMounted } from "vue"; // Declare some properties, pass values to the parent component, and set default values to the partconst props = withDefaults(defineProps<IProps>(), { title: "CustomList", }); // Throw an event for use by the parent component// const emit = defineEmits(["click-item"]); const emit = defineEmits<{ (e: "click-item", item: IDataItem, $event: Event): void; }>(); const clickItem = function (item: IDataItem, e: Event) { // You can perform some operations in the function ("Custom component clicks on the item inside the component...", item, e); // Throw the macro-defined event emit("click-item", item, e); }; onMounted(() => { ("CustomList onMounted...", props); }); </script> <template> <h1>{{ title }}</h1> <ul @click="$emit('click-ul', $event, 1)"> <li @click="clickItem(item, $event)" v-for="item in data" :key=""> {{ }} </li> </ul> </template> <style lang="less" scoped></style>
src
Belowtype
Declared in the folderinterface
Interface file
// src/type/ export interface IDataItem { name: string; id: number; }
2. InUse custom components in
<!-- src/ --> <script setup lang="ts"> import { ref, reactive, onMounted, onBeforeMount } from "vue"; import CustomList from "./components/"; import type { IDataItem } from "./type/customlist"; // Declare a data and pass it to the custom component CustomListconst data = reactive([] as Array<IDataItem>); const customListRef = ref<HTMLElement | null>(null); // Click the item of the custom component, execute the custom component to throw the macro definition event and receive the parameters it carries overconst clickItem = function (item: string, e: Event) { ("clickItem...", item, e); }; // Click the event directly thrown in the temple of the custom component and receive the parameters it carriesconst clickUl = function (e: Event, value: number) { ("clickUl...", e, value); }; onBeforeMount(() => { const list: Array<IDataItem> = [ { name: "aaa", id: 1, }, { name: "bbb", id: 2, }, ]; (...list); }); onMounted(() => { ("onMounted...", ); }); </script> <template> <div class="content"> <!-- Using custom componentsCustomList --> <CustomList @click-ul="clickUl" @click-item="clickItem" :data="data" ref="customListRef" /> </div> </template> <style scoped lang="less"> .content { width: 100vw; height: 100vh; display: flex; flex-direction: column; color: var(--colorTextNormal); padding: 50px; } </style>
1. Component registration
Component registration:/guide/components/
1. Global registration
existUsed in
('MyComponent', MyComponent)
Register a component globally and can be used anywhere in the app.
shortcoming:
Cannot be automatically removed during production packaging (also called
tree-shaking
) Even if it is not actually used, it will still appear after packagingJS
in the file.The dependency relationship is not obvious, it is difficult to locate if there is a problem, and it is difficult to maintain if it is used too much.
2. Local registration
Where components are usedimport
Import
<script setup> import ComponentA from './' </script> <template> <ComponentA /> </template>
3、Summarize: Do not use global registration unless necessary
2. Attributes
The parent component controls the child component's final display status by passing different attribute data to the child component.
1. Define a props
passdefineProps
Macro defines an attribute
const props = defineProps(['title']) ()
2. Add a type to props and give the default value
Props/emit declaration for types
defineProps<IProps>()
Can giveprops
Set type,IProps
forprops
typeAnnotate the props type for the component
withDefaults
The second parameter of is supported forprops
Set the default valueThe default props value when using type declaration
import type { IDataItem } from "../type/customlist"; // IProps cannot be imported directly from the outside, there will be an error at present, and may be supported in the future (someone mentioned the issue)export interface IProps { title?: string; data: Array<IDataItem>; } const props = withDefaults(defineProps<IProps>(), { title: "CustomList", });
3. Props read-only, not modified
In the componentprops
They are all read-only and cannot be modified.One-way data flow
<script setup lang="ts"> import { onMounted } from "vue"; // Declare some properties, pass values to the parent component, and set default values to the partconst props = withDefaults(defineProps<IProps>(), { title: "CustomList", }); onMounted(() => { // ❎ Can't do this, one-way data stream props cannot be modified = "Changed the title of CustomList" }); </script>
III. Events
The child component throws internal events and passes parameters for use by the parent component.
1. Use $emit in template to directly throw an event
In the template expression of the component, you can use it directly$emit
The method triggers a custom event and throws relevant parameters.$emit('throwed event name', parameter one, parameter two that needs to be passed to the parent component...)
. You can use the event name to throw it.camelCase
andkebab-case
Form (suggestedkebab-case
)。
<!-- MyComponent --> <button @click="$emit('someEvent', $event, 1)">click me</button>
2. defineEmits() macro declares the event to be triggered
exist<template>
Used in$emit
Methods cannot be in the component<script setup>
Used in part, it means that you cannot process this event first and then throw it.defineEmits()
The macro statement that the event to be triggered can solve this problem:
Declare the triggered event
<script> // Throw an event for use by the parent componentconst emit = defineEmits<{ // (e: "Topped event name", thrown parameter one, parameter two...) (e: "callback", $event: Event): void; }>(); const callback = function (e: Event) { emit("callback", e); }; </script> <template> <button @click="callback($event, 111)">click me</button> </template>
3. Use components and listen for events and parameters thrown by subcomponents
<script> import MyComponent from "./components/"; const callback = function (e: Event, value) { ("callback...", e, value); } </script> <template> <MyComponent @some-event="callback" /> </template>
4. Slot
Custom content can be inserted into the specified parts inside the custom component to make the component more flexible.
1. Anonymous slots
Insert into components<slot>
Tags are not specifiedname
There is only one attribute by default, and you can add a default value to the slot. When the parent component does not pass the value when using the component, the default content will be displayed, and the default content will be replaced by the passing value.
<!-- Subcomponents SubmitButton --> <button type="submit"> <slot>Here is the default content text</slot> </button> <!-- use SubmitButton (No value passed) ,The button is displayed internally【Here is the default content text】--> <SubmitButton /> <!-- use SubmitButton (Pass the value) ,The button is displayed internally【Save】--> <SubmitButton>Save</SubmitButton>
2. Named slots
Insert into components<slot>
Add one when taggingname
Attributes, differentiate between different slots, and there can be multiple.
<slot name="header"></slot>
3. Named scope slots
It feels like the named slot is the same thing, which can be brought from the subcomponent and can only be used in the specified slot.
<!-- Subcomponents MyComponent --> <template> <slot name="header" message="hello header"></slot> <slot message="hello default"></slot> <slot name="footer" message="hello footer"></slot> </template> <!-- Parent component --> <!-- headerProps, defaultProps, footerProps is an object ,Return to correspond slot superior { property: property值 } Data in form --> <MyComponent> <template #header="headerProps"> {{ }} </template> <template #default="defaultProps"> {{ }} </template> <template #footer="footerProps"> {{ }} </template> <!-- Deconstruct the value 🌰 --> <template #footer="{ message }"> {{ message }} </template> </MyComponent>
5. Please note when packaging a component
1. Component coding specifications
use
PascalCase
The component name of the form improves the readability of the template and facilitates the distinction.vue component
and nativeHTML DOM
Component name format-
Naming the event can be used
camelCase
andkebab-case
(short horizontal hyphen) form, used when usingkebab-case
(short horizontal hyphen) form, usecamelCase
There are not many advantages, the recommendation is closerHTML
ofkebab-case
Writing style.Notes on DOM template analysis
Pass the details of the prop
2. Reusability
- The internal style of the component can be overwritten, so don't write it as much as possible, and provide parameters to modify it.
- The internal page display of components is more flexible, providing slots in the right places, making the layout within components controllable and more flexible
Summarize
This is the article about the custom components of vue3 learning notes. For more related content of vue3 custom components, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!