1. Development environment of the project

Development dependencies:

"dependencies": {
   "axios": "^ 0.21.1"."babel-plugin-transform-remove-console": "^ 6.9.4"."core-js": "^ 3.6.5." "."echarts": "^ 5.1.2." "."element-ui": "^ 2.4.5"."moment": "^ 2.29.1"."nprogress": "^ 0.2.0." "."quill": "^ 1.3.6." "."vue": "^ 2.6.11." "."vue-quill-editor": "^ 3.0.6"."vue-router": "^ 3.2.0"."vue-table-with-tree-grid": "^ 0.2.4." "."vuex": "^ 3.4.0"
 },
Copy the code

Element-ui is installed globally

Vue add element- UI // Enter in terminalCopy the code



You can see here that let’s choose to import all or import on demand, at this point we choose import on demandImport on demand \

Then select zh-cn and you can see that there is a plugins folder with an element.js file and an import in main.js. However, if we look closely, we can see that babel.config.js is also injected with relevant content.Copy the code

Element-ui —-> Form Form

<template>
  <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
    <el-form-item label="Activity Name" prop="name">
      <el-input v-model="ruleForm.name"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm('ruleForm')">Immediately create</el-button>
      <el-button @click="resetForm('ruleForm')">reset</el-button>
    </el-form-item>
  </el-form>
</template>
<script>
export default {
  data() {
    return {
      ruleForm: {
        name: ' '
      },
      rules: {
        name: [{required: true.message: 'Please enter an activity name'.trigger: 'blur' },
          { min: 3.max: 5.message: 'Between 3 and 5 characters long'.trigger: 'blur'}]}}},methods: {
    submitForm(formName) {
      this.$refs[formName].validate((valid) = > {
        if (valid) {
          // Verify successful execution of this code block
          alert('submit! ')}else {
          // Validate failed to execute this code block
          console.log('error submit!! ')
          return false}})},resetForm(formName) {
     // Reset the form
      this.$refs[formName].resetFields()
    }
  }
}
</script>
Copy the code

RuleForm: input Bidirectional binding data rules: verification rule of the form prop: field name to be verified

Element-ui —-> Cascader cascading selector

<el-cascader v-model="value" :options="options" @change="handleChange"></el-cascader>
Copy the code

Options: An optional data source. The key name can be configured using the Props property

Props:

Click /hover default ‘click’ checkStrictly: whether parent nodes are strictly observed not to associate with each other value: specifies the value of the option as an attribute value of the option object label: Children: Specifies that the children of the option are an attribute value of the option object

Element-ui —-> Pagination

<el-pagination 
  @size-change="handleSizeChange" 
  @current-change="handleCurrentChange"
  :current-page="currentPage4" 
  :page-sizes="[100, 200, 300, 400]." " 
  :page-size="100" layout="total, sizes, prev, pager, next, jumper" 
  :total="400">
</el-pagination>
Copy the code

Page-change and current-change: events to handle page size and current page changes page-sizes: Accepts an array of integer elements that are displayed as options for selecting the number of displays per page. [100, 200, 300, 400] represents four options for displaying 100, 200, 300, or 400 data per page. Total: indicates the total number of displays

2. Implement the login interface

When the user clicks the login button, the user will make a data request, and save the token after successful login to the sessionStorage of the client, and then jump to the route. At the same time, the token is carried in axios request interceptor. Finally, the global front-guard of the route is used to read the stored in sessionStorage to determine whether there is a value, if there is a value to jump, otherwise return to the login page.

Click event for the login button

 submitForm(formName) {
   this.$refs[formName].validate((valid) = > {
     if(! valid)return
     this.$http.post('login'.this.ruleForm).then(res= > {
       console.log(res.data)
       if(res.data.meta.status ! = =200) return this.$message.error('Login failed! ')
       this.$message.success('Login successful')
       // 1. Save the token in the sessionStorage of the client
       // There are other API interfaces in the 1.1 project, which must be accessed after login
       // 1.2 Token should only take effect while the current site is open, so save token in sessionStorage
       window.sessionStorage.setItem('token', res.data.data.token)
       // 2. Use the programmatic navigation to go to the background home page. The route address is /home
       this.$router.push('/home')})})},})Copy the code

Request interceptor

  axios.interceptors.request.use((config) = > {
    // This config contains tokens
    config.headers.Authorization = window.sessionStorage.getItem('token') | |' '
    return config
})
Copy the code

