Summarize the overall framework of the current vue project in combination with the company's project

Posted by mbh23 on Sat, 29 Jan 2022 03:10:42 +0100

1. Ecological use around the framework

  • Frame limited to vue2 x
  • At present, the company's R & D and delivery of medium-sized and large-scale projects, so vuex and Vue router must be used
  • The UI is based on elementui, and the MD UI developed by the experience design department is used to eliminate elementui in subsequent development
  • The tool library uses lodash, including MD hooks of Bluebird component library

2. Scaffold

  • At present, the experience design department provides a general framework for the construction of the project framework, and the Department tools need to be customized and modified
  • Departments can build npm private servers and use Node environment to develop CLI tools in combination with the general framework to provide a set of general framework for departments
  • The developed tools can be improved according to the needs (such as: quickly create components, quickly create pages, filters, instructions, tool functions, etc.)

3. Development specifications

  • Code style, naming standard, unified directory structure
  • git submission record, multi person collaborative development specification
  • Specification of static resource usage
  • Page structure
    • According to the business needs, create corresponding page components in views according to the routing level, create them in the form of folders, and create index Vue file is used as the entry file of the page.
    • Components in the page: create the components folder under the page folder, and create the corresponding component files in it. If it is a complex component, create the component in the form of folder.
    • Tool module: a tool module that can be highly abstract. js files should be created in @ / lib.

