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.

Componentization and modularization thinking have been indispensable in the development process of our big front end. Frequent introduction and registration are needed when we package the components ourselves. When more and more components and modules are added, long-term maintenance and frequent changes need a lot of energy. This is the time to take advantage of WebPack’s tree-shaking and automated code to achieve a more convenient and flexible component registration solution while keeping performance in mind. Nonsense not much to say, directly on the source code: like words point a small hand

Let’s start with the basics

The component registration

Component name

When registering a component, we always need to give it a name. For example, in global registration we have seen:

const app = Vue.createApp({... }) app.component('my-component-name', { /* ... * /})Copy the code

The component name is the first parameter in app.component.ponent, and in the example above, the component name is “my-component-name.”

The name of the component may depend on where you plan to use it. When using a component directly in the DOM (rather than in a string template or single-file component), we strongly recommend following the W3C specification for naming custom tags:

  1. All lowercase
  2. Contains a hyphen (and: that is, more than one word is connected to a hyphen)

This will help us avoid conflicts with current and future HTML elements.

You can find additional suggestions for component names in the style guide.

#Component name case

When defining a component in a string template or a single-file component, there are two ways to define the component name:

#Use the kebab – case

app.component('my-component-name', {
  /* ... */
})
Copy the code

When defining a component using kebab-case (dash delimited naming), you must also use kebab-case when referencing the custom element, such as

.

#Using PascalCase

app.component('MyComponentName', {
  /* ... */
})
Copy the code

When defining a component using PascalCase, you can use either nomenclature when referring to the custom element.

and

are both acceptable. Note, however, that only kebab-case is valid when used directly in the DOM (that is, a template that is not a string).

Automated registration

-src

–components

—CommonComponents

—-autpModules

—index.js

Start by matching the underlying component file with require’s context method

Const requireComponent = require.context(// relative path of its component directory ".. / components ", / / if true, query its directory / / based component matching filename of the regular expression / / / V [a-z] \ w + \. (vue | js) $/ / \. (vue) $/, / / configuration is asynchronous loading "sync");Copy the code

The requirecomponent.keys ().foreach method is then used to retrieve all public components in the Components folder

Requirecomponent.keys ().foreach ((fileName) => {const componentConfig = requireComponent(fileName); }); });Copy the code

The component object and associated configuration are then obtained through conditional judgment

There are two conditions for judging here, and either one can be satisfied:

  1. Reads whether automatic registration is enabled in the component configuration
  2. Files that meet the verification conditions in the default automatic registration folder
if (componentConfig.default.isAutoRegister || (componentConfig.default.__file.indexOf(dirpath) ! = -1 && new RegExp(/\.(vue|js)$/).test(componentConfig.default.__file)) ) { ... }Copy the code

Gets the PascalCase name of the component

const componentName = upperFirst()
Copy the code

Gets a file name independent of directory depth

CamelCase (/ / access and depth has nothing to do with the name of the file fileName. The split ("/"). The pop (). The replace (/ \ \ w + $/, ""))Copy the code

Global Registry component

If the component option is exported via Export Default,

.default is preferred,

Otherwise, fall back to using the root of the module.

Vue.component(
            componentName,
            componentConfig.default || componentConfig
          );
Copy the code

Main.js automatic plug-in registration module

// main.js const setUseModule = (moduleName) => {if (moduleName. Constructor === Object) {// For (let key in moduleName) { if (Object.hasOwnProperty.call(moduleName, key)) { let element = moduleName[key]; app.use(element); } } } else { app.use(moduleName); }};Copy the code

Then register in main.js

// main.js import component from "./component-expand"; . setUseModule(component);Copy the code

And then the source code

<template> <div id="KayCard"> <el-card class="box-card" :body-style="bodyStyle" :style="cardStyle"> <slot></slot> </el-card> </div> </template> <script> import { reactive, toRefs, onBeforeMount, onMounted, getCurrentInstance, } from "vue"; Export default {// isAutoRegister: true, // Whether to enable automatic component registration (global); FitVuexModuleName: 'KayCard', fitVuexModuleName: 'KayCard', fitVuexModuleName: 'KayCard', fitVuexModuleName: "KayCard", Components: {}, props: {bodyStyle: {// Padding: '20px'} Type: Object, default: () => { return {}; },}, cardStyle: {// custom card body style {padding: '20px'} type: Object, default: () => {return {}; {},}}, the setup (). The console log (" 1 - began to create components - the setup "); const thisVue = getCurrentInstance().proxy; Const data = reactive({// define reactive data}); Const methods = {// define methods}; Const conputeds = {// define computed attributes}; onBeforeMount(() => { console.log("2. Component mount page before executing ----onBeforeMount", thisVue); }); OnMounted (() = > {the console. The log (" 3. - the components mounted to the page after execution -- -- -- -- -- -- -- onMounted "); }); return { ... toRefs(data), ... methods, ... conputeds, }; }}; </script> <style scoped lang="scss"> #KayCard { .box-card:hover { --el-box-shadow-light: 0 10px 12px 5px rgba(0, 0, 0, 0.1); } } </style>Copy the code
// components/index.js // Export const autoRegisterDirectory = the directory that automatically registers components for this autoRegisterDirectory configuration ["/CommonComponents/autoModules"];Copy the code
// component-expand.js import upperFirst from "lodash/upperFirst"; import camelCase from "lodash/camelCase"; import { autoRegisterDirectory } from ".. /components"; Export default {install(Vue) {const requireComponent = require.context(//) export default {install(Vue) {const requireComponent = require.context The relative path of its component directory ".. / components ", / / if true, query its directory / / based component matching filename of the regular expression / / / V [a-z] \ w + \. (vue | js) $/ / \. (vue) $/, / / configuration is asynchronous loading "sync"); Requirecomponent.keys ().foreach ((fileName) => {const componentConfig = requireComponent(fileName); autoRegisterDirectory.forEach((dirpath) => { if ( componentConfig.default.isAutoRegister || (componentConfig.default.__file.indexOf(dirpath) ! && new RegExp = - 1 / \. (vue | js) $/). The test (componentConfig. Default. __file))) {/ / components for PascalCase named const the componentName = UpperFirst (camelCase(// get filename.split ("/").pop().replace(/\.\w+$/, ""))); Vue.componentname (componentName, // If the componentoption is exported by 'export default', // then '. Default 'is preferred, // otherwise, the module is reverted to the root. componentConfig.default || componentConfig ); }}); }); }};Copy the code