Vue.js Development Techniques and Best Practices
Automated Component Registration with Webpack
Leveraging webpack's require.context enables automatic registration of Vue components without manual imports. This approach streamlines the component registration process in main.js:
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
const componentModules = require.context(
'./components',
false,
/Base[A-Z]\w+\.(vue|js)$/)
componentModules.keys().forEach(filePath => {
const moduleConfig = componentModules(filePath)
const componentName = upperFirst(
camelCase(
filePath
.split('/')
.pop()
.replace(/\.\w+$/, '')
)
)
Vue.component(
componentName,
moduleConfig.default || moduleConfig
)
})
The require.context method accepts three parameters: target directory, subdirectory scanning flag, and filename matching regex.
Inheritance Properties and Event Listeners
$attrs Property
When passing numerous properties from parent to child components, $attrs captures undefined props values:
// Parent component
<home title="Page Title" width="80" height="80" imgUrl="image-source"/>
// Child component
mounted() {
console.log(this.$attrs) // {title: "Page Title", width: "80", height: "80", imgUrl: "image-source"}
}
Props explicitly defined in the child component are automatically excluded from $attrs.
$listeners Property
For invoking parent methods from child components, $listeners provides access to parent events:
// Parent component
<home @change="handleChange"/>
// Child component
mounted() {
console.log(this.$listeners) // Contains handleChange event
}
Dynamic Component Management
Implementing tab interfaces requiers dynamic component loading:
<component :is="activeComponent"></component>
Performance optimization through component caching:
<keep-alive>
<component :is="activeComponent"></component>
</keep-alive>
Adding transition effects:
<transition>
<keep-alive>
<component :is="activeComponent"></component>
</keep-alive>
</transition>
Component Extension Mechanism
Creating component constructors for element mounting:
const UserProfile = Vue.extend({
template: '<p>{{extendedInfo}}</br>Data passed: {{receivedProps}}</p>',
data() {
return {
extendedInfo: 'Extended component data',
}
},
props: ['receivedProps']
})
// Mount instance with property data
new UserProfile({
propsData: { receivedProps: 'Instance data' }
}).$mount('#target-element')
// Register as global component
Vue.component('UserProfile', UserProfile)
Asset URL Transformation
Simplified asset handling replaces explicit require statements:
<!-- Before -->
<template>
<div>
<avatar :img-src="avatarSource"></avatar>
</div>
</template>
<script>
export default {
created() {
this.avatarSource = require('./assets/default-avatar.png')
}
}
</script>
<!-- After -->
<template>
<div>
<avatar img-src="./assets/default-avatar.png"></avatar>
</div>
</template>
Configuration for vue-cli 3.x:
module.exports = {
chainWebpack: config => {
config
.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.transformAssetUrls = {
avatar: 'img-src',
}
return options;
});
}
}
Path Alias Configuration
vue-cli 2.x Setup
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
}
vue-cli 3.x Setup
const path = require('path')
function resolvePath(dir) {
return path.join(__dirname, dir)
}
module.exports = {
chainWebpack: config => {
config.resolve.alias
.set('alias-key', resolvePath('src/components'))
}
}
Image Error Handling
Implementing fallback images for broken sources:
<img :src="imageUrl" @error="setDefaultImage" alt="">
<script>
export default{
data(){
return{
imageUrl:''
}
},
methods:{
setDefaultImage(event){
event.target.src = require('@/assets/default-image.png')
}
}
}
</script>