0
点赞
收藏
分享

微信扫一扫

小兔鲜儿电商项目(一) —— 项目初始化

邯唐情感 2022-04-07 阅读 142

一、创建项目

1. vue-cli 创建项目

  1. 打开控制台,输入 vue create 项目名 ,创建项目
    在这里插入图片描述

  2. 选择配置,然后回车
    在这里插入图片描述

  3. vue版本选择3
    在这里插入图片描述

  4. 路由是否使用history模式?选择 n
    如果项目中存在要求就使用history(即:y),但是一般还是推荐大家使用hash模式,毕竟history模式需要依赖运维
    在这里插入图片描述

  5. 选择一种CSS预处理类型,这个需要根据各个项目的要求使用那种css编译处理
    在这里插入图片描述

  6. eslint 风格,建议选择标准模式即可
    在这里插入图片描述

  7. 选择校验时机
    建议保存和修改时都进行检测
    在这里插入图片描述

  8. 配置文件的存放位置,一般存放在单独的文件中
    在这里插入图片描述

  9. 是否保存当前选择的配置项
    如果当前配置是经常用到的配置,建议选择y存储一下当前配置项。如果只是临时使用的话就不需要存储了
    在这里插入图片描述

  10. 等待安装完成
    在这里插入图片描述

  11. 安装完成
    在这里插入图片描述

2. 项目目录调整

2.1 初始项目目录

在这里插入图片描述

2.2 调整后的项目目录

在这里插入图片描述

2.3 vue3 中改变的文件

  1. router / index.js

    import { createRouter, createWebHashHistory } from 'vue-router'
    // 路由规则
    const routes = [
    ]
    
    // 创建路由实例
    const router = createRouter({
      // 使用hash路由模式
      history: createWebHashHistory(),
      routes
    })
    
    export default router
    
    
  2. store / index.js

    import { createStore } from 'vuex'
    
    // 创建仓库
    export default createStore({
      state: {
      },
      getters: {
      },
      mutations: {
      },
      actions: {
      },
      modules: {
      }
    })
    
  3. . main.js

    // 不再引入Vue构造函数,引入的是名为createApp的工厂函数,无需通过new调用
    import { createApp } from 'vue'
    // 引入根组件
    import App from './App.vue'
    // 引入路由实例
    import router from './router'
    // 引入仓库(vuex)实例
    import store from './store'
    // createApp(App):创建应用实例对象——app(类似于vue2中的vm,但app比vm更“轻”,即app没有vm那么多的方法属性等)
    const app = createApp(App)
    // 挂载
    app.mount('#app')
    

3. 项目配置

3.1 src文件夹简写,别名@的配置

  • 这个是针对项目进行配置的,如果vscode已经全局配置了,可以不进行配置
  • 新建 src / jsconfig.json
{
  "compilerOptions": {
      "baseUrl": "./",
          "paths": {
          "@/*": [
              "src/*"
          ]
      }
  },
  "exclude": [
      "node_modules",
      "dist"
  ]
}
  • 注意:配置后需要重启编辑器

3.2 忽略eslint校验

  • 新建 src / .eslintignore
/dist
/src/vender
  • eslint在做风格检查的时候忽略 dist 和 vender 不去检查

二、vuex 扩展

1. getters

  • vuex的计算属性,用来简化state中的数据

2. modules模块

  • 让代码更好维护,让多种数据分类更加明确
  • 组件的state、actions、mutations、getters单独管理,最后引入

2.1 默认模块

  • state 区分模块,其他 getters mutations actions 都在全局
  • 使用时直接 store.state.getters/mutations/actions.xxx 即可

2.2 开启命名空间的模块

  • 通过namespaced:true 开启命名空间

  • 所有功能区分模块,更高封装度和复用

  • 使用时要写模块名

    • 开启命名空间(namespace)后,组件中读取state数据
    // 直接读取
     $store.state.模块名.要读取的state数据
    
    • 开启命名空间后,组件中读取getters数据:
    // 直接读取
    $store.getters['模块名/要读取的getters']
    
    • 开启命名空间后,组件中调用dispatch
    // 直接dispatch
    $store.dispatch('模块名/actions方法名',数据)
    
    • 开启命名空间后,组件中调用commit
    // 直接commit
    $store.commit('模块名/xxx',数据)
    

三、vuex 持久化

  • vuex中的数据会在刷新时丢失
  • 在实际开发中,比如用户信息(名字,头像,token),需要vuex中存储且需要本地存储来实现持久化
  • 可以通过插件简化该过程,让在vuex中管理的状态数据同时存储在本地,免去自己存储的环节

