vue項(xiàng)目工程化撬呢,大大提升開發(fā)效率和開發(fā)體驗(yàn)

前言

(大神繞路)vue create project-name創(chuàng)建的項(xiàng)目吝梅,基本上滿足開發(fā)使用的需求虱疏。但是,在開發(fā)過程中苏携,會發(fā)現(xiàn)一些問題:

  • eslint+prettier檢查發(fā)現(xiàn)的錯(cuò)誤做瞪,沒辦法保存代碼時(shí)自動(dòng)修復(fù),或者兩者格式化存在沖突兜叨,比如格式化代碼后穿扳,eslint發(fā)現(xiàn)的錯(cuò)誤消除了衩侥,但是prettier依然提示代碼格式不對国旷;
  • 使用公共組件時(shí),都需要在業(yè)務(wù)組件內(nèi)單獨(dú)引入一次茫死;
  • 多人協(xié)同開發(fā)時(shí)跪但,git提交日志信息格式不統(tǒng)一,雜亂無章峦萎;

等等基本優(yōu)化都可以在接下來的說明中屡久,一一解決,讓你在開發(fā)中爱榔,如魚得水被环,輕松自在。

一详幽、代碼格式化代碼筛欢,樣式格式化

1.安裝eslint相關(guān)依賴 (如果vue create時(shí)選擇了eslint+prettier浸锨,可以跳過步驟1和步驟3 的依賴安裝)

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

如果需要校驗(yàn)的代碼包含typescript,需要安裝

 npm i -D typescript

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

 node_modules/.bin/eslint --init

3.安裝prettier相關(guān)依賴

 npm i -D prettier eslint-plugin-prettier

4.在.eslintrc.js中關(guān)聯(lián)prettier版姑,相關(guān)屬性增加內(nèi)容

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

5.創(chuàng)建prettier的配置文件柱搜,項(xiàng)目根目錄新建prettier.config.js,規(guī)則根據(jù)自己的需要設(shè)置

//prettier.config.js
module.exports = {
  // 單行最大長度
  printWidth: 100,
  // 設(shè)置編輯器每一個(gè)水平縮進(jìn)的空格數(shù)
  tabWidth: 2,
  // 在句尾添加分號
  semi: true,
  // 使用單引號
  singleQuote: true,
  jsxSingleQuote: true,
  // 在任何可能的多行中輸入尾逗號剥险。
  trailingComma: 'all',
  // 在對象字面量聲明所使用的的花括號后({)和前(})輸出空格
  bracketSpacing: true,
  // 在多行JSX元素最后一行的末尾添加 > 而使 > 單獨(dú)一行(不適用于自閉和元素)
  jsxBracketSameLinte: false,
  // 為單行箭頭函數(shù)的參數(shù)添加圓括號聪蘸。
  alwaysParens: 'always',
  // 行結(jié)束
  endOfLine: 'lf',
};

6.結(jié)合webpack設(shè)置保存時(shí)自動(dòng)格式化,僅對vue的src目錄生效

  • 安裝eslint-loader依賴
npm i -D eslint-loader
  • 在vue.config.js(項(xiàng)目沒有的話表制,在根目錄自行創(chuàng)建)中增加代碼
module.exports = {
  chainWebpack: (config) => {
    config.module
      .rule('eslint')
      .use('eslint-loader')
      .loader('eslint-loader')
      .tap((options) => {
        options.fix = true
        return options
      })
  },
}

7.非vue項(xiàng)目/src目錄下文件的格式校驗(yàn)健爬,需要結(jié)合vscode編輯器功能配置,根目錄創(chuàng)建文件 .vscode/settings.json

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

8.如果需要讓樣式代碼也格式化么介,可以執(zhí)行以下操作:可以統(tǒng)一整理樣式代碼的順序

??8.1.安裝依賴

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

??8.2.項(xiàng)目根目錄創(chuàng)建stylelint配置文件.stylelintrc

//.stylelintrc
{
    "extends": "stylelint-config-standard",
    "plugins": [
       "stylelint-order"
    ],
    "rules": {
        "order/order": [
            "declarations",
            "custom-properties",
            "dollar-variables",
            "rules",
            "at-rules"
        ],
        // 規(guī)定樣式順序
        "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
  }
}

二浑劳、規(guī)范git提交

1.安裝依賴

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

2.根?錄創(chuàng)建 .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.根目錄創(chuàng)建 .lintstagedrc

{
    "*.{js, vue, css}": [
      "eslint --fix",
      "git add"
    ]  //git commit前校驗(yàn)并糾正eslint語法問題,然后再add
}

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

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

