项目起步
创建项目
目的:使用vue-cli创建一个vue3.0项目。
第一步:打开命令行窗口。
- 注意,所在目录将会是你创建项目的目录。
第二步:执行创建项目命令行

第三步:选择自定义创建
第四步:选中vue-router,vuex,css Pre-processors选项
第五步:选择vue3.0版本
第六步:选择hash模式的路由
第七步:选择less作为预处理器
第八步:选择 standard 标准代码风格
第九步:保存代码校验代码风格,代码提交时候校验代码风格
第十步:依赖插件或者工具的配置文件分文件保存
第十一步:是否记录以上操作,选择否
第十二步:等待安装…
最后:安装完毕
目录调整
目的:对项目功能模块进行拆分。
大致步骤:
- 删除无用代码和文件
- 完善项目的基础结构
- 读懂默认生成的代码
落的代码:

注意:以上结构目录及供参考
需要注意的一些文件:
router/index.js
import { createRouter, createWebHashHistory } from 'vue-router'const routes = []// 创建路由实例const router = createRouter({// 使用hash方式实现路由history: createWebHashHistory(),// 配置路由规则,写法和之前一样routes})export default router
vue3.0中createRouter来创建路由实例,createWebHashHistory代表使用hash模式的路由。
store/index.js
import { createStore } from 'vuex'// 创建vuex仓库并导出export default createStore({state: {// 数据},mutations: {// 改数据函数},actions: {// 请求数据函数},modules: {// 分模块},getters: {// vuex的计算属性}})
vue3.0中createStore来创建vuex实例。
main.js
import { createApp } from 'vue'import App from './App.vue'import router from './router'import store from './store'// 创建一个vue应用实例createApp(App).use(store).use(router).mount('#app')
vue3.0中createApp来创建应用app。
额外增加两个配置文件:
jsconfig.json
{"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["./src/*"],}},"exclude": ["node_modules", "dist"]}
当我们使用路径别名@的时候可以提示路径。
.eslintignore
/dist/src/vender
eslint在做风格检查的时候忽略 dist 和 vender 不去检查。
基于git管理项目
- git init
- git add .
- git commit -m ‘初始化仓库’
- 创建远程仓库
- 添加远程仓库的别名 git remote add origin
https://gitee.com/wzj1031/erabbit-128.git - 推送代码 git push -u origin master
vuex-基础
目的:知道每个配置作用,根模块vue3.0的用法,带命名空间模块再vue3.0的用法
- 根模块的用法
定义
import { createStore } from 'vuex'// vue2.0 创建仓库 new Vuex.Store({})// vue3.0 创建仓库 createStore({})export default createStore({// 数据state: {info: '王浩'},// vuex的计算属性getters: {fullInfo (state) {return state.info + '😁😁😁'}},// 改数据函数mutations: {updateInfo (state, payload) {state.info = payload}},// 请求数据函数actions: {updateInfo (context, payload) {setTimeout(() => {context.commit('updateInfo', payload)}, 1000)}},// 分模块modules: {}})
使用
<template><!-- vue2.0需要根元素,vue3.0可以是代码片段 Fragment --><div><!-- 1. 使用根模块state的数据 --><div>{{ $store.state.info }}</div><!-- 2. 使用根模块getters的数据 --><div>{{ $store.getters.fullInfo }}</div><button @click="handleClick">点击</button></div></template><script>import { useStore } from 'vuex'export default {name: 'App',setup () {// 获取store对象不可以写到事件函数中const store = useStore()const handleClick = () => {// 获取store对象// 触发mutation// store.commit('updateInfo', '你好啊')// 触发actionstore.dispatch('updateInfo', 'hi')}return { handleClick }}}</script>
- modules (分模块)
- 存在两种情况
- 默认的模块,
state区分模块,其他gettersmutationsactions都在全局。 - 带命名空间
namespaced: true的模块,所有功能区分模块,更高封装度和复用。
- 默认的模块,
import { createStore } from 'vuex'const moduleA = {// 子模块state建议写成函数state: () => {return {username: '模块A'}},getters: {changeName (state) {return state.username + 'AAAAAA'}}}const moduleB = {// 带命名空间的模块namespaced: true,// 子模块state建议写成函数state: () => {return {username: '模块B'}},getters: {changeName (state) {return state.username + 'BBBBBB'}},mutations: {// 修改名字的mutationupdate (state) {state.username = 'BBBB' + state.username}},actions: {update ({ commit }) {// 假设请求setTimeout(() => {commit('update')}, 2000)}}}// 创建vuex仓库并导出export default createStore({state: {// 数据person: [{ id: 1, name: 'tom', gender: '男' },{ id: 2, name: 'lucy', gender: '女' },{ id: 3, name: 'jack', gender: '男' }]},mutations: {// 改数据函数},actions: {// 请求数据函数},modules: {// 分模块a: moduleA,b: moduleB},getters: {// vuex的计算属性boys: (state) => {return state.person.filter(p => p.gender === '男')}}})
使用:
<template><div>APP组件</div><ul><li v-for="item in $store.getters.boys" :key="item.id">{{item.name}}</li></ul><!-- 使用模块A的username --><p>A的username --- {{$store.state.a.username}}</p><p>A的changeName --- {{$store.getters.changeName}}</p><hr><p>B的username --- {{$store.state.b.username}}</p><p>B的changeName --- {{$store.getters['b/changeName']}}</p><button @click="$store.commit('b/update')">修改username</button><button @click="$store.dispatch('b/update')">异步修改username</button></template>
vuex-持久化
目的:让在vuex中管理的状态数据同时存储在本地。可免去自己存储的环节。
- 在开发的过程中,像用户信息(名字,头像,token)需要vuex中存储且需要本地存储。
- 再例如,购物车如果需要未登录状态下也支持,如果管理在vuex中页需要存储在本地。
- 我们需要category模块存储分类信息,但是分类信息不需要持久化。
1)首先:我们需要安装一个vuex的插件vuex-persistedstate来支持vuex的状态持久化。
npm i vuex-persistedstate
2)然后:在src/store 文件夹下新建 modules 文件,在 modules 下新建 user.js 和 cart.js
src/store/modules/user.js
// 用户模块export default {namespaced: true,state () {return {// 用户信息profile: {id: '',avatar: '',nickname: '',account: '',mobile: '',token: ''}}},mutations: {// 修改用户信息,payload就是用户信息对象setUser (state, payload) {state.profile = payload}}}
src/store/modules/cart.js
// 购物车状态export default {namespaced: true,state: () => {return {list: []}}}
src/store/modules/category.js
// 分类模块export default {namespaced: true,state () {return {// 分类信息集合list: []}}}
3)继续:在 src/store/index.js 中导入 user cart 模块。
import { createStore } from 'vuex'import user from './modules/user'import cart from './modules/cart'import cart from './modules/category'export default createStore({modules: {user,cart,category}})
4)最后:使用vuex-persistedstate插件来进行持久化
import { createStore } from 'vuex'+import createPersistedstate from 'vuex-persistedstate'import user from './modules/user'import cart from './modules/cart'import cart from './modules/category'export default createStore({modules: {user,cart,category},+ plugins: [+ createPersistedstate({+ key: 'erabbit-client-pc-store',+ paths: ['user', 'cart']+ })+ ]})
注意:
===> 默认是存储在localStorage中
===> key是存储数据的键名
===> paths是存储state中的那些数据,如果是模块下具体的数据需要加上模块名称,如user.token
===> 修改state后触发才可以看到本地存储数据的的变化。
测试: user模块定义一个mutation在main.js去调用下,观察浏览器application的localStorage下数据。
src/App.js
<template><div class="container"><!-- 修改数据,测试是否持久化 -->App {{$store.state.user.profile.account}}<button @click="$store.commit('user/setUser',{account:'zhousg'})">设置用户信息</button></div></template><script>export default {name: 'App'}</script>
请求工具
目的:基于axios封装一个请求工具,调用接口时使用。
- 安装 axios
npm i axios
- 新建
src/utils/request.js模块,代码如下
// 封装通用的接口调用模块----------------------import axios from 'axios'import store from '@/store'import router from '@/router'// ------------------请求的基准路径-----------------------------export const baseURL = ''// 创建独立的axios的实例const instance = axios.create({baseURL: baseURL,timeout: 5000})// ------------请求拦截器:统一添加请求头--------------------instance.interceptors.request.use((config) => {// 判断Vuex中是否有token,如果有就添加到请求头const token = store.state.user.profile.token// 2. 判断是否有tokenif (token) {// 3. 设置tokenconfig.headers.Authorization = 'Bearer ' + token}return config}, (err) => {return Promise.reject(err)})// ------------响应拦截器:处理后端返回的数据,把data属性去掉----------------instance.interceptors.response.use((response) => {return response.data}, (err) => {// 处理token的过期操作if (err.response && err.response.status === 401) {// token过期了,清空过期的用户信息,跳转到登录页面store.commit('user/updateUserInfo', {})router.push('/login')}return Promise.reject(err)})// ----------------封装一个通用的请求方法----------------------------export default (options) => {return instance({// 如果没有传递请求方式,默认是使用get请求method: options.method || 'GET',// 请求地址url: options.url,// 对象的键可以是动态的变量// get请求,添加params属性,其他请求添加data属性[options.method.toUpperCase() === 'GET' ? 'params' : 'data']: options.data// data用于传递请求体数据(POST/PUT/DELETE)// data: options.data,// params用于传递get请求数据(查询字符串)// params: options.data})}
路由设计
目的:知道项目路由层级的设计

| 路径 | 组件(功能) | 嵌套级别 |
|---|---|---|
| / | 首页布局容器 | 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级 |