1. 需要持久化存储的模块

  • 新建需要持久化存储的模块: src / store / modules下新建 cart.js 、user.js 、 category.js
  • 子模块state建议写成函数形式
  • 本项目的子模块都开启了命名空间
  1. user.js:用户模块

    /** 用户模块 */
    
    // 子模块state建议写成函数
    const state = () => {
      return {
        // 用户信息
        profile: {
          id: '',
          avatar: '',
          nickname: '',
          account: '',
          mobile: '',
          token: ''
        }
      }
    }
    const mutations = {
      // 修改用户信息,payload代表要修改的用户信息对象
      SETUSER (state, payload) {
        state.profile = payload
      }
    }
    const actions = {}
    const getters = {}
    export default {
      namespaced: true, // 开启命名空间
      state,
      mutations,
      actions,
      getters
    }
    
  2. cart.js:购物车模块

    /** 购物车模块 */
    
    const state = () => {
      return {
        // 购物车商品列表
        list: []
      }
    }
    const mutations = {}
    const actions = {}
    const getters = {}
    export default {
      namespaced: true, // 开启命名空间
      state,
      mutations,
      actions,
      getters
    }
    
    
  3. category.js :分类模块,管理所有分类

    /** 分类模块 */
    
    const state = () => {
      return {
        // 分类信息
        categoryList: []
      }
    }
    const mutations = {}
    const actions = {}
    const getters = {}
    export default {
      namespaced: true, // 开启命名空间
      state,
      mutations,
      actions,
      getters
    }
    
    
  4. store / index.js中引入

    import { createStore } from 'vuex'
    // 导入模块
    import user from './modules/user'
    import cart from './modules/cart'
    import category from './modules/category'
    
    // 创建仓库实例
    export default createStore({
      modules: {
        user,
        cart,
        category
      }
    })
    

2. vuex的状态持久化插件

  1. 安装 vuex-persistedstate
cnpm i vuex-persistedstate --save
  1. 使用vuex-persistedstate插件
import { createStore } from 'vuex'
// 引入持久化插件
import createPersistedstate from 'vuex-persistedstate'
// 导入模块
import user from './modules/user'
import cart from './modules/cart'
import category from './modules/category'

// 创建仓库实例
export default createStore({
  modules: {
    user,
    cart,
    category
  },
  // 配置插件
  plugins: [
    // 默认存储在localStorage
    createPersistedstate({
      // 本地存储的名字
      key: 'rabbit-client-pc-store',
      // 指定需要存储的模块
      paths: ['user', 'cart']
    })
  ]
})

注意:

  • 默认是存储在localStorage

  • key是存储数据的键名

  • paths是存储state中的那些数据,如果是模块下具体的数据需要加上模块名称,如user.token

  • 修改state后触发才可以看到本地存储数据的的变化

四、axios请求工具函数

  1. 安装 axios
cnpm install --save axios
  1. 新建 src / utils / request.js
/** *****************axios的二次封装,主要是封装请求拦截器和响应拦截器 ************/
/** 实现步骤
 * 1. 创建一个新的axios实例
 * 2. 请求拦截器,如果有token进行头部携带
 * 3. 响应拦截器,获取响应数据,拦截失效token
 * 4. 定义函数,使用配置好的axios发送请求
 **/

// 导入axios
import axios from 'axios'
// 导入store实例
import store from '@/store'
// 导入路由
import router from '@/router'

// 导出baseURL:一些不是axios发送的请求也会用到baseURL
export const baseURL = 'http://pcapi-xiaotuxian-front-devtest.itheima.net/'
/**
 * TODO-1: 通过 axios.create() 创建axios实例
 */
const instance = axios.create({
  // axios 的配置
  // 基础路径,`baseURL` 将自动加在 `url` 前面
  baseURL,
  // 超时时间,指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 5000
})

/**
 * TODO-2:请求拦截器
 */
instance.interceptors.request.use(config => {
  // 发送请求前要做的事情
  // config:配置对象,其中含请求头header属性

  const { profile } = store.state.user
  // 如果存在token,就在请求头携带
  if (profile.token) {
    config.headers.token = `Bearer ${profile.token}`
  }

  // 最后必须返回config配置对象
  return config
}, error => {
  // 请求失败要做的事情
  return Promise.reject(new Error(error))
})

