# vue-ev-71 **Repository Path**: leetc/vue-ev-71 ## Basic Information - **Project Name**: vue-ev-71 - **Description**: 这是一个很大的事件 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-02-27 - **Last Updated**: 2022-03-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 大事件项目纪要 ## 注册功能 ### 使用路由切换组件 1. 新建组件: `src/views/Reg/Reg.vue` `src/views/Login/Login.vue` 2. 配置路由规则 3. 在 App.vue 中设置路由的挂载点 `router-view` ### 渲染基础布局 1. 在 main.js 引入全局样式 `global.less` 2. 讲义中复制静态页面粘贴到 Reg.vue 组件中 注意事项: router-view 外面不要包裹 div, 否则高度会出问题 ### 渲染表单组件 1. 去官网复制 form 组件的前四行, 加上闭合标签 2. 调整样式和数据 ### 注册表单校验 1. 去官网复制表单校验规则 检查以下三个属性的配置 model rules prop 2. 根据需求配置校验规则 自定义校验规则同样参考官网 ### 完成注册功能 1. 兜底校验 手动调用校验方法, 确保用户全部输入正确后才发请求 2. 发请求注册 3. 获取到结果后应该对结果进行判断, 提醒用户 4. 编程式导航跳转至登录页 ### 提交注册功能到码云 1. 新建 reg 分支 ```bash git checkout -b reg ``` 2. 提交到本地仓库 ```bash git add . git commit -m "完成注册功能" ``` 3. 推送到远程 (由于 reg 远程没有, 所以需要 -u) ```bash git push -u origin reg ``` 4. 切换回 master 分支 ```bash git checkout master ``` 5. 合并 reg 分支 ```bash git merge reg ``` 6. 推送到远程 ```bash git push ``` ## 登录功能 ### 渲染基础布局及表单验证 1. 复制笔记中的基本结构 (删除关键代码重新去官网复制) 2. 完成表单验证 3. 给 el-link 添加点击事件, 使用编程式导航进行页面跳转 ### 点击登录发送请求 1. 给登录按钮绑定点击事件 2. 兜底校验 3. 校验通过后发送请求 4. 获取结果后判断, 并提醒用户 ### 将 token 存入 Vuex 1. 定义 Vuex 的子模块 user, 定义数据 token 2. 定义 mutations 函数, 用于更新 token 3. 当用户登录成功后, 使用 commit 触发 mutations 函数更新 token ### 持久化存储 Vuex 1. 装包 ```bash yarn add vuex-persistedstate ``` 2. 导入到 store/index.js ```js import createPersistedState from 'vuex-persistedstate' ``` 3. 安装插件 ```js const store = new Vuex.Store({ plugins: [createPersistedState()] }) ``` 注意: 只要安装了插件, Vuex 中的所有数据将被自动存储到 localStorage, 页面刷新时会自动从中取值 ### 登录成功跳转至首页 1. 登录成功后使用编程式导航跳转到首页 2. 创建 Main 组件后配置路由规则 ### 退出登录 1. 给退出登录按钮绑定点击事件, 使用确认框 this.$confirm 提醒用户是否确认退出 2. 用户点击确认后, 清空 token 3. 跳转至登录页 ## 首页 ### 渲染用户信息 1. 复制静态页面和样式 2. 在 Vuex 中定义数据 userInfo 3. 使用 actions 获取数据, 通过 mutations 修改数据 4. 在 Main.vue 的created 中调用 actions 发请求 5. 在 Main.vue 中导入数据并渲染, 处理默认头像 ### 渲染左侧菜单基本布局 1. 去官网复制 el-menu 到项目中进行修改 2. 设置样式 (颜色 / 宽度 ...) ### 配置请求拦截器携带 token 1. 去 axios 官网复制请求拦截器代码 2. 将 vuex 中的 token 携带到请求头上 3. 所有请求都不需要手动设置 token 了 ### 拦截未登录用户访问首页 1. 配置全局前置导航守卫 2. 如果没有登录允许跳转到 /login /reg, 不允许跳到 / ### 渲染首页组件 1. 创建 Home.vue 组件, 复制静态页面代码 2. 安装 echarts 3. 配置路由规则, 设置重定向 4. 在 Main.vue 中设置 router-view ## 用户中心 ### 渲染基本资料模块 1. 创建 UserInfo 组件, 赋值静态页面代码 2. 配置路由规则 3. 开启 el-menu 的路由模式 4. 设置默认高亮为 $route.path ### 重置表单 1. 给重置按钮绑定点击事件 2. 调用 $refs.userForm.resetFields() ### 更新用户信息 1. 点击按钮兜底校验 2. 校验通过后发起请求更新用户信息 3. 调用 actions 的函数重新获取用户信息, 由于 vuex 的数据是响应式的, 所以用到数据的地方都会更新 ## 用户头像 ### 选择图片 1. 添加一个 input:file 的表单元素, 将其隐藏 2. 给按钮绑定点击事件, 点击按钮后触发 input:file 点击事件 3. 给 input 绑定 change 事件, 捕获用户选择的图片 ### 渲染用户选择的头像 1. 获取到的图片是 File 对象, 无法直接设置给 img 的 src, 需要将其转换成 base64 或 url 2. 使用 FileReader 进行转换 3. 创建 FileReader 对象 4. 调用 readAsDataURL 方法去异步读取文件 5. 监听 FileReader 对象的 onload 事件获取结果设置给 img 的 src ### 更新用户头像 1. 动态绑定上传头像按钮的 disabled 属性 2. 给按钮绑定点击事件, 点击后发请求上传 ## 重置密码 ### 渲染重置密码模块 1. 复制静态页面 2. 配置路由 ### 表单校验 1. 定义校验规则进行校验 2. 自定义校验检查两次输入的密码是否一致 3. 重置密码点击事件, 调用 $refs.pwdForm.resetFields() ### 更新用户密码 1. 点击事件中进行兜底校验 2. 校验通过后发请求提示用户 3. 重置表单 ## 文章分类 ### 获取分类数据 1. 在 data 中定义数据, methods 中定义获取的方法 2. 在 created 调用方法获取数据即可 ### 渲染表格 1. 去官网复制表格组件, 修改属性适配我们的数据 2. 设置序号需要使用 type="index" ### 重置表单 1. 给 dialog 绑定 closed 事件 2. 事件中调用重置表单方法 ### 添加分类功能完成 1. 点击按钮进行兜底校验 2. 校验通过后发请求 3. 根据结果提醒用户 4. 关闭 dialog 5. 重新获取所有分类数据 ### 编辑分类组件渲染 1. 复制添加分类的 dialog 进行修改, 能弹出即可 ### 编辑功能完成 1. 点击编辑按钮渲染数据 (作用域插槽 / 传递数据到事件处理函数) 2. 将数据进行浅拷贝到 data 中 3. 给修改按钮绑定点击事件 4. 点击按钮进行兜底校验 5. 校验通过后发请求 6. 根据结果提醒用户 7. 关闭 dialog 8. 重新获取所有分类数据 9. 用户点击 id 为 1 或 2 的分类时阻止并提醒 ### 删除分类功能完成 1. 给删除按钮绑定事件传递 id 2. 用户点击 id 为 1 或 2 的分类时阻止并提醒 3. 使用 $confirm 对话框提醒用户是否确认删除 4. 用户确认后发送请求传递 id (查询参数) 5. 根据结果提醒用户 6. 重新获取所有分类数据 ## 文章列表 ### 渲染组件 1. 创建文章列表组件, 配置路由渲染 ### 渲染发布文章 dialog 1. 去官网复制 dialog , 并添加一个 fullscreen 实现全屏的 dialog 2. 设置 before-close 属性, 当用户点击 x 的时候提醒用户是否确定关闭 ### 渲染发布文章表单 1. 复制官网的 form 组件进行修改 2. 书写表单校验规则 ### 渲染文章分类 1. 获取文章分类数据 2. 使用 v-for 循环渲染 el-option 3. 使用 v-model 在 el-select 绑定表单要提交的数据 cate_id ### 选择封面设置数据 1. 给文本按钮绑定点击事件, 触发文件选择框的点击事件 2. 监听文件选择框的 change 事件, 当用户选择了文件后判断是否有选择 3. 如果选择了就设置到表单数据上 ### 选择封面预览 1. 导入默认图片, 在 data 中设置一个变量绑定默认图片给 src 2. 当用户选择图片后使用 URL.createObjectURL() 创建 url 设置给 src, 实现预览 3. 用户取消选择时, 设置回默认图片 ### 发布文章前准备工作 1. 添加发布和草稿按钮并绑定点击事件设置 state 2. 兜底校验 - 给封面添加校验规则 - 修改文章分类的 trigger 为 change - 选择封面后手动校验封面字段 3. 关闭 dialog 后清空表单 (使用 resetFields 需要给每个字段设置 prop 属性) ### 发布文章功能完成 1. 创建 FormData 对象 2. 往 FormData 对象中添加数据 3. 发请求 4. 根据结果提醒用户 5. 关闭 dialog 6. TODO: 刷新文章列表 暂未完成 ### 渲染文章列表 1. 封装获取文章列表的函数, 在 created 时调用 2. 发送请求获取文章列表 3. 使用 table 组件渲染数据 4. 发表文章后需要调用函数重新获取数据 ### 日期格式化 1. 使用 table 组件的作用域插槽获取到数据 2. 下载 dayjs 3. 进行格式化后返回数据并渲染 ### 渲染分页组件 1. 去官网复制完整功能的分页组件 2. 根据需求修改对应的属性 1. 绑定两个事件: size-change current-change 事件 2. current-page 设置为 q.pagenum (当前在第几页) 3. page-sizes 设置为 [2, 3, 5, 10] 4. page-size 设置为 q.pagesize (每页显示多少条) 5. total 设置为总数量 (获取数据时服务器返回的) ### 分页功能实现 1. 理解分页的流程, 用户点击下一页或指定页码时, 重新发起请求获取数据, 覆盖渲染 2. 在 current-change 事件中获取到当前页码, 设置给 q.pagenum 请求参数中, 发起请求 3. 在 size-change 事件中获取到当前的分页大小, 设置给 q.pagesize 请求参数中, 发起请求 ### 筛选数据 1. 使用 v-for 循环渲染 el-option (已实现双向绑定) 2. 用户点击筛选时发请求获取筛选后的数据 3. 用户点击重置时, 重置 q 对象, 发请求 ### 筛选重置 Bug 修复 1. 切换到最后一页后筛选, 数据丢失 原因: 切换到最后一页时, pagenum 设置为了最后一页, 点击筛选时数据没有那么多, 所以获取不到数据 解决方案: 点击筛选时, 将 pagenum 设置为 1 2. 当选择了分类后, 点击页码最后一页, 数据丢失 原因: 类似于上面, 点击分类后双向绑定给了 q.cate_id 页码切换后会发送请求, 导致数据获取不到 解决方案: 1. 定义数据 filterState: { cate_id, state } 2. 双向绑定给 el-select (用户选择分类或状态时不会修改 q 的属性) 3. 点击筛选时将 filterState 的两个属性设置给 q 后发请求 ### 获取文章详情数据 1. 将所有的标题使用作用域插槽进行渲染, 可以使用 el-link 组件 2. 给 el-link 组件绑定点击事件, 传递 id 3. 根据 id 获取数据并存入 data ### 渲染文章详情 1. 使用dialog 渲染文章详情数据 2. 编写差值表达式和样式完成功能 ### 实现删除功能 1. 给删除按钮绑定事件传入 id 1. 通过确认框提醒用户是否删除 2. 通过 id 删除数据 3. 根据响应结果提醒用户 4. 重新获取文章列表数据 6. 当前页如果只有一条数据, 则让 pagenum-- 后重新获取 ## 打包上线 ### 配置 externals 结合 CDN 加速 流程 1. 找到要 CDN 加速的包 (report.html 中最大的包) 2. 去 jsdelivr 上搜索对应的包名 3. 将 js 文件引入到 test.html 测试, 观察 window 对象中添加了什么属性 4. 在 vue.config.js 中配置 externals 属性 5. 将测试的代码复制到 index.html (注意全局 css 也可以引入过来, 将 main.js 的 css 引入删除)