美文网首页
vue项目工程化,大大提升开发效率和开发体验

vue项目工程化,大大提升开发效率和开发体验

作者: Jimson_Shen | 来源:发表于2020-04-30 12:02 被阅读0次

    前言

    (大神绕路)vue create project-name创建的项目,基本上满足开发使用的需求。但是,在开发过程中,会发现一些问题:

    • eslint+prettier检查发现的错误,没办法保存代码时自动修复,或者两者格式化存在冲突,比如格式化代码后,eslint发现的错误消除了,但是prettier依然提示代码格式不对;
    • 使用公共组件时,都需要在业务组件内单独引入一次;
    • 多人协同开发时,git提交日志信息格式不统一,杂乱无章;

    等等基本优化都可以在接下来的说明中,一一解决,让你在开发中,如鱼得水,轻松自在。

    一、代码格式化代码,样式格式化

    1.安装eslint相关依赖 (如果vue create时选择了eslint+prettier,可以跳过步骤1和步骤3 的依赖安装)

     npm i -D eslint @vue/cli-plugin-eslint eslint-plugin-vue @typescript-eslint/eslint-plugin @typescript-eslint/parser
    

    如果需要校验的代码包含typescript,需要安装

     npm i -D typescript
    

    2.初始化生成eslint配置文件.eslintrc.js

     node_modules/.bin/eslint --init
    

    3.安装prettier相关依赖

     npm i -D prettier eslint-plugin-prettier
    

    4.在.eslintrc.js中关联prettier,相关属性增加内容

     //.eslintrc.js
    {
      "plugins": ["prettier"],
      "rules": {
        "prettier/prettier": "warn"
      }
    }
    

    5.创建prettier的配置文件,项目根目录新建prettier.config.js,规则根据自己的需要设置

    //prettier.config.js
    module.exports = {
      // 单行最大长度
      printWidth: 100,
      // 设置编辑器每一个水平缩进的空格数
      tabWidth: 2,
      // 在句尾添加分号
      semi: true,
      // 使用单引号
      singleQuote: true,
      jsxSingleQuote: true,
      // 在任何可能的多行中输入尾逗号。
      trailingComma: 'all',
      // 在对象字面量声明所使用的的花括号后({)和前(})输出空格
      bracketSpacing: true,
      // 在多行JSX元素最后一行的末尾添加 > 而使 > 单独一行(不适用于自闭和元素)
      jsxBracketSameLinte: false,
      // 为单行箭头函数的参数添加圆括号。
      alwaysParens: 'always',
      // 行结束
      endOfLine: 'lf',
    };
    

    6.结合webpack设置保存时自动格式化,仅对vue的src目录生效

    • 安装eslint-loader依赖
    npm i -D eslint-loader
    
    • 在vue.config.js(项目没有的话,在根目录自行创建)中增加代码
    module.exports = {
      chainWebpack: (config) => {
        config.module
          .rule('eslint')
          .use('eslint-loader')
          .loader('eslint-loader')
          .tap((options) => {
            options.fix = true
            return options
          })
      },
    }
    

    7.非vue项目/src目录下文件的格式校验,需要结合vscode编辑器功能配置,根目录创建文件 .vscode/settings.json

    //settings.json
    {
      "editor.formatOnSave": true
    }
    

    8.如果需要让样式代码也格式化,可以执行以下操作:可以统一整理样式代码的顺序

      8.1.安装依赖

    npm i -D stylelint stylelint-config-standard stylelint-order
    

      8.2.项目根目录创建stylelint配置文件.stylelintrc

    //.stylelintrc
    {
        "extends": "stylelint-config-standard",
        "plugins": [
           "stylelint-order"
        ],
        "rules": {
            "order/order": [
                "declarations",
                "custom-properties",
                "dollar-variables",
                "rules",
                "at-rules"
            ],
            // 规定样式顺序
            "order/properties-order": [
                "position",
                "z-index",
                "top",
                "bottom",
                "left",
                "right",
                "float",
                "clear",
                "columns",
                "columns-width",
                "columns-count",
                "column-rule",
                "column-rule-width",
                "column-rule-style",
                "column-rule-color",
                "column-fill",
                "column-span",
                "column-gap",
                "display",
                "grid",
                "grid-template-rows",
                "grid-template-columns",
                "grid-template-areas",
                "grid-auto-rows",
                "grid-auto-columns",
                "grid-auto-flow",
                "grid-column-gap",
                "grid-row-gap",
                "grid-template",
                "grid-template-rows",
                "grid-template-columns",
                "grid-template-areas",
                "grid-gap",
                "grid-row-gap",
                "grid-column-gap",
                "grid-area",
                "grid-row-start",
                "grid-row-end",
                "grid-column-start",
                "grid-column-end",
                "grid-column",
                "grid-column-start",
                "grid-column-end",
                "grid-row",
                "grid-row-start",
                "grid-row-end",
                "flex",
                "flex-grow",
                "flex-shrink",
                "flex-basis",
                "flex-flow",
                "flex-direction",
                "flex-wrap",
                "justify-content",
                "align-content",
                "align-items",
                "align-self",
                "order",
                "table-layout",
                "empty-cells",
                "caption-side",
                "border-collapse",
                "border-spacing",
                "list-style",
                "list-style-type",
                "list-style-position",
                "list-style-image",
                "ruby-align",
                "ruby-merge",
                "ruby-position",
                "box-sizing",
                "width",
                "min-width",
                "max-width",
                "height",
                "min-height",
                "max-height",
                "padding",
                "padding-top",
                "padding-right",
                "padding-bottom",
                "padding-left",
                "margin",
                "margin-top",
                "margin-right",
                "margin-bottom",
                "margin-left",
                "border",
                "border-width",
                "border-top-width",
                "border-right-width",
                "border-bottom-width",
                "border-left-width",
                "border-style",
                "border-top-style",
                "border-right-style",
                "border-bottom-style",
                "border-left-style",
                "border-color",
                "border-top-color",
                "border-right-color",
                "border-bottom-color",
                "border-left-color",
                "border-image",
                "border-image-source",
                "border-image-slice",
                "border-image-width",
                "border-image-outset",
                "border-image-repeat",
                "border-top",
                "border-top-width",
                "border-top-style",
                "border-top-color",
                "border-top",
                "border-right-width",
                "border-right-style",
                "border-right-color",
                "border-bottom",
                "border-bottom-width",
                "border-bottom-style",
                "border-bottom-color",
                "border-left",
                "border-left-width",
                "border-left-style",
                "border-left-color",
                "border-radius",
                "border-top-right-radius",
                "border-bottom-right-radius",
                "border-bottom-left-radius",
                "border-top-left-radius",
                "outline",
                "outline-width",
                "outline-color",
                "outline-style",
                "outline-offset",
                "overflow",
                "overflow-x",
                "overflow-y",
                "resize",
                "visibility",
                "font",
                "font-style",
                "font-variant",
                "font-weight",
                "font-stretch",
                "font-size",
                "font-family",
                "font-synthesis",
                "font-size-adjust",
                "font-kerning",
                "line-height",
                "text-align",
                "text-align-last",
                "vertical-align",
                "text-overflow",
                "text-justify",
                "text-transform",
                "text-indent",
                "text-emphasis",
                "text-emphasis-style",
                "text-emphasis-color",
                "text-emphasis-position",
                "text-decoration",
                "text-decoration-color",
                "text-decoration-style",
                "text-decoration-line",
                "text-underline-position",
                "text-shadow",
                "white-space",
                "overflow-wrap",
                "word-wrap",
                "word-break",
                "line-break",
                "hyphens",
                "letter-spacing",
                "word-spacing",
                "quotes",
                "tab-size",
                "orphans",
                "writing-mode",
                "text-combine-upright",
                "unicode-bidi",
                "text-orientation",
                "direction",
                "text-rendering",
                "font-feature-settings",
                "font-language-override",
                "image-rendering",
                "image-orientation",
                "image-resolution",
                "shape-image-threshold",
                "shape-outside",
                "shape-margin",
                "color",
                "background",
                "background-image",
                "background-position",
                "background-size",
                "background-repeat",
                "background-origin",
                "background-clip",
                "background-attachment",
                "background-color",
                "background-blend-mode",
                "isolation",
                "clip-path",
                "mask",
                "mask-image",
                "mask-mode",
                "mask-position",
                "mask-size",
                "mask-repeat",
                "mask-origin",
                "mask-clip",
                "mask-composite",
                "mask-type",
                "filter",
                "box-shadow",
                "opacity",
                "transform-style",
                "transform",
                "transform-box",
                "transform-origin",
                "perspective",
                "perspective-origin",
                "backface-visibility",
                "transition",
                "transition-property",
                "transition-duration",
                "transition-timing-function",
                "transition-delay",
                "animation",
                "animation-name",
                "animation-duration",
                "animation-timing-function",
                "animation-delay",
                "animation-iteration-count",
                "animation-direction",
                "animation-fill-mode",
                "animation-play-state",
                "scroll-behavior",
                "scroll-snap-type",
                "scroll-snap-destination",
                "scroll-snap-coordinate",
                "cursor",
                "touch-action",
                "caret-color",
                "ime-mode",
                "object-fit",
                "object-position",
                "content",
                "counter-reset",
                "counter-increment",
                "will-change",
                "pointer-events",
                "all",
                "page-break-before",
                "page-break-after",
                "page-break-inside",
                "widows"
            ],
            "no-empty-source": null,
            "property-no-vendor-prefix": [
                true,
                {
                    "ignoreProperties": [
                        "background-clip"
                    ]
                }
            ],
            "number-leading-zero": "never",
            "number-no-trailing-zeros": true,
            "length-zero-no-unit": true,
            "value-list-comma-space-after": "always",
            "declaration-colon-space-after": "always",
            "value-list-max-empty-lines": 0,
            "shorthand-property-no-redundant-values": true,
            "declaration-block-no-duplicate-properties": true,
            "declaration-block-no-redundant-longhand-properties": true,
            "declaration-block-semicolon-newline-after": "always",
            "block-closing-brace-newline-after": "always",
            "media-feature-colon-space-after": "always",
            "media-feature-range-operator-space-after": "always",
            "at-rule-name-space-after": "always",
            "indentation": 2,
            "no-eol-whitespace": true,
            "string-no-newline": null
        }
    }
    

      8.3.vscode编辑器下载插件stylelint

      8.4.修改 .vscode/settings.json

    //settings.json
    {
      "editor.codeActionsOnSave": {
        "source.fixAll": true
      }
    }
    

    二、规范git提交

    1.安装依赖

    npm i -D husky lint-staged @commitlint/cli @commitlint/config-conventional
    

    2.根⽬录创建 .huskyrc

    {
      "hooks": {
        "pre-commit": "lint-staged",
        "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
      }
    }
    

    等同于在package.json的如下配置:

    {
      "husky": {
        "hooks": {
          "pre-commit": "lint-staged",
          "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
        }
      }
    }
    

    3.根目录创建 .lintstagedrc

    {
        "*.{js, vue, css}": [
          "eslint --fix",
          "git add"
        ]  //git commit前校验并纠正eslint语法问题,然后再add
    }
    

    等同于在package.json的如下配置:

    {
      "lint-staged": {
        "*.{js, vue, css}": [
          "eslint --fix",
          "git add"
        ]
      }
    }
    

    4.根目录创建git commit提交说明内容格式限制配置文件commitlint.config.js

    module.exports = {
      extends: ['@commitlint/config-conventional'],
      rules: {
        'type-enum': [
            2,
            'always',
            [
            'feat', // 新功能(feature)
            'fix', // 修补bug
            'docs', // 文档(documentation)
            'style', // 格式(不影响代码运行的变动)
            'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动)
            'test', // 增加测试
            'revert', // 回滚
            'config', // 构建过程或辅助工具的变动
            'chore', // 其他改动
            ],
        ],
        //rule由name和配置数组组成,
        //如:'name:[0, 'always', 72]',
        //数组中第一位为level,可选0,1,2,0为disable,1为warning,2为error,
        //第二位为应用与否,可选always | never,
        //第三位该rule的值。
        'type-empty': [2, 'never'], //提交类型是否允许为空
        'subject-empty': [2, 'never'], //提交说明内容是否允许为空
      }
    }
    

    到这里,项目在提交时就会校验提交说明内容是否符合标准。

    接下来再记录如何通过终端交互规范commit内容的配置

    1.安装依赖:

    npm i -D commitizen conventional-changelog cz-conventional-changelog
    

    2.配置依赖路径,在 package.json 中添加配置

    { 
        //...
        "config": {
            "commitizen": {
              "path": "./node_modules/cz-conventional-changelog"
            }
        }
    }
    

    尝试在命令行中输入

    提交代码
    git add -A  
    
    暂存代码
    git-cz  
    

    三、配置svg图标:svg-icon

    1.安装svg-sprite-loader:

    npm i -D svg-sprite-loader
    

    2.vue.config.js中,覆盖原有项目对svg的处理loader:

    const path = require("path");
    
    module.exports = {
      chainWebpack: (config) => {
        config.module
          .rule("svg")
          .exclude.add(resolve("src/components/SvgIcon/svgs"))
          .end()
        
        config.module
          .rule("icon")
          .test(/\.svg$/)
          .include.add(resolve("src/components/SvgIcon/svgs")) //处理svg目录
          .end()
          .use("svg-sprite-loader")
          .loader("svg-sprite-loader")
          .options({
            symbolId: "icon-[name]",
          });
      },
    };
    
    function resolve(dir) {
      return path.join(__dirname, dir);
    }
    

    3.创建svg-icon组件

    <script>
    export default {
      name: "SvgIcon",
      props: {
        iconClass: {
          type: String,
          required: true,
        },
      },
      computed: {
        iconName() {
          return `#icon-${this.iconClass}`;
        },
      },
    };
    </script>
    
    <template>
      <svg class="SvgIcon" aria-hidden="true">
        <use :xlink:href="iconName" />
      </svg>
    </template>
    
    <style scoped lang="less">
    .SvgIcon {
      width: 1em;
      height: 1em;
      // vertical-align: -0.15em;
      fill: currentColor;
      overflow: hidden;
    }
    </style>
    

    4.创建引入组件和svg图片的index.js:

    import Vue from 'vue';
    import svgIcon from './index.vue';
    Vue.component(svgIcon.name, svgIcon);
    
    const req = require.context('@/components/SvgIcon/svgs', true, /\.svg$/);
    const requireAll = requireContext => requireContext.keys().map(name => requireContext(name));
    requireAll(req);
    

    以下是我本地项目svg-icon组件相关的文件夹结构

    src
        components
            SvgIcon
                svgs
                    testIcon.svg
                index.js
                index.vue
    

    5.main.js中引入

    import "/components/SvgIcon/index.js";
    

    6.使用示例

    <svg-icon :icon-class='svg文件名' />
    

    四、配置全局less

    1.通过vue安装style-resources-loader,安装时我选择less,安装后自动创建vue.config.js

    vue add style-resources-loader
    

    完善vue.config.js配置

    const path = require("path");
    module.exports = {
      pluginOptions: {
        "style-resources-loader": {
          preProcessor: "less",
          patterns: [
            path.resolve(__dirname, "./src/styles/reset.less"), //需要引入的文件路径列表,可以设置模糊匹配
            path.resolve(__dirname, "./src/styles/variable.less"), //可以设置全局变量
          ]
        }
      }
    };
    

    五、axios

    1.安装依赖(已安装的进入下一步)

    npm i axios
    

    2.创建api配置文件/src/utils/http/.env.default.js

    const apiBase = {
      dev: 'http://xxxx:8080',
      local: 'http://xxxx',
      stg: 'http://xxxx',
      production: 'http://xxxx'
    }
    
    export const baseUrl = apiBase[process.env.NODE_ENV || 'dev']
    

    3.创建接口响应处理方法/src/utils/http/handle.js

    export const successCode = '1000'
    
    // 根据自己接口返回的实际情况,转换属性名,假设接口返回的状态属性是returnCode,消息属性是message
    export const key = {
      code: 'returnCode',
      msg: 'message'
    }
    
    export const handles = {
      'error:0001': (err) => {
        console.log(err[key.msg] || '系统异常')
      },
      errorTips: (err) => {
        console.log(err[key.msg] || '系统异常')
      }
    }
    

    4.创建文件/src/utils/http/index.js

    import axios from 'axios'
    import { baseUrl } from './.env.default.js'
    import {
      key,
      handles,
      successCode
    } from './handle.js'
    
    // axios 配置
    const defaultBaseUrl = 'http://localhost:8080/'
    // 默认超时时间
    axios.defaults.timeout = 15000
    // 数据接口域名统一配置.env
    axios.defaults.baseURL = baseUrl || defaultBaseUrl
    axios.defaults.baseURL = ''
    
    // http request 拦截器
    axios.interceptors.request.use(
      (config) => {
        config.headers = {}
        return config
      },
      (err) => {
        return Promise.reject(err)
      }
    )
    
    // http response 拦截器
    axios.interceptors.response.use(
      (response) => {
        const data = response.data
        if (data[key.code] !== successCode) {
          const fn = handles[data[key.code]]
          if (fn) {
            fn(data)
          } else {
            handles.errorTips(data)
          }
        }
        return response
      },
      (error) => {
        const data = error.response.data
        if (data && data[key.code] !== successCode) {
          const fn = handles[data[key.code]]
          if (fn) {
            fn(data)
          } else {
            handles.errorTips(data)
          }
        }
    
        return Promise.reject(data || error)
      }
    )
    
    export default axios
    
    /**
     * get 请求方法
     * @param {*} url
     * @param {*} params
     */
    export function get(url, params = {}) {
      return new Promise((resolve, reject) => {
        axios
          .get(url, {
            params: params
          })
          .then((response) => {
            resolve(response.data)
          })
          .catch((err) => {
            reject(err)
          })
      })
    }
    
    /**
     * post 请求方法,发送数据格式 json
     * @param {*} url
     * @param {*} data
     */
    export function post(
      url,
      data = {},
      config = {
        transformRequest: [
          function(fData, headers) {
            headers['Content-Type'] =
              'application/json'
            return JSON.stringify(fData)
          }
        ]
      }
    ) {
      return new Promise((resolve, reject) => {
        axios.post(url, data, config).then(
          (response) => {
            resolve(response.data)
          },
          (err) => {
            reject(err)
          }
        )
      })
    }
    
    /**
     * patch 请求方法,发送数据格式 json
     * @param {*} url
     * @param {*} data
     */
    export function patch(url, data = {}) {
      return new Promise((resolve, reject) => {
        axios
          .patch(url, data, {
            transformRequest: [
              function(fData, headers) {
                headers['Content-Type'] =
                  'application/json'
                return JSON.stringify(fData)
              }
            ]
          })
          .then(
            (response) => {
              resolve(response.data)
            },
            (err) => {
              reject(err)
            }
          )
      })
    }
    
    export function del(url, data) {
      return new Promise((resolve, reject) => {
        axios.delete(url, { data }).then(
          (response) => {
            resolve(response.data)
          },
          (err) => {
            reject(err)
          }
        )
      })
    }
    

    5.创建某个业务模块对应的API集合文件/src/utils/http/services/public.js

    import { post, get } from '../index.js'
    
    export const list = (data = {}) =>
      post(
        '/user/info',
        data
      )
    
    export const userinfo = (data = {}) => get('/user/list', data)
    

    6.vue文件中的调用

    import { userinfo } from '@/utils/http/services/public.js'
    
    userinfo()
        .then((data) => {
            console.log(data)
        })
        .catch(() => {})
    

    六、mock数据

    1.安装依赖

    npm i -D webpack-dev-server mockjs
    

    2.改造vue.config.js

    const webpackConfig = {
      devServer: {}
    }
    
    //本地mock
    if (process.env.NODE_ENV === 'local') {
      webpackConfig.devServer.before = require('./src/mock') //引入mock/index.js
    }
    
    module.exports = webpackConfig
    

    3.package.json增加脚本

    {
        script:{
            "serve:mock": "vue-cli-service serve --mode=local --open "
        }
    }
    

    4.创建mock入口文件/src/mock/index.js

    const Mock = require('mockjs') //mockjs 导入依赖模块
    const util = require('./util') //自定义工具模块
    //返回一个函数
    module.exports = function(app) {
      //监听http请求
      app.get('/user/userinfo', function(rep, res) {
        //每次响应请求时读取mock data的json文件
        //util.getJsonFile方法定义了如何读取json文件并解析成数据对象
        var json = util.getJsonFile(
          './jsons/userinfo.json'
        )
        //将json传入 Mock.mock 方法中,生成的数据返回给浏览器
        res.json(Mock.mock(json))
      })
    }
    

    5.创建mock方法 /src/mock/util.js

    const fs = require('fs') //引入文件系统模块
    const path = require('path') //引入path模块
    
    module.exports = {
      //读取json文件
      getJsonFile: function(filePath) {
        //读取指定json文件
        var json = fs.readFileSync(
          path.resolve(__dirname, filePath),
          'utf-8'
        )
        //解析并返回
        return JSON.parse(json)
      }
    }
    

    6.创建模拟接口返回数据json /src/mock/jsons/userinfo.json

    {
      "error": 0,
      "data": {
        "userid": "@id()", 
        "username": "@cname()", 
        "date": "@date()", 
        "avatar":
          "@image('200x200','red','#fff','avatar')", 
        "description": "@paragraph()", 
        "ip": "@ip()", 
        "email": "@email()" 
      }
    }
    

    7.运行npm run serve:mock,发现可以获取到mock数据

    七、vuex

    1.安装依赖(已安装的进入下一步)

    npm i vuex
    

    2.创建vuex入口文件 /src/store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    import root from './modules/root.js'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        testState: 1
      },
      mutations: {
        changeState: (state, value) => {
          state.testState = value
        }
      },
      actions: {},
      modules: {
        root
      }
    })
    

    3.分模块配置vuex,有利于管理维护,创建模块/src/store/modules/root.js

    export default {
      state: {
        rootState: 1
      },
      mutations: {},
      actions: {},
      getters: {}
    }
    

    4.检查main.js是否引入/src/utils/tools/index.js

    5.如果需要缓存数据,可以结合sessionStorage或者localStorage对数据进行本地缓存,可以做一下操作:

    • 创建缓存方法
    // /src/utils/tools/index.js
    export const setSesStorage = (key, value) => {
      try {
        value = JSON.stringify(value)
        // eslint-disable-next-line no-empty
      } catch (error) {}
    
      sessionStorage.setItem(
        `${process.env.VUE_APP_BASE_NAME}${key}`,  //全局配置,可以用于sessionStorage的命名空间,区分同域名不同项目的缓存
        value
      )
    }
    
    export const getSesStorage = (key) => {
      let value = sessionStorage.getItem(
        `${process.env.VUE_APP_BASE_NAME}${key}`
      )
      try {
        return JSON.parse(value)
      } catch (error) {
        return value
      }
    }
    
    • 改造mutations,如在index.js中改造:
    // /src/store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import root from './modules/root.js'
    import {
      setSesStorage,
      getSesStorage
    } from '../utils/tools/index.js'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        testState: getSesStorage('testState') || ''
      },
      mutations: {
        changeState: (state, value) => {
          state.testState = value
          setSesStorage('testState', value)  // localStorage同理
        }
      },
      actions: {},
      modules: {
        root
      }
    })
    

    八、全局filter

    1.创建文件 /src/filters/index.js

    import Vue from 'vue'
    
    Vue.filter('filterSome', (value) => {
      return value || ''
    })
    

    2.main.js导入 /src/filters/index.js

    九、路由router

    个人建议,路由逻辑和路由配置分开编写

    1.安装依赖(已安装的进入下一步)

    npm i vue-router
    

    2.创建路由逻辑文件 /src/router/index.js

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import routes from './routes.js'
    
    Vue.use(VueRouter)
    
    // 解决跳转相同路由报错的问题
    const originalPath = VueRouter.prototype.push
    VueRouter.prototype.push = function push(
      location
    ) {
      return originalPath
        .call(this, location)
        .call((err) => err)
    }
    
    const router = new VueRouter({
      routes
    })
    
    export default router
    

    3.创建路由配置文件 /src/router/routes.js

    export const routes = [
      {
        path: '/',
        name: 'Home',
        component: () =>
          import(
            // webpackChunkName后面的值表示按不同模块打包,按需加载,访问到对应的路由才开始加载对应的js
            /* webpackChunkName: "home" */ '../views/Home.vue'
          )
      },
      {
        path: '/about',
        name: 'About',
        component: () =>
          import(
            // webpackChunkName后面的值表示按不同模块打包,按需加载,访问到对应的路由才开始加载对应的js
            /* webpackChunkName: "about" */ '../views/About.vue'
          )
      }
    ]
    

    十、全局批量注册组件

    1.创建公共组件示例,如/src/components/global/AppTest.vue

    <!-- 说明内容 -->
    <!-- @author XXX -->
    <script>
    export default {
      name: 'AppTest'
    }
    </script>
    
    <template>
      <section class="AppTest">
        App Test Component
      </section>
    </template>
    
    <style scoped lang="less">
    .AppTest {
    }
    </style>
    

    2.创建批量注册的入口文件/src/components/index.js

    import Vue from 'vue'
    
    const requireComponent = require.context(
      // 其组件目录的相对路径
      './global/',
      // 是否查询其子目录
      false,
      // 匹配基础组件文件名的正则表达式
      /\.(vue|js)$/
    )
    
    requireComponent.keys().forEach((fileName) => {
      // 获取组件配置
      const componentConfig = requireComponent(
        fileName
      )
    
      // 如果这个组件选项是通过 `export default` 导出的,
      // 那么就会优先使用 `.default`,
      // 否则回退到使用模块的根。
      const ctrl =
        componentConfig.default || componentConfig
    
      // 全局注册组件
      Vue.component(ctrl.name, ctrl)
    })
    

    3.main.js引入入口文件

    import '@/components/index.js'
    

    4.这样就可以在全局直接使用公共组件了

    相关文章

      网友评论

          本文标题:vue项目工程化,大大提升开发效率和开发体验

          本文链接:https://www.haomeiwen.com/subject/akrzwhtx.html