Dynamic components
This is the 15th day of my participation in the August Text Challenge.More challenges in August
Dynamic components
What if we need to do v-if frequently on a page to determine what components need to be rendered
If there are too many conditions, the template logic can be cumbersome, and VUE provides dynamic components to simplify operations
Dynamic components use component components, implemented with a special attribute is
The passing and listening events on a dynamic component are exactly the same as on a normal component
<template>
<div>
<button
v-for="tab in tabs"
:key="tab"
:class="{ active: activeTab === tab }"
@click="changeTab(tab)"
>
{{ tab }}
</button>
<! The value of dynamic component is the component name that needs to be displayed (which is the registered component name) -->
<component :is="activeTab" />
</div>
</template>
<script>
import About from './components/About.vue'
import Home from './components/Home.vue'
import Category from './components/Category.vue'
export default {
name: 'App'.components: {
About,
Home,
Category
},
data: () = > ({
tabs: [
'Home'.'About'.'Category'].activeTab: 'Home'
}),
methods: {
changeTab(v) {
this.activeTab = v
}
}
}
</script>
<style scoped>
.active {
color: red;
}
</style>
Copy the code
keep-alive
By default, when we switch components, the old components are destroyed and re-created when we come back
However, there are situations in development where we want to keep the state of the component rather than destroy it
At this point we can use a built-in component: keep-alive
<keep-alive>
<! When a component is switched, the old component will be cached.
<component :is="activeTab" />
</keep-alive>
Copy the code
But when we do this, all components will be cached, and sometimes we only want some components to be cached
In this case, you can set an attribute to keep-alive
attribute | The values | instructions |
---|---|---|
include | String or RegExp or Array | Only components with matching names are cached If multiple components are represented by string, they are separated by commas |
exclude | String or RegExp or Array | Any component with a matching name will not be cached If the value of exclude conflicts with that of include, exclude takes higher precedence If multiple components are represented by string, they are separated by commas |
max | The number or string | How many component instances can be cached, and once this number is reached, Instances in the cache component that have not been accessed recently are destroyed |
Note: It is important to note whether you use string or RegExp or Array
Instead of taking the name of the component, the value is taken from the name property in the component
<! -- Use commas between components when using strings -->
<keep-alive include="Home,Category">
<component :is="activeTab" />
</keep-alive>
Copy the code
<! -- use regex -->
<keep-alive :include="/Home|Category/">
<component :is="activeTab" />
</keep-alive>
Copy the code
<! -- Use array -->
<keep-alive :include="['Home', 'Category']">
<component :is="activeTab" />
</keep-alive>
Copy the code
Asynchronous components
By default, during the process of building the entire component tree, webPack packs these component modules together at package time, since components are directly dependent on each other through modularity
At this point, as the project gets bigger and bigger, the size of the app.js file will get bigger and bigger, which will slow down the rendering speed of the first screen
So, for components that don’t need immediate use, we can separate them into smaller chunks of chunk.js
To do this, we are given a function in Vue :defineAsyncComponent
DefineAsyncComponent accepts two types of arguments:
Type 1: a factory function that returns a Promise object
<template>
<div>
<Home />
<About />
</div>
</template>
<script>
import { defineAsyncComponent } from 'vue'
// Asynchronously load components directly from script so that they can be registered in components
// defineAsyncComponent returns the result we need to use
const Home = defineAsyncComponent(() = > import('./components/Home.vue'))
const About = defineAsyncComponent(() = > import('./components/About.vue'))
export default {
name: 'App'.components: {
Home,
About
}
}
</script>
Copy the code
Type 2: Accepts an object type and configures asynchronous functions
const Home = defineAsyncComponent({
// The default component to display
loader: () = > import('./components/Home.vue'),
// The component is displayed when the component has not been loaded
loadingComponent: Loader,
// The component is displayed when the component load error occurs
errorComponent: Error.// After 2s delay, loadingComponent is displayed
delay: 2000.// In ms if the component has not been downloaded within the time specified in timeout
// Whether an error is reported or not, it is considered a failure
// The default is Infinity
timeout: 0
})
Copy the code
In the real world, however, you might not need to configure as many attributes, so Vue provides a built-in component for that
Suspense is a built-in global component that has two slots
- Default: Displays the content of default if it can be displayed
- Fallback: If default cannot be displayed, the contents of the Fallback slot will be displayed
<suspense>
<template #default>
<About />
</template>
<! -- If the contents in the default slot cannot be displayed, the contents in the fallback slot cannot be displayed -->
<template #fallback>
<Home />
</template>
</suspense>
Copy the code
$refs
In some cases, we can bind the element or component to a ref attribute if we want to retrieve the element object or subcomponent instance directly, but we do not recommend DOM manipulation directly in Vue development
$refs is an Object that stores all DOM elements and component instances registered with ref attributes
<! Register the corresponding component in refs
<About ref="about" />
Copy the code
/ / value
mounted() {
console.log(this.$refs.title) // The native element gets the DOM object
console.log(this.$refs.about) // The component gets the component instance object (proxy object)
console.log(this.$refs.about.$el) // If you want to get the component's DOM object, you need to get its property $el
}
Copy the code
$parent
and$root
attribute | instructions |
---|---|
$parent |
The parent component element of the current component |
$root |
The root component element generally refers to the App component |
Note: the $children attribute has been removed from Vue3, so it is no longer usable
The component of v – model
We can use v-Model to do bidirectional binding in input, which now encapsulates a component that is used elsewhere, but also supports V-Model on components, similar to the.sync operator in VUe2
The parent component
<template>
<div>
<Home v-model="msg" />
<! -- This is equivalent to -->
<! -- So the child is actually passed modelValue, not MSG -->
<Home :model-value="msg" @update:modelValue="msg = $event" />
<! -- update:modelValue is the updated value in a special event subcomponent of the VUE that is passed directly as an event parameter -->
<h2>{{ msg }}</h2>
</div>
</template>
<script>
import Home from './components/Home.vue'
export default {
name: 'App'.components: {
Home
},
data() {
return {
msg: '123'}}}</script>
Copy the code
Child components
<template>
<div>
<input type="text" v-model="message">
</div>
</template>
<script>
export default {
name: 'Home'.props: {
// The actual value passed in is modelValue, not MSG
modelValue: String
},
emits: ['update:modelValue'].computed: {
message: {
get() {
return this.modelValue
},
set(v) {
this.$emit('update:modelValue', v)
}
}
}
}
</script>
Copy the code
But in fact we might need multiple properties on a component that need to be bidirectionally bound,
At this point, v-Model cannot be used alone, and the property names passed cannot all be called ModelValues
So in practice, you can usually manually set the name of the props variable that you want to pass to the child component
The parent component
<template>
<div>
<! -- Use MSG instead of default modelValue -->
<! V-model <Home V-model :foo="foo" V-model :bar="bar" /> -->
<Home v-model:msg="msg" />
<h2>{{ msg }}</h2>
</div>
</template>
<script>
import Home from './components/Home.vue'
export default {
name: 'App'.components: {
Home
},
data() {
return {
msg: '123'}}}</script>
Copy the code
Child components
<template>
<div>
<input type="text" v-model="message">
</div>
</template>
<script>
export default {
name: 'Home'.props: {
msg: String
},
emits: ['update:msg'].computed: {
message: {
get() {
return this.msg
},
set(v) {
this.$emit('update:msg', v)
}
}
}
}
</script>
Copy the code
The life cycle
Each component may go through a series of processes from creation, mounting, updating, unmounting, and so on
At some point in the process, you might want to add some code logic of your own
Vue provides us with the component’s lifecycle functions for this purpose
Life cycle function
Lifecycle functions are hook functions that are called back at some point from within the Vue source code
By calling back to the lifecycle function, we can tell what stage the component is currently going through
Then we can write our own logical code in this lifecycle
The life cycle of the cache component
For cached components, we do not execute created or Mounted lifecycle functions on re-entry
But sometimes we do want to monitor when we re-enter a component and when we leave it
The lifecycle hook functions activated and deactivated can be used to listen
activated() {
// This can play a similar role to created in caching components, called when the keep-alive cached component is activated
// The created method executes with activated on the first load.
// On the second entry, only the activated function is executed
console.log('activated')},deactivated() {
// This can play a similar role in the cache component to unmounted, when the keep-alive cache component is disabled
// Deactivated is executed when the component is removed
// Deactivated and unmounted are both executed when a component is destroyed.
console.log('deactivated')}Copy the code
So in the cache component, we can use the activated and deactivated functions instead of the Created and unmouted functions