4.根目錄創(chuàng)建git commit提交說明內(nèi)容格式限制配置文件commitlint.config.js

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
        2,
        'always',
        [
        'feat', // 新功能(feature)
        'fix', // 修補(bǔ)bug
        'docs', // 文檔(documentation)
        'style', // 格式(不影響代碼運(yùn)行的變動(dòng))
        'refactor', // 重構(gòu)(即不是新增功能夭拌,也不是修改bug的代碼變動(dòng))
        'test', // 增加測試
        'revert', // 回滾
        'config', // 構(gòu)建過程或輔助工具的變動(dòng)
        'chore', // 其他改動(dòng)
        ],
    ],
    //rule由name和配置數(shù)組組成魔熏,
    //如:'name:[0, 'always', 72]',
    //數(shù)組中第一位為level鸽扁,可選0,1,2蒜绽,0為disable,1為warning桶现,2為error躲雅,
    //第二位為應(yīng)用與否,可選always | never骡和,
    //第三位該rule的值相赁。
    'type-empty': [2, 'never'], //提交類型是否允許為空
    'subject-empty': [2, 'never'], //提交說明內(nèi)容是否允許為空
  }
}

到這里,項(xiàng)目在提交時(shí)就會校驗(yàn)提交說明內(nèi)容是否符合標(biāo)準(zhǔn)慰于。

接下來再記錄如何通過終端交互規(guī)范commit內(nèi)容的配置

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圖標(biāo):svg-icon

1.安裝svg-sprite-loader:

npm i -D svg-sprite-loader

2.vue.config.js中,覆蓋原有項(xiàng)目對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.創(chuàng)建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.創(chuàng)建引入組件和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);

以下是我本地項(xiàng)目svg-icon組件相關(guān)的文件夾結(jié)構(gòu)

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绵脯,安裝時(shí)我選擇less,安裝后自動(dòng)創(chuàng)建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"), //需要引入的文件路徑列表休里,可以設(shè)置模糊匹配
        path.resolve(__dirname, "./src/styles/variable.less"), //可以設(shè)置全局變量
      ]
    }
  }
};

五蛆挫、axios

1.安裝依賴(已安裝的進(jìn)入下一步)

npm i axios

2.創(chuàng)建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.創(chuàng)建接口響應(yīng)處理方法/src/utils/http/handle.js

export const successCode = '1000'

// 根據(jù)自己接口返回的實(shí)際情況,轉(zhuǎn)換屬性名妙黍,假設(shè)接口返回的狀態(tài)屬性是returnCode悴侵,消息屬性是message
export const key = {
  code: 'returnCode',
  msg: 'message'
}

export const handles = {
  'error:0001': (err) => {
    console.log(err[key.msg] || '系統(tǒng)異常')
  },
  errorTips: (err) => {
    console.log(err[key.msg] || '系統(tǒng)異常')
  }
}

4.創(chuàng)建文件/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/'
// 默認(rèn)超時(shí)時(shí)間
axios.defaults.timeout = 15000
// 數(shù)據(jù)接口域名統(tǒng)一配置.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 請求方法,發(fā)送數(shù)據(jù)格式 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 請求方法拭嫁,發(fā)送數(shù)據(jù)格式 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.創(chuàng)建某個(gè)業(yè)務(wù)模塊對應(yīng)的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文件中的調(diào)用

import { userinfo } from '@/utils/http/services/public.js'

userinfo()
    .then((data) => {
        console.log(data)
    })
    .catch(() => {})

六可免、mock數(shù)據(jù)

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.創(chuàng)建mock入口文件/src/mock/index.js

const Mock = require('mockjs') //mockjs 導(dǎo)入依賴模塊
const util = require('./util') //自定義工具模塊
//返回一個(gè)函數(shù)
module.exports = function(app) {
  //監(jiān)聽http請求
  app.get('/user/userinfo', function(rep, res) {
    //每次響應(yīng)請求時(shí)讀取mock data的json文件
    //util.getJsonFile方法定義了如何讀取json文件并解析成數(shù)據(jù)對象
    var json = util.getJsonFile(
      './jsons/userinfo.json'
    )
    //將json傳入 Mock.mock 方法中筒繁,生成的數(shù)據(jù)返回給瀏覽器
    res.json(Mock.mock(json))
  })
}

5.創(chuàng)建mock方法 /src/mock/util.js

const fs = require('fs') //引入文件系統(tǒng)模塊
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.創(chuàng)建模擬接口返回?cái)?shù)據(jù)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.運(yùn)行npm run serve:mock,發(fā)現(xiàn)可以獲取到mock數(shù)據(jù)

七巴元、vuex

1.安裝依賴(已安裝的進(jìn)入下一步)

npm i vuex