4. Style

  • At present, according to the project framework dependency, Sass/Scss preprocessor is used in department projects

  • Local styles use scoped schemes

  • Global style definition variable SCSS file writing, multi project public style using common SCSS, the layout style uses layout scss

    • You can use these variables and common styles anywhere in the project without import ing.

    • // vue.config.js
      module.exports = {
        css: {
          loaderOptions: {
            sass: {
              prependData: `
              @import '@/styles/variable.scss';
              @import '@/styles/mixins.scss';
              `,
            },
          },
        },
      }
      
  • Use nprogress to make a pseudo progress bar for route jump to solve the problem that users know that the page is already loading under the condition of poor network

    • import NProgress from 'nprogress';
      
      router.beforeEach(() => {
        NProgress.start();
      });
      
      router.afterEach(() => {
        NProgress.done();
      });
      
  • When the page is loaded for the first time, a large amount of white screen time will be generated. According to the current delivery, R & D, demand center and other projects, it will be directly displayed in public / index Just write some static styles in HTML.

  • As for the use of 100vh, 100vh is widely used in the current project, and the viewport height of 100vh on the mobile terminal will be inconsistent with the imagination

    • 100vh !== Viewport height 100vh = = = viewport height + height of browser toolbar (address bar, etc.)

    • Install VH check NPM install VH check -- save to solve the problem

    • import vhCheck from 'vh-check';
      vhCheck('browser-address-bar');
      
      // Define css mixin
      @mixin vh($height: 100vh) {
        height: $height;
        height: calc(#{$height} - var(--browser-address-bar, 0px));
      }
      

5. Component library

  • Use MD UI for development, do not use multiple UI frameworks together, and do not introduce element UI
  • Introduce the MD UI as needed to avoid the excessive volume of css after packaging
  • The style definition of designer's design drawing is different from that of MD UI. It is overwritten by a separate style file, and local changes are modified by v-deep penetration in the component
  • Some components with large volume should not be referenced globally, but locally as much as possible to reduce the loading pressure of the first screen
  • The secondary packaging of third-party tools will be more flexible whether the tools are replaced or used for various reasons

6. Asynchronous request, encapsulating Axios

According to the previous project and other open source projects, at @ / LIBS / HTTP Axios is encapsulated under the JS path, which encapsulates the request parameters, request header, error prompt information, request interceptor, response interceptor, unified error handling, baseURL setting, etc.

import axios from 'axios';
import get from 'lodash/get';
import storage from 'store';
// Create an axios instance
const request = axios.create({
 // Default prefix for API requests
 baseURL: '/',
 timeout: 50000, // Request timeout
});

// Exception interception processor
const errorHandler = (error) => {
 const status = get(error, 'response.status');
 switch (status) {
   /* eslint-disable no-param-reassign */
   case 400: error.message = 'Request error'; break;
   case 401: error.message = 'Unauthorized, please login'; break;
   case 403: error.message = 'access denied'; break;
   case 404: error.message = `Error requesting address: ${error.response.config.url}`; break;
   case 408: error.message = 'request timeout'; break;
   case 500: error.message = 'Server internal error'; break;
   case 501: error.message = 'Service not implemented'; break;
   case 502: error.message = 'Bad Gateway '; break;
   case 503: error.message = 'Service Unavailable'; break;
   case 504: error.message = 'gateway timeout '; break;
   case 505: error.message = 'HTTP Version not supported'; break;
   default: break;
   /* eslint-disabled */
 }
 return Promise.reject(error);
};

// request interceptor
request.interceptors.request.use((config) => {
 // If the token exists
 // Let each request carry a custom token. Please modify it according to the actual situation
 // eslint-disable-next-line no-param-reassign
 config.headers.Authorization = `bearer ${storage.get('ACCESS_TOKEN')}`;
 return config;
}, errorHandler);

// response interceptor
request.interceptors.response.use((response) => {
 const dataAxios = response.data;
 // This status code is agreed with the backend
 const { code } = dataAxios;
 // Judge by code
 if (code === undefined) {
   // If there is no code, it means that this is not the interface developed by the back-end of the project
   return dataAxios;
 // eslint-disable-next-line no-else-return
 } else {
   // code indicates that this is a back-end interface, which can be further judged
   switch (code) {
     case 200:
       // [example] code === 200 means there is no error
       return dataAxios.data;
     case 'xxx':
       // [example] other code s agreed with the background
       return 'xxx';
     default:
       // Not the correct code
       return 'Not right code';
   }
 }
}, errorHandler);

export default request;
  • Our project uses cookie s to store tokens. sotre's package is used here as a local storage tool to store tokens
  • For cross domain problems, use proxy. According to previous projects, proxy is defined in config folder JS for cross domain processing during development

7.mock data

Mock data function is based on mock JS development, through webpack configuration, automatically load the mock configuration file

  • All mock configuration files should be placed in the @ / mock/services path

  • Business related folders can be established in @ / mock/services to store configuration files by category.

  • All configuration files shall be in accordance with * * * mock.js naming convention creation.

  • entrance

    • import Mock from 'mockjs';
      
      Mock.setup({
        timeout: '500-800',
      });
      
      const context = require.context('./services', true, /\.mock.js$/);
      
      context.keys().forEach((key) => {
        Object.keys(context(key)).forEach((paramKey) => {
          Mock.mock(...context(key)[paramKey]);
        });
      });
      

8. Routing

  • Layout:

    • At present, the experience design department provides three Layout components: Basic, User and Blank. There are three types: with sidebar, without sidebar and Blank

    • Combined with some open source projects, the routes of login or permission authentication can be divided. There are two kinds: FrameIn and FrameOut. One is the page that needs permission verification, and the other is the page that does not need permission verification, such as login page

    • In routing, the function of permission verification is integrated. When you need to add permissions to the page, add corresponding key s under meta:

    • auth

      • Type: Boolean. When auth is true, this page needs login permission verification. It is only valid for frameIn routing.
    • permissions

      • Type: object, permissions. Each key corresponds to the verification of permission function. When the value of the key is true, it means that you have permission. If the key is false, you can hide the corresponding DOM with the v-permission instruction
      • https://blog.csdn.net/weixin_45646663/article/details/112277206 [online blog about permissions]
import router from '@/router';
import store from '@/store';
import storage from 'store';
import util from '@/libs/utils';

// progress bar
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

const loginRoutePath = '/user/login';
const defaultRoutePath = '/home';

/**
 * Route interception
 * Permission verification
 */
router.beforeEach(async (to, from, next) => {
  // progress bar
  NProgress.start();
  // Verify whether login verification is required in all matches of the current route
  if (to.matched.some((r) => r.meta.auth)) {
    // Is there a token as a condition to verify whether to log in
    const token = storage.get('ACCESS_TOKEN');
    if (token && token !== 'undefined') {
      // Is it on the login page
      if (to.path === loginRoutePath) {
        next({ path: defaultRoutePath });
        // Query whether to save user information
      } else if (Object.keys(store.state.system.user.info).length === 0) {
        store.dispatch('system/user/getInfo').then(() => {
          next();
        });
      } else {
        next();
      }
    } else {
      // Jump to the login interface when you don't log in
      // Carry the complete path of the page to jump after successful login
      next({
        name: 'Login',
        query: {
          redirect: to.fullPath,
        },
      });
      NProgress.done();
    }
  } else {
    // Pass directly without identity verification
    next();
  }
});

router.afterEach((to) => {
  // progress bar
  NProgress.done();
  util.title(to.meta.title);
});

9. Construction optimization

  • Using the graphical interface of vue, you can view some specific conditions of interface resources

  • Open Gzip

    • chainWebpack: (config) => {
        config
          .plugin('CompressionPlugin')
          .use(CompressionPlugin, []);
      },
      
  • Route lazy loading

    • {
        path: 'home',
        name: 'Home',
        component: () => import(
          /* webpackChunkName: "home" */ '@/views/home/index.vue'
        ),
      },
      // The comment webpackChunkName must be added to make it easy to know that the page is too redundant after packaging.
      
  • Preload & prefetch optimize page opening speed

10. Unit test

  • According to the specific project, no unit test has been conducted for the project

11.Vuex

  • User information management (storing information, operating token, etc.)
  • Login (transfer interface)
  • Menu management (store routing information, generate menu, fuzzy query and other functions)
  • Full screen operation
  • Loading

12. Filter

Common filter global registration

  • Date time
  • file size

13. Directive

Global registration of common instructions

  • Component permission verification
  • focus
  • Lazy loading of pictures
  • Scroll to the specified position

14. Code base specification

  • Reduce the complexity of css selector and enhance performance [the browser reads the selector from the right to the left of the selector.]

  • Avoid wildcard selectors*

  • Without considering IE 678, try to use flexbox layout for better performance

  • Changes to the two attributes of transforms and opacity will not trigger rearrangement and redrawing. Try to use them in animation

  • When the value is a decimal between 0 and 1, it is recommended to omit the 0 of the integer part.

  • When the length is 0, it is recommended to omit the unit

  • Do not use named color values.

  • When the element needs to be raised to contain internal floating elements, clearfix is performed by setting clear on the pseudo class or triggering BFC. Try not to add empty labels.

  • In addition to the public style, it should not be used in business code as far as possible! important.

  • The z-index is layered to manage the visual hierarchical relationship of absolute positioning elements outside the document flow.

  • The font size shall not be less than 12px (PC side).

  • The font weight attribute is described numerically.

15.vue specification

  • When using the data attribute in a component (anywhere except new Vue), its value must be the function data() {return {...}} that returns an object.
  • The definition of prop should be as detailed as possible, and at least its type needs to be specified.
  • Boolean type attribute. When it is true, write the attribute value directly.
  • Do not operate on vue variables in computed.
  • Communication between parent and child components through prop and events should be given priority over this$ Parent or change prop.
  • key must always be used with v-for on components to maintain the state of internal components and their subtrees.
  • v-if and v-for cannot be used at the same time
  • Public methods should not be hung on the prototype as far as possible. They can be written in utils file or mixin file. Do not register business public components to the global.
  • Do not mount any third-party plug-ins to the vue prototype.
  • Methods with high versatility should be encapsulated in libs, global components or instruction sets.
  • Set the scope for the component style.
  • Try to use instruction abbreviations.

16.vuex specification

State is a single state tree. In state, we need to define the arrays, objects, strings, etc. that we need to manage. Only if it is defined here can we get the state of the object you define in the vue component

  • To modify the data in the state, you must go through changes.
  • Every state that may change must synchronously create one or more changes to change it.
  • The data obtained by the server is stored in the state and retained as original data and cannot be changed.

Getters is similar to Vue JS calculation attribute. When we need to derive some states from the state of the store, we need to use getters. Getters will receive state as the first parameter, and the return value of getters will be cached according to its dependency, Only when the dependency value in getters (a value in state that needs to derive state) changes will it be recalculated.

  • Use getters to process the data format you need, rather than modifying the original state data.
  • mapGetters is not mandatory in components, because you may need to use getters and setter s.
  • The only way to change the state is to submit changes.
  • The mapMutations auxiliary function is used in the component to map the methods in the component to store Commit call.
  • The naming adopts the rule of uppercase letter + underline.

Actions is used when dealing with complex data processing and asynchronous operations

  • The data interface with heavy page is invoked in actions as much as possible.
  • The data returned by the server shall not be processed as far as possible, and the original data shall be retained.
  • The obtained data must be changed to state by calling changes.

Modules is divided into modules according to the page situation, which has been done in previous projects

  • Generally, modules are divided by page
  • The default built-in system ensures the basic functions of the scaffold.
  • Add the attribute named: true to each page module or sub module of the page.

Topics: Javascript Front-end Vue