文章将自动保存至草稿箱
    一、 区别vue-cli和webpack
    vue-cli是什么:vue-cli是vue的命令行工具,只要按照官网敲几行命令就可以新建一个基本的vue项目框架。方便快捷。
    vue-cli和webpack是什么关系:vue-cli 里面包含了webpack, 并且配置好了基本的webpack打包规则,

    二、 使用vue-cli创建项目
    1. 检查 node nvm vue-cli是否已经安装
    mac nvm安装博客推荐:https://blog.csdn.net/longgege001/article/details/114067242
    如若没有,安装命令为:cnpm install -g vue-cli 全局安装vue-cli

    2.本地新建项目文件夹,初始化 vue init webpack create-cli(文件名)
    image.png
    3.等待安装完成
    image.png
    4.创建完成之后的文件内容

    image.png
    三、项目搭建完毕提前封装一些公共的方法方便后续开发;main.js引入;封装api;路由懒加载;路由首位➕拦截器;封装公共方法;

    1. // main.js
    2. import Vue from 'vue'
    3. import App from './App'
    4. import router from './router'
    5. import ElementUI from 'element-ui'
    6. import 'element-ui/lib/theme-chalk/index.css'
    7. import Mock from './mock'
    8. import axios from './axios'
    9. import './assets/css/custom.css'
    10. import 'font-awesome/css/font-awesome.min.css'
    11. import MyPlugin from './assets/js/plugin'
    12. Vue.use(ElementUI)
    13. Vue.use(MyPlugin)
    14. Vue.config.productionTip = false
    15. if (process.env.NODE_ENV === 'development') {
    16. Mock.bootstrap()
    17. }
    18. /* eslint-disable no-new */
    19. var vm = new Vue({
    20. el: '#app',
    21. router,
    22. template: '<App/>',
    23. components: { App }
    24. })
    25. export default vm
    1. axios封装api及使用
    2. const axios = window.axios
    3. const apis: APIS = {
    4. insetRhbt: {
    5. url: '/mbs/add/web/bsc/rhbtList/insetRhbt',
    6. method: post
    7. },
    8. doValid: {
    9. url: '/mbs/add/web/bsc/rhbtList/doValid',
    10. method: get
    11. }
    12. }
    13. export async function insetRhbt (data) {
    14. return axios({
    15. url: apis.insetRhbt.url,
    16. method: apis.insetRhbt.method,
    17. data
    18. })
    19. }
    20. export async function doValid (params) {
    21. return axios({
    22. url: apis.doValid.url + '/' + `${params.rhbtFilNo}`,
    23. method: apis.doValid.method
    24. })
    25. }
    26. //引入
    27. import {doValid,insetRhbt} from '@/apis/recover'
    28. // 项目内使用
    29. const data = {
    30. rhbtFilNo: this.formData1.psnNo
    31. }
    32. const res = await doValid(data)
    1. // 路由懒加载
    2. import Vue from 'vue'
    3. import VueRouter from 'vue-router'
    4. Vue.use(VueRouter)
    5. const routes = [
    6. {
    7. path: '/demo',
    8. name: 'Demo',
    9. meta: {
    10. title: 'demo'
    11. },
    12. component: () => import('@/views/demo/index.vue') // 文件路径
    13. },
    14. ]
    15. // 路由守卫
    16. import router from '@/router'
    17. import whiteList from '@/router/whiteList'
    18. import { getToken } from '@/utils/auth'
    19. import { Route } from 'vue-router'
    20. router.beforeEach(async (to: Route, from: Route, next: any) => {
    21. // 校验是否在白名单之内
    22. // if (whiteList.includes(to.path)) {
    23. // next()
    24. // } else {
    25. // 查看是否有token
    26. // const token: string = getToken()
    27. // if (!token) {
    28. // next('/login', true)
    29. // } else {
    30. next()
    31. // }
    32. // }
    33. })
    34. router.afterEach((to: Route) => {
    35. document.title = to.meta.title
    36. })
    1. // 请求拦截器
    2. import Vue, { PluginObject } from 'vue'
    3. import axios, { AxiosResponse } from 'axios'
    4. import { Message } from 'element-ui'
    5. function errorCreate (msg:any, flag = true) {
    6. const error = new Error(msg)
    7. // 获取页面所有已经存在的message
    8. const dom = document.getElementsByClassName('el-message')
    9. // 设置值控制显示当前message
    10. // 遍历获取到的message DOM集合
    11. for (let i = 0; i < dom.length; i++) {
    12. // 如果页面已存在的message中有显示文本和当前message相同的情况,flag设置为false
    13. if (error.message === dom[i].getElementsByClassName('el-message__content')[0].innerHTML) {
    14. flag = false
    15. }
    16. }
    17. if (dom.length === 0 || flag) {
    18. Message({
    19. showClose: true,
    20. message: error.message,
    21. type: 'error',
    22. duration: 3 * 1000
    23. })
    24. }
    25. throw error
    26. }
    27. const config = {
    28. // baseURL: process.env.baseURL || process.env.apiUrl || '/api',
    29. timeout: 60 * 1000 // 请求超时
    30. // withCredentials: true, // Check cross-site Access-Control
    31. }
    32. const _axios = axios.create(config)
    33. // 请求拦截
    34. _axios.interceptors.request.use(
    35. (cfg: any) => {
    36. // try {
    37. // if (!whiteList.includes(cfg.url)) {
    38. // const token = getToken()
    39. // if (!token) {
    40. // router.replace('/login')
    41. // } else {
    42. // // cfg.headers.Authorization = `Bearer ${token}`
    43. // }
    44. // }
    45. // } catch (e) {
    46. // }
    47. return cfg
    48. },
    49. (err: Error) => {
    50. // Do something with request error
    51. return Promise.reject(err)
    52. }
    53. )
    54. // 响应拦截
    55. _axios.interceptors.response.use(
    56. async (res: AxiosResponse<any>) => {
    57. // dataAxios 是 axios 返回数据中的 data
    58. const dataAxios = res.data
    59. // 这个状态码是和后端约定的
    60. const { code } = dataAxios
    61. // 根据 code 进行判断
    62. // 有 code 代表这是一个后端接口 可以进行进一步的判断
    63. switch (code) {
    64. case '0':
    65. return dataAxios
    66. case 0:
    67. return dataAxios
    68. default:
    69. // 不是正确的 code
    70. if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
    71. return dataAxios
    72. } else {
    73. errorCreate(dataAxios.message)
    74. }
    75. break
    76. }
    77. },
    78. async (error: any) => {
    79. if (error && error.response) {
    80. switch (error.response.status) {
    81. case 400: error.message = '请求错误'; break
    82. case 401: error.message = '未授权,请登录'; break
    83. case 403: error.message = '拒绝访问'; break
    84. case 404: error.message = `请求地址出错: ${error.response.config.url}`; break
    85. case 408: error.message = '请求超时'; break
    86. case 500: error.message = '服务器内部错误'; break
    87. case 501: error.message = '服务未实现'; break
    88. case 502: error.message = '网关错误'; break
    89. case 503: error.message = '服务不可用'; break
    90. case 504: error.message = '网关超时'; break
    91. case 505: error.message = 'HTTP版本不受支持'; break
    92. default: break
    93. }
    94. }
    95. errorCreate(error)
    96. return Promise.reject(error)
    97. }
    98. )
    99. const Plugin: PluginObject<any> = {
    100. install: (Vue) => {
    101. Vue.$axios = _axios
    102. }
    103. }
    104. Plugin.install = (Vue) => {
    105. Vue.$axios = _axios
    106. window.axios = _axios
    107. Object.defineProperties(Vue.prototype, {
    108. $axios: {
    109. get () {
    110. return _axios
    111. }
    112. }
    113. })
    114. }
    115. Vue.use(Plugin)
    116. export default Plugin

    utils封装的公共方法

    1. /**
    2. * 防抖函数
    3. * @param handler 处理函数
    4. * @param wait 等待时间 number
    5. */
    6. export default function (handler, wait) {
    7. let timer: number
    8. return () => {
    9. if (timer) clearTimeout(timer)
    10. timer = setTimeout(handler, wait)
    11. }
    12. }
    1. // 格式化时间
    2. /**
    3. *
    4. *格式化日期
    5. * @param {Date|Number|String}time 传入的时间
    6. * @param {String}format 日期格式,如‘yyyy-mm-dd hh:mm:ss’等
    7. * @returns {string} 返回格式化之后的字符串
    8. */
    9. export function dateFormat (time = new Date(), format = 'yyyy-MM-dd hh:mm:ss') {
    10. if (typeof time === 'number' || typeof time === 'string') {
    11. time = new Date(+time)
    12. } else if (!(time instanceof Date)) {
    13. throw new Error('第一个参数必须是Number或者Date类型')
    14. }
    1. // localstorage文件
    2. const localStorage = window.localStorage
    3. /**
    4. * 设置或者更新Localstorage
    5. * @param {String}name 需要设置的属性名称
    6. * @param {any}item 需要设置的属性值
    7. */
    8. export function setItem (name, item) {
    9. if (!name) throw new Error('name属性是必须的')
    10. if (!item) throw new Error('item属性是必须的')
    11. localStorage.setItem(name, JSON.stringify(item))
    12. }
    13. /**
    14. * 从localstorage中获取值
    15. * @param {String}name 名称
    16. * @returns {null|any} 返回对应值,如果没有则返回null
    17. */
    18. export function getItem (name) {
    19. if (!name) throw new Error('name属性是必须的')
    20. const item = localStorage.getItem(name)
    21. if (item === 'undefined') return null
    22. return JSON.parse(item as any)
    23. }
    24. /**
    25. * 删除指定localstorage
    26. * @param {string}name storage名称
    27. */
    28. export function rmItem (name) {
    29. if (!name) throw new Error('name属性是必须的')
    30. localStorage.removeItem(name)
    31. }
    32. /**
    33. * 移除所有的localstorage
    34. */
    35. export function clearAllItem () {
    36. localStorage.clear()
    37. }

    四、各个文件夹下边的内容文字详细解释:

    1. node_modules

    用来存放包管理工具下载的包的文件夹,当我们将项目拷贝给别人的时候,传输速度会很慢,所以传输项目一般不传输node_modules文件夹,可以根据package.json文件记录的信息通过执行npm install 下载当前依赖的第三方模块,生成node_modules文件夹

    1. src文件夹包含整个项目中所有需要包含的代码(脚手架生成的webpack配置项,只对src目录进行编译处理,其他目录是不处理的)

    api 在开发项目时一般都是在src下创建一个文件夹api在里面对axios进行二次封装,组件化创建文件对应的页面在对应的文件下发请求,方便管理;
    assets 放静态资源的比如:css文件,图片文件
    components 主要存放自定义的一些组件文件
    plugins 主要放配置文件,常用的放element.js
    utils里面放公共方法
    router 里面包含index.js文件,配置路由规则和挂载
    views 项目自带的页面级组件
    App.vue 当前页面的主要入口
    main.js 项目入口(单页面一个入口,多页面多个入口)
    3.editorconfig 格式化的配置
    4.eslintrc.js 自己手动更改了一些规则,避免报错
    5.babel.config.js 将高级语法转化为浏览器可以识别的低级语法
    6.package-lock.json 记录本地下载依赖的版本
    7.package.json项目描述文件,记录了当前项目信息,例如项目名称,版本,作者,GitHub地址;使用npm init -y 命令生成package.json
    8.README.md 一些基本npm指令,可以修改
    [

    ](https://blog.csdn.net/qq_45331969/article/details/110956989)