Make writing a habit together! This is my first day to participate in the “Gold Digging Day New Plan · April More text challenge”, click to see the details of the activity.
If we can use the following tips in the development of VUE project at ordinary times, we may achieve twice the result with half the effort
The template-render function can be simplified
Sometimes there is a multi-value judgment in the template of a project, and if the business logic is written according to the code below, the code is redundant and messy.
<template>
<div>
<h1 v-if="level === 1">
<slot></slot>
</h1>
<h2 v-else-if="level === 2">
<slot></slot>
</h2>
<h3 v-else-if="level === 3">
<slot></slot>
</h3>
<h4 v-else-if="level === 4">
<slot></slot>
</h4>
<h5 v-else-if="level === 5">
<slot></slot>
</h5>
<h6 v-else-if="level === 6">
<slot></slot>
</h6>
</div>
</template>
<script>
export default {
data() {
return {}
},
props: {
level: {
type: Number,
required: true,
},
},
}
</script>
Copy the code
Now rewrite the above example using the render function:
<script> export default { props: { level: { require: true, type: Number, } }, render(createElement) { return createElement('h' + this.level, this.$slots.default); }}; </script>Copy the code
Flexible component registration
Before using a component, import it and then register it:
import BaseButton from './baseButton'
import BaseIcon from './baseIcon'
import BaseInput from './baseInput'
export default {
components: {
BaseButton,
BaseIcon,
BaseInput
}
}
Copy the code
BaseButton, BaseIcon, and BaseInput can now be used in templates:
<BaseInput
v-model="searchText"
@keydown.enter="search"
/>
<BaseButton @click="search">
<BaseIcon name="search"/>
</BaseButton>
Copy the code
However, if there are many components and you have to import each component you want to use every time, and then register the component, it will add a lot of code. In this case, we need to use webpack’s require.context() method to create our own (module) context. This method takes three parameters: the folder directory to search, whether its subdirectories should also be searched, and a regular expression to match the files. We’ll start by adding a file called global.js to the Components folder (which contains high-frequency components) and using require.context to dynamically package all high-frequency components we need. Then import the global.js file in the main.js file.
import Vue from 'vue' function changeStr (str) { return str.charAt(0).toUpperCase() + str.slice(1) } const requireComponent = require.context('./', false, /\.vue$/) // Find components that end in vue in the same directory const install = () => {requireComponent.keys().foreach (fileName => {let config = RequireComponent (fileName) console.log(config) //./child1.vue let componentName = changeStr( fileName.replace(/^\.\//, '').replace(/\.\w+$/, '') ) Vue.component(componentName, Config. The default | | config)})} export default {install / / exposed outside the install method} / / the main js import index the from './components/global.js' Vue.use(index)Copy the code
As a result, we can use these high-frequency components anywhere and anytime on the page without having to manually import them one by one.
Hidden big trick — hook
Sometimes during development we will create a timer that will be destroyed before the component is destroyed. The code is as follows:
Mounted () {/ / this create a timer. The timer = setInterval () = > {/ /... }, 500); }, // Destroy the timer. beforeDestroy() { if (this.timer) { clearInterval(this.timer); this.timer = null; }}Copy the code
There is an obvious drawback to this: the timer is created and cleaned in different places, so it’s easy to forget to clean! We can hook the code so that it is easier to maintain:
mounted() { let timer = setInterval(() => { // ...... }, 500); this.$once("hook:beforeDestroy", function() { if (timer) { clearInterval(timer); timer = null; }}); }Copy the code
$on(‘ hook:updated ‘, () => {}) In addition to the above application, hook can also listen to the component’s life cycle function externally. In some cases, we need to know in the parent when a child component is created, mounted, or updated. For example, if you want to listen for a third-party component CustomSelect’s updated hook when rendering, you can do so with @hook:updated:
<template> <! Listen to the component's updated hook function --> <! <custom-select @hook:updated="doSomething" /> </template> <script> import CustomSelect from ".. /components/custom-select"; export default { components: { CustomSelect }, methods: {doSomething() {console.log("custom-select component's updated hook function is triggered "); }}}; </script>Copy the code
Simple and violent router key
When we were developing a project, we might encounter a problem like this: when the page switches to the same route but with different parameter addresses, for example, /detail/1, and goes to /detail/2, the data is not updated after the page jumps? The route configuration is as follows:
{
path: "/detail/:id",
name:"detail",
component: Detail
}
Copy the code
This is because vue-Router recognizes that the two routes use the same component for reuse and does not recreate the component, and the component’s lifecycle hooks are not triggered, resulting in no data updates after the jump. So how do we solve this problem? We can add a property key to the router-view component as shown in the following example:
<router-view :key="$route.fullpath"></router-view>
Copy the code
This method mainly uses the virtual DOM to compare whether two nodes are the same by key during rendering. If the key is not the same, the router-View component will be judged as a new node, so the component will be destroyed first, and then a new component will be created, so that the life cycle within the component will be triggered again.
Dynamic instruction parameter
One of the coolest features of Vue is the ability to dynamically pass instruction parameters to components. We can use a JavaScript expression enclosed in square brackets as an argument to an instruction:
<a v-bind:[attributeName]="url"> This is a link </a>Copy the code
The attributeName is evaluated dynamically as a JavaScript expression, and the resulting value is used as the final parameter. Similarly, you can bind handlers to a dynamic event name with dynamic parameters:
<a V-on :[eventName]="doSomething">Copy the code
Let’s take a look at an example: Suppose you have a button that in some cases wants to listen for click events and in some cases for double-click events. This is where the dynamic command argument comes in handy:
<template>
<div>
<aButton @[someEvent]="handleSomeEvent()" />
</div>
</template>
<script>
export default {
data () {
return {
someEvent: someCondition ? "click" : "dbclick"
}
},
methods: {
handleSomeEvent () {
// handle some event
}
}
}
</script>
Copy the code