Global front guard

  router.beforeEach((to, from, next) = > {
    // to Specifies the path to be accessed
    // from indicates the path from which to jump
    // next is a function that permits
    // next() permits next('/login') forces a jump
    
    if (to.path === '/login') return next()
    / / access token
    const tokenStr = window.sessionStorage.getItem('token')
    if(! tokenStr)return next('/login')
    next()
  })
Copy the code

3. The layout of the entire page is based on the Container layout Container in the common component of Element-UI

<el-container>
  <el-header>Header</el-header>  / / to the head
  <el-container>
    <el-aside width="200px">Aside</el-aside>
    <el-main>Main</el-main>
  </el-container>
</el-container>
Copy the code

4. Project —-> Optimization

4.1. To add a progress bar to the project, use nProgress

NPM install nprogress -s // nprogress has two methods: start() done()Copy the code

Configuration:

  1.Start by importing nProgress inside the wrapped AXIOSimport NProgress from 'nprogress'
  2.Add nprogress.start () to the request interceptor// What time does it start
  3.Add nprogress.done () to the response interceptor// When will it be finished
Copy the code

4.2. Modify warnings and errors during packaging

4.3 Unpacking console.log(unpacking console.log() during the release phase)

To automatically remove console.log(), use babel-plugin-transform-remove-console.

NPM install babel-plugin-transform-remove-console -dCopy the code

Configuration: In babel.config.js, configure the following

   const proPlugins = []
   if (process.env.NODE_ENV === 'production') {
     proPlugins.push('transform-remove-console')}module.exports = {
     presets: [
       '@vue/cli-plugin-babel/preset'].plugins: [
       ...proPlugins   // Expand the array]}Copy the code

4.4. Complete multiple entry for packaging, separating the entry for development and release stages

Create a main-dev.js file and a main-prod.js file. Copy the contents of main.js to these two files and configure the following contents in vue.config.js:

  module.exports = {
      chainWebpack: config= > {
          // Publish mode
         config.when(process.env.NODE_ENV === 'production'.config= > {
            // entry Finds the default packing entry. Clear deletes the default packing entry
            // add adds a new packing entry
            config.entry('app').clear().add('./src/main-prod.js')})// Development mode
        config.when(process.env.NODE_ENV === 'development'.config= > {
        config.entry('app').clear().add('./src/main-dev.js')}}}Copy the code

4.5. Replace references to local files with CDN loads

First add the following to the publishing mode configured above in vue.config.js

  config.when(process.env.NODE_ENV === 'production'.config= > {
    config.entry('app').clear().add('./src/main-prod.js')

    config.set('externals', {
      vue: 'Vue'.'vue-router': 'VueRouter'.axios: 'axios'.echarts: 'echarts'.nprogress: 'NProgress'.moment: 'moment'.lodash: '_'.quill: 'quill'
    })
    // html-webpack-plugin assigns index to isProd
    config.plugin('html').tap(args= > {
      args[0].isProd = true
      return args
    })
  })
Copy the code

Add the CDN to the index. HTML file in the public directory as follows:

The < %if(htmlWebpackPlugin.options.isProd) { %>  // Determine if it is a development phase, if it is, replace it with the contents of {}
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.2.0/vue-router.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.core.min.js"></script><! -- moment --><script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/moment.min.js"></script><! -- elementUI --><script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.2/index.min.js"></script>< link href = "https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.2/theme-chalk/index.min.css" rel = "stylesheet" > < link Href = "https://cdn.bootcdn.net/ajax/libs/quill/1.3.6/quill.snow.min.css" rel = "stylesheet" > < %} % >Copy the code

4.6. Enable GZIP compression

Configure the following information in vue.config.js:

   const CompressionWebpackPlugin = require('compression-webpack-plugin')
   const productionGzipExtensions = ['js'.'css']
   
   configureWebpack: {
       plugins: [
         // configure compression-webpack-plugin compression
         new CompressionWebpackPlugin({
           algorithm: 'gzip'.test: new RegExp('\ \. (' + productionGzipExtensions.join('|') + '$'),
           threshold: 10240.minRatio: 0.8})]Copy the code

4.7. Enable lazy route loading

   {
     path: 'welcome'.component: () = > import('.. /views/Welcome.vue')},Copy the code