- 先写完静态页面(html、css)
- 拆分静态组件(将Home模块拆成7个组件)
- 获取服务器数据,动态展示
TypeNav三级联动组件
在main.js处注册成为全局组件,可以在项目的任意地方使用
// 注册全局组件
import TypeNav from "@/pages/Home/TypeNav/TypeNav.vue";
Vue.component(TypeNav.name, TypeNav);
//第一个参数:全局组件的名字;第二个参数:要注册成为全局组件的组件
在任意组件内,TypeNav无需注册,直接使用
<template>
<div>
<TypeNav></TypeNav>
</div>
</template>
注册时使用什么名字,在组件中就写什么标签
Vue.component(TypeNav.name, TypeNav);
如果是随便起的名字,要用"“(此处TypeNav.name是一个变量,没有用”")
向服务器请求数据
-
先用POSTMAN测试接口是否可用
服务器的ip地址http://39.98.123.211 (返回一个HTML页面??)
最新接口地址http://gmall-h5-api.atguigu.cn
首页三级分类的接口/api/product/getBaseCategoryList,请求方式GET
如果服务器返回的数据code字段200,代表服务器返回数据成功
接口前缀都有/api:
封装axios
向服务器发请求:XMLHttpRequest、fetch、jQuery、axios
为什么要二次封装axios?主要使用axios的请求拦截器和响应拦截器
- 请求拦截器: 可以在发请求之前处理一些业务(添加cookie、token,请求头等)
- 响应拦截器: 当服务器数据返回以后,可以处理一些事情
-
安装axios插件——项目依赖
npm install axiso
![图片.png](https://img-blog.csdnimg.cn/img_convert/a95d60ac7f59fa15ace8c149c8a7307f.png)
-
在src文件夹下,有一个api文件夹,存储axios请求
二次封装axios,代码在api/request.js中
- 配置拦截器: 在请求或响应被then
或 catch
处理前拦截它们
- 首先创建一个axios实例对象
import axios from "axios" //axios是一个构造axios实例的类
const myRequest = axios.create({ //利用静态方法create创建实例
baseURL:"",
timeout:1000, //1s后没有返回响应,则请求失败
headers:{}
})
-
一个axios实例就创建好了,我们就可以使用实例属性、实例方法
-
请求拦截器
// 添加请求拦截器
myRequest.interceptors.request.use((config)=>{
// config是一个配置对象,对象里的header属性很重要
// 在发送请求之前做些什么
return config;
});
- 响应拦截器
// 添加响应拦截器
myRequest.interceptors.response.use((response)=>{
// 服务器响应成功的回调函数:服务器成功返回数据后,响应拦截器可以检测到
if(response.code===200){
return response.data;
}
},(error)=>{
// 服务器响应失败的回调函数
return Promise.reject(error); //终止promise链
});
- 最后对外暴露axios实例对象
export default myRequest;
总结:
- 请求拦截器:其实就是先执行要添加的数据,然后再执行Ajax,如果把这个添加数据的过程抽出来,就成了所谓的请求拦截器了
- 响应拦截器:就是是在请求结果返回后的同时,先不直接导出,而是先对响应码等等的进行处理,处理好之后再导出给页面,如果将这个对象响应码的处理过程抽出来,就成了所谓的响应拦截器
api接口统一管理
对外暴露一个函数,只要外部调用这个函数,就向服务器发送ajax请求。
此函数执行后需要把服务器返回的结果返回
axios发送请求,返回的结果是promise实例对象
项目很小:可以在生命周期钩子里发送ajax请求
项目比较大:统一管理api
import myRequests from "./request.js"; //引入二次封装好的axios实例对象
// 三级联动接口 请求地址/api/product/getBaseCategoryList 请求方式GET 不携带参数
export const reqCategoryList = () => {
// 发请求:axios返回的结果是promise实例对象
return myRequests({
url: "/product/getBaseCategoryList",
method: "get",
});
};
// 测试一下能否成功发送请求——分别暴露时,引入要加{}
import { reqCategoryList } from "@/api/index.js";
reqCategoryList();
- 解决ajax跨域问题——配置vue脚手架:配置跨域代理服务器
跨域:前后端服务器的协议、域名、端口号任一不同,就称为跨域
例如: 本地服务器的地址 http://localhost:8080/ 后端服务器的地址 http://gmall-h5-api.atguigu.cn/api/…… (域名和端口号不同)
解决办法:在vue.config.js里配置代理服务器,配置文件需要重新运行才能生效
JSONP、CROS、代理服务器(webpack提供的功能)
服务器与服务器之间不用ajax请求,没有跨域问题;
服务器与浏览器有跨域问题,而代理服务器与前端服务器同源,可以去代理服务器取数据777777777777
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
// 关闭语法校验
lintOnSave: false,
// 配置代理跨域
devServer: {
proxy: {
// 只要请求路径出现/api字段,会将请求代理到http://gmall-h5-api.atguigu.cn/api/……
"/api": {
target: "http://gmall-h5-api.atguigu.cn",
},
},
},
});
进度条nprogress插件
-
安装插件
npm install nprogress
-
在request.js中引入进度条
import nprogress from "nprogress";
引入进入条样式`import "nprogress/nprogress.css";`
-
在请求拦截器中配置"进度条开始"
nprogress.start();
-
在相应拦截器中,等待数据返回成功后配置"进度条结束"
nprogress.done();
vuex状态管理器
vuex是官方提供的一个插件,是一个状态管理库,集中式管理项目中组件共用的数据
(项目较大时,可以用vuex,方便维护数据)
-
安装插件
npm i vuex@3
(vue2用vuex@3,vue3用pinia)![图片.png](https://img-blog.csdnimg.cn/img_convert/4f9ac39b7ff470c7ab7997b2cd96cd19.png)
-
在src文件夹下新建store文件夹
import Vue from "vue";
import Vuex from "vuex";//Vuex是一个对象,有一个Store方法(构造函数,创建store实例)
Vue.use(Vuex);
// 对外暴露一个Store类的实例
export default new Vuex.Store({
// 配置对象——state、getters、mutaition、actions(它们4个都是对象)
});
-
在入口文件引入store实例
import store from "./store/index.js"
在vm身上配置store配置项(store配置项是一个Store实例对象)
// 引入仓库
import store from "@/store";
new Vue({
// 注册仓库
store,
})
vuex的模块化
思路:根据不同的业务,将该业务state、mutations、action、getters 的封装在一个js文件中,让多种数据分类更加明确,代码更好维护 --> 将store大仓库分为一个一个小仓库
实现:利用Vuex.store的modules配置挂载在store上
home模块的小仓库
const state={};
const mutations ={};
const actions = {};
const getter = {};
export default{
namespaced:true,
state,
mutations,
actions,
getter
}
// 或者直接默认暴露
export default {
// 开启命名空间
namespaced: true,
state: {},
getters: {},
actions: {},
mutation: {},
};
// 引入小仓库
import home from "./Home/index.js";
import search from "./Search/index.js";
// 对外暴露一个Store类的实例
export default new Vuex.Store({
// 实现Vuex仓库模块式存储数据
modules: {
home: home, //将home仓库的数据赋给home变量
search,
},
});
组件读取仓库中的数据
命名空间:namespaced:true