【Vue项目】商品汇前台(一)组件拆分+请求封装
写在最前面
之前学完vue基础之后,一直想做一下前端的项目,但是自己写了一点前后端分离的项目发现自己前端写的是真的乱,所以趁着假期的空闲做一下尚硅谷商品汇的前后台项目,争取这周写完前台,然后这个月再写一下后台的前端和java后端,月底之前学习SpringBoot、下个月学完分布式的内容后再写前台的java后端。
1 项目的配置
1.1 关闭eslint校验工具
eslint校验比如在声明一个变量但是不使用的情况下就会报错导致不能正常运行,关闭之后便可以运行。方法是通过在根目录下创建一个vue.config.js文件:
module.exports = { // 关闭eslint lintOnSave: false }
1.2 为src文件夹配置别名@
在根目录下创建jsconfig.json
{ "compilerOptions": { "baseUrl": "./", "paths": { "@/*": ["src/*"] } }, "exclude": ["node_modules", "dist"] }
2 项目路由
2.1 项目路由分析
路由组件:main、login、register、search
非路由组件:
header:首页、搜索页
footer:首页、注册、登录页
注意:创建组件的时候,组件结构 + 组件样式 + 图片资源 缺一不可
2.2 完成Header与Footer非组件搭建
①Header
首先对静态页面进行拆分,页面放入template、less样式放入style。
注意:项目采用的是less样式,浏览器不识别less样式,需要通过less、less-loader进行处理less,将less变为css浏览器才能识别
less、less-loader安装
npm install --save less less-loader@5
想让组件识别less,需要在style标签上添加lang=“less”
添加后仍然报错的,如果使用的是VsCode的IDE,看下右下角的选择语言模式是不是html,改成Vue就可以了
2.3 路由组件的搭建
vue-router:经过上面的分析,路由组件应该有4个:Home、Search、Login、Register
components文件夹通常存放非路由组件(共用全局组件),pages或者views文件夹存放路由组件。安装vue-router:
npm install vue-router@3
2.3.1 配置路由
①项目中配置的路由一般放置在router文件夹下:router/index.js
import Vue from 'vue' import VueRouter from 'vue-router' import Home from '@/pages/Home' import Login from '@/pages/Login' import Register from '@/pages/Register' import Search from '@/pages/Search' Vue.use(VueRouter) export default new VueRouter({ routes: [ { path: '/home', component: Home }, { path: '/login', component: Login }, { path: '/register', component: Register }, { path: '/search', component: Search }, // 重定向 // { // path: '*', // redirect: '/home' // } ] })
区分路由器router和路由route,一个路由器可以包含很多路由规则。
②在main.js中注册路由
import Vue from 'vue' import App from './App.vue' import router from '@/router' Vue.config.productionTip = false let a = 100; new Vue({ render: h => h(App), router }).$mount('#app')
2.3.2 路由组件与非路由组件的区别
①路由组件一般放置在view、pages,非路由主键一般放置在components下
②路由组件需要在router文件夹中进行注册,使用的即是组件的名字;而非路由组件使用的是以标签的形式。
③注册完路由,不论是路由组件还是非路由组件身上都有
$route:一般用于获取路由信息【路径、query、params等】
$router:一般用于编程式导航进行路由跳转【push|replace】
2.3.3 路由的跳转
①声明式导航 router-link
声明式路由导航在编译后相当于a标签,同时要求属性to声明跳转后的路由路径。
<router-link to='/login'>登录</router-link> <router-link to='/register' class="register">免费注册</router-link> <router-link to='/home'><img src="./images/logo.png" alt=""></router-link>
②编程式导航 push|replace
<button class="sui-btn btn-xlarge btn-danger" type="button" @click="gosearch">搜索</button>
gosearch() { this.$router.push('/search') }
2.4 路由元信息的使用
场景:路由组件Login、Register不需要footer组件,Home、Search需要
解决方法一:通过$route获取路由路径判定
<Footer v-show="$route.path === '/home' || $route.path === '/search'"></Footer>
解决方法二:通过$route获取路由元信息判定
①在路由配置文件添加元信息
{ path: '/home', component: Home, meta: { showFooter: true } }, { path: '/login', component: Login, meta: { showFooter: false } }, ...
元信息的写法是固定的,即为meta不能修改
②使用元信息判定
<Footer v-show="$route.meta.showFooter"></Footer>
2.5 路由传参
①字符串形式
params参数: 需要先在路由配置文件中进行参数配置,如下keyWord即为传递的参数
{ path: '/search/:keyWord', component: Search, meta: { showFooter: true } },
this.$router.push('/search/' + this.keyWord)
params参数:{{$route.params.keyWord}}<br/>
query参数:不需要进行参数配置,直接在跳转前push后,在跳转后路由进行参数获取:
this.$router.push('/search?k=' + this.keyWord)
query参数:{{$route.query.k}}
②模板形式
略
③对象形式
goSearch() { this.$router.push({ name: 'search', params: { keyWord: this.keyWord }, query: { k: this.keyWord.toUpperCase() } }) }
对象形式需要route添加name属性
2.6 重写push和replace方法
编程式路由跳转到当前路由(参数不变),多次执行会抛出NavigationDuplicated的警告错误。声明式导航不会出现这种情况,因为vue-router底层已经处理好了。编程式导航出现这种警告错误是因为最新的vue-router引入了promise。
对push方法执行结果输出后即可得到promise,promise需要传递一个成功或者失败的回调,才能处理这次异常。
let result = this.$router.push({ name: 'search', params: { keyWord: this.keyWord }, query: { k: this.keyWord.toUpperCase() } }) console.log(result)
Promise {<fulfilled>: {…}} [[Prototype]]: Promise [[PromiseState]]: "fulfilled" [[PromiseResult]]: Object
解决方法:在push中为promise传递成功和失败的两个参数,再进行多次点击就不会出现错误警告
goSearch() { this.$router.push( { name: "search", params: { keyWord: this.keyWord, }, query: { k: this.keyWord.toUpperCase(), }, }, // 成功参数 () => {}, // 失败参数 () => {} ); },
但是这种方法需要在每个组件的push、replac方法上添加这样的参数,比较麻烦,所以最根本的方法是在VueRouter原型上直接修改push、replace方法添加,这样所有的方法就不必自己添加了。
// 保存原型push方法 let orignPush = VueRouter.prototype.push; let orignReplace = VueRouter.prototype.replace; // 修改VueRouter的push // 第一个参数告诉原来的push方法往哪里跳(传递了那些参数) // resolve reject参数传递了成功失败参数 VueRouter.prototype.push = function(location, resolve, reject){ if(resolve && reject) { orignPush.call(this, location, resolve, reject) } else { // this为VueRouter,call将上下文修改为了Vuerouter orignPush.call(this, location, ()=>{}, ()=>{}) } } VueRouter.prototype.replace = function(location, resolve, reject){ if(resolve && reject) { orignReplace.call(this, location, resolve, reject) } else { orignReplace.call(this, location, ()=>{}, ()=>{}) } }
3 Home组件业务拆分及实现
结构+样式+图片资源
3.1 TypeNav三级联动组件
首先将静态页面的模板和样式拆分到pages/Hemo/TypeNav/index.vue下,然后在main.js下进行全局组件注册。
import TypeNav from '@/pages/Home/TypeNav' Vue.config.productionTip = false; Vue.component(TypeNav.name, TypeNav);
Vue注册全局组件函数component的第一个参数为组件的名字(需要在组件中进行指定),第二个参数为组件本身
最后在Home/index.vue中使用三级联动组件。
<template lang=""> <div> <TypeNav/> </div> </template> <script> export default { } </script> <style lang=""> </style>
3.2 ListContainer
包含轮播图加右侧尚品汇快报,不需要全局注册
3.3 TodayRecommend
包含今日推荐块
3.4 Rank
3.5 Like
3.6 Floor
4 PostMan工具测试接口
请求地址:http://gmall-h5-api.atguigu.cn
测试:

5 axios二次封装
常见的服务器发送请求方式:XMLHttpRequest、fetch、FQ、axios
为什么要封装axios?
可以对请求和响应拦截器进行封装修改,请求拦截器可以在请求之前处理一些业务,响应拦截器则是在服务器数据返回之后处理一些事情。
5.1 安装axios
npm i --save axios
5.2 建立API文件夹request.js封装axios请求
request.js
// 对axios进行二次封装 import axios from 'axios' import { config } from 'vue/types/umd'; // 1 利用axios create创建一个axios实例 // 2 requests就是配置参数后的axios实例 const requests = axios.create({ // 基础路径,请求发出的时候,路径前面就会出现api baseURL: '/api', // 设置请求超出事件 timeout: 5000 }) // 请求拦截器,在请求发出之前能够检测到,做一些指定的业务 requests.interceptors.request.use((config)=>{ // 参数为config的回调函数 // config为配置对象,包含一个中要的属性headers请求头 return config; }); requests.interceptors.response.use((res)=>{ // 响应成功的回调函数 return res.data; }, error=>{ // 响应失败的回调函数 // 终止promise链 return Promise.reject(new Error('faile')) }) export default requests;
6 接口统一管理
方便在接口变更的时候直接修改不必一个个去修改。
6.1 跨域问题
什么是跨域:违背了同源策略,即协议名、主机名、端口号必须一致。浏览器与服务器之间存在跨域问题,而服务器与服务器之间由于通过Http通信是不存在跨域问题的。
具体不多介绍了,详细地跨域移步我之前的这篇博客:【Vue】前端解决跨域问题 - Tod4 - 博客园
vue.config.js
module.exports = { // 关闭eslint校验工具 lintOnSave: false, // 代理跨域 devServer: { proxy: { // 当路径出现api时,代理服务器开始工作 // http://localhost:8080/api -> 8080端口的代理服务器 -> http://gmall-h5-api.atguigu.cn/api '/api': { target: 'http://gmall-h5-api.atguigu.cn' } } } }
如此一来,只要请求含有api就会被代理服务器发送请求到目标服务器,解决了浏览器客户端和服务器端的跨域问题。
\http://localhost:8080/api -> 8080端口的代理服务器 -> \http://gmall-h5-api.atguigu.cn/api
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步