/**
 * TODO-3:响应拦截器
 */
instance.interceptors.response.use(response => {
  // 响应成功,直接返回data数据
  return response.data
}, error => {
  // 响应失败

  // 401 未登录状态
  if (error.response && error.response.status === 401) {
    // 清空本地无效信息:通过提交修改用户信息的mutation,并且传递一个空对象实现
    store.commit('user/SETUSER', {})
    /** 跳转到登录,且传递当前路由地址给登录页面 */
    // js模块中获取当前路由信息地址:router.currentRoute.value.fullPath
    // encodeURIComponent 转换uri编码,防止解析地址出问题
    const fullPath = encodeURIComponent(router.currentRoute.value.fullPath)
    router.push(`/login?redirectUrl=${fullPath}`)
  }

  return Promise.reject(new Error(error))
})

/**
 * TODO-4:封装请求函数
 * 负责发请求,传递的参数:请求地址、请求方式、提交的数据
 */
export default (url, method, submitData) => {
  // instance 负责发请求,得到的是Promise对象,所以最后直接返回instance
  return instance({
    url,
    method,
    // 如果是get请求,需要使用params传参
    // 如果不是get请求,需要使用data进行传参
    [method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
  })
}

五、路由设计

在这里插入图片描述

路径组件(功能)嵌套级别
/首页布局容器1级
/首页2级
/category/:id一级分类2级
/category/sub/:id二级分类2级
/product/:id商品详情2级
/login登录1级
/login/callback第三方登录回调1级
/cart购物车2级
/member/checkout填写订单2级
/member/pay进行支付2级
/member/pay/result支付结果2级
/member个人中心布局容器2级
/member个人中心3级
/member/order订单管理3级
/member/order/:id订单详情3级

六、编程规范

1. 代码格式规范

通过 ESLint + Prettier + VSCode 配置 配合进行了处理。最终达到在保存代码时,自动规范化代码格式的目的

1.1 ESlint 和 Prettier 配合解决代码格式问题

  1. VSCode中安装prettier插件
  2. 新建prettier配置文件: .prettierrc
    注意:复制过去时,不能加注释!!!!
{
    // 不尾随分号
    "semi": false,
    // 使用单引号
    "singleQuote": true,
    // 多行逗号分割的语法中,最后一行不加逗号
    "trailingComma": "none"
  }
  1. 修改VSCode配置
    在这里插入图片描述
  2. 打开VSCode设置面板,不用选择或者搜索,找到如下代码,将4修改为2
    在这里插入图片描述
  3. 解决多个代码格式化工具之间的冲突
  • 在vscode中右键选择 “使用…格式化文档”,选择“prettier”
    在这里插入图片描述
    在这里插入图片描述
  1. 解决 ESLint 和 Prettier之间冲突问题
  • 打开 .eslintrc.js 在 rules 下新增 'space-before-function-paren': 'off'

2. git 提交规范

2.1 工具 —— Commitizen

约定式提交

  1. 全局安装commitizen
cnpm install -g commitizen
  1. 安装并配置 cz-customizable 插件
  • 使用 npm 下载 cz-customizable
cnpm i --save-dev  cz-customizable
  • 添加以下配置到 package.json 中
"config": {
    "commitizen": {
      "path": "node_modules/cz-customizable"
    }
  }
  • 项目根目录下创建.cz-config.js 自定义提示文件
module.exports = {
  // 可选类型
  types: [
    { value: 'feat', name: 'feat:     新功能' },
    { value: 'fix', name: 'fix:      修复' },
    { value: 'docs', name: 'docs:     文档变更' },
    { value: 'style', name: 'style:    代码格式(不影响代码运行的变动)' },
    {
      value: 'refactor',
      name: 'refactor: 重构(既不是增加feature,也不是修复bug)'
    },
    { value: 'perf', name: 'perf:     性能优化' },
    { value: 'test', name: 'test:     增加测试' },
    { value: 'chore', name: 'chore:    构建过程或辅助工具的变动' },
    { value: 'revert', name: 'revert:   回退' },
    { value: 'build', name: 'build:    打包' }
  ],
  // 消息步骤
  messages: {
    type: '请选择提交类型:',
    customScope: '请输入修改范围(可选):',
    subject: '请简要描述提交(必填):',
    body: '请输入详细描述(可选):',
    footer: '请输入要关闭的issue(可选):',
    confirmCommit: '确认使用以上信息提交?(y/n/e/h)'
  },
  // 跳过问题
  skipQuestions: ['body', 'footer'],
  // subject文字长度默认是72
  subjectLimit: 72
}
  • 使用 git cz 代替 git commit,即可看到提示内容

2.2 Git Hooks配置提交校验

2.2.1 使用 husky + commitlint 检查提交描述是否符合规范要求

  • commitlint:用于检查提交信息

  • husky:是git hooks工具

注意:npm 需要在 7.x 以上版本!!!!!

2.2.1.1 安装commitlint
  1. 安装依赖:
cnpm install --save-dev @commitlint/config-conventional @commitlint/cli
  1. 创建 commitlint.config.js 文件
  • config-conventional 默认配置点击可查看
module.exports = {
  // 继承的规则
  extends: ['@commitlint/config-conventional'],
  // 定义规则类型
  rules: {
    // type 类型定义,表示 git 提交的 type 必须在以下类型范围内
    'type-enum': [
      // 当前验证的错误级别
      2,
      // 在什么情况下验证
      'always',
      // 泛型内容
      [
        'feat', // 新功能 feature
        'fix', // 修复 bug
        'docs', // 文档注释
        'style', // 代码格式(不影响代码运行的变动)
        'refactor', // 重构(既不增加新功能,也不是修复bug)
        'perf', // 性能优化
        'test', // 增加测试
        'chore', // 构建过程或辅助工具的变动
        'revert', // 回退
        'build' // 打包
      ]
    ],
    // subject 大小写不做校验
    'subject-case': [0]
  }
}

注意:确保保存为 UTF-8 的编码格式,否则可能报错

2.2.1.2 安装husky
  1. 安装依赖:
cnpm install --save-dev husky
  1. 启动 hooks , 生成 .husky 文件夹
    控制台输入:
npx husky install
  1. package.json 中生成 prepare 指令( 需要 npm > 7.0 版本
npm set-script prepare "husky install"
  1. 执行 prepare 指令
npm run prepare
  1. 执行成功,提示
    在这里插入图片描述

  2. 添加 commitlinthookhusky中,并指定在 commit-msghooks 下执行 npx --no-install commitlint --edit "$1" 指令

  1. 此时的 .husky 的文件结构
    在这里插入图片描述

至此, 不符合规范的 commit 将不再可提交
强制规范化的提交要求,到现在 不符合规范的提交信息,将不可在被提交!

2.3 通过 pre-commit 检测提交时代码规范

  1. 执行 npx husky add .husky/pre-commit "npx eslint --ext .js,.vue src" 添加 commit 时的 hooknpx eslint --ext .js,.vue src 会在执行到该 hook 时运行)
npx husky add .husky/pre-commit "npx eslint --ext .js,.vue src"
  1. 该操作会生成对应文件 pre-commit
    在这里插入图片描述

2.4 lint-staged 自动修复格式错误

  • lint-staged 可以让你当前的代码检查 只检查本次修改更新的代码,并在出现错误的时候,自动修复并且推送

  • lint-staged 无需单独安装,我们生成项目时,vue-cli 已经帮助我们安装过了,所以我们直接使用就可以了

  1. 修改 package.json 配置

    "lint-staged": {
        "src/**/*.{js,vue}": [
          "eslint --fix",
          "git add"
        ]
      }
    
  2. 如上配置,每次它只会在你本地 commit 之前,校验你提交的内容是否符合你本地配置的 eslint规则(这个见文档 ESLint ),校验会出现两种结果:

    1. 如果符合规则:则会提交成功。
    2. 如果不符合规则:它会自动执行 eslint --fix 尝试帮你自动修复
      • 修复成功,则会帮你把修复好的代码提交
      • 如果失败,则会提示你错误,让你修好这个错误之后才能允许你提交代码。
  3. 修改 .husky/pre-commit 文件

    #!/bin/sh
    . "$(dirname "$0")/_/husky.sh"
    
    npx lint-staged
    
    
  4. 再次执行提交代码

  5. 发现 暂存区中 不符合 ESlint 的内容,被自动修复

2.5 总结

对于 git 提交规范 而言我们使用了 husky 来监测 Git hooks 钩子,并且通过以下插件完成了对应的配置:

  1. 约定式提交规范
  2. commitizen:git 提交规范化工具
  3. commitlint:用于检查提交信息
  4. pre-commitgit hooks 钩子
  5. lint-staged:只检查本次修改更新的代码,并在出现错误的时候,自动修复并且推送
举报

相关推荐

0 条评论