2.創(chuàng)建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毡咏,有利于管理維護(hù),創(chuàng)建模塊/src/store/modules/root.js

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

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

5.如果需要緩存數(shù)據(jù)逮刨,可以結(jié)合sessionStorage或者localStorage對數(shù)據(jù)進(jìn)行本地緩存呕缭,可以做一下操作:

  • 創(chuàng)建緩存方法
// /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的命名空間修己,區(qū)分同域名不同項(xiàng)目的緩存
    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.創(chuàng)建文件 /src/filters/index.js

import Vue from 'vue'

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

2.main.js導(dǎo)入 /src/filters/index.js

九睬愤、路由router

個(gè)人建議片仿,路由邏輯和路由配置分開編寫

1.安裝依賴(已安裝的進(jìn)入下一步)

npm i vue-router

2.創(chuàng)建路由邏輯文件 /src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes.js'

Vue.use(VueRouter)

// 解決跳轉(zhuǎn)相同路由報(bào)錯(cuò)的問題
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.創(chuàng)建路由配置文件 /src/router/routes.js

export const routes = [
  {
    path: '/',
    name: 'Home',
    component: () =>
      import(
        // webpackChunkName后面的值表示按不同模塊打包,按需加載尤辱,訪問到對應(yīng)的路由才開始加載對應(yīng)的js
        /* webpackChunkName: "home" */ '../views/Home.vue'
      )
  },
  {
    path: '/about',
    name: 'About',
    component: () =>
      import(
        // webpackChunkName后面的值表示按不同模塊打包砂豌,按需加載,訪問到對應(yīng)的路由才開始加載對應(yīng)的js
        /* webpackChunkName: "about" */ '../views/About.vue'
      )
  }
]

十光督、全局批量注冊組件

1.創(chuàng)建公共組件示例阳距,如/src/components/global/AppTest.vue

<!-- 說明內(nèi)容 -->
<!-- @author XXX -->
<script>
export default {
  name: 'AppTest'
}
</script>

<template>
  <section class="AppTest">
    App Test Component
  </section>
</template>

<style scoped lang="less">
.AppTest {
}
</style>

2.創(chuàng)建批量注冊的入口文件/src/components/index.js

import Vue from 'vue'

const requireComponent = require.context(
  // 其組件目錄的相對路徑
  './global/',
  // 是否查詢其子目錄
  false,
  // 匹配基礎(chǔ)組件文件名的正則表達(dá)式
  /\.(vue|js)$/
)

requireComponent.keys().forEach((fileName) => {
  // 獲取組件配置
  const componentConfig = requireComponent(
    fileName
  )

  // 如果這個(gè)組件選項(xiàng)是通過 `export default` 導(dǎo)出的,
  // 那么就會優(yōu)先使用 `.default`结借,
  // 否則回退到使用模塊的根筐摘。
  const ctrl =
    componentConfig.default || componentConfig

  // 全局注冊組件
  Vue.component(ctrl.name, ctrl)
})

3.main.js引入入口文件

import '@/components/index.js'

4.這樣就可以在全局直接使用公共組件了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市船老,隨后出現(xiàn)的幾起案子咖熟,更是在濱河造成了極大的恐慌,老刑警劉巖柳畔,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馍管,死亡現(xiàn)場離奇詭異,居然都是意外死亡荸镊,警方通過查閱死者的電腦和手機(jī)咽斧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門堪置,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躬存,“玉大人,你說我怎么就攤上這事舀锨×胫蓿” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵坎匿,是天一觀的道長盾剩。 經(jīng)常有香客問我雷激,道長,這世上最難降的妖魔是什么告私? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任屎暇,我火速辦了婚禮,結(jié)果婚禮上驻粟,老公的妹妹穿的比我還像新娘根悼。我一直安慰自己,他們只是感情好蜀撑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布挤巡。 她就那樣靜靜地躺著,像睡著了一般酷麦。 火紅的嫁衣襯著肌膚如雪矿卑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天沃饶,我揣著相機(jī)與錄音母廷,去河邊找鬼。 笑死糊肤,一個(gè)胖子當(dāng)著我的面吹牛徘意,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播轩褐,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼椎咧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了把介?” 一聲冷哼從身側(cè)響起勤讽,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拗踢,沒想到半個(gè)月后脚牍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巢墅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年诸狭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片君纫。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驯遇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蓄髓,到底是詐尸還是另有隱情叉庐,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布会喝,位于F島的核電站陡叠,受9級特大地震影響玩郊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枉阵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一译红、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兴溜,春花似錦临庇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至斋攀,卻和暖如春已卷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背淳蔼。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工侧蘸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹉梨。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓讳癌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親存皂。 傳聞我的和親對象是個(gè)殘疾皇子晌坤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360