一,mockjs模拟banner和floor接口操作,组件获取数据
1.创建mock文件夹,创建banner.json和floor.json, mockServer.js(提供服务,模拟接口) 安装mockjs npm i mockjs
mockServer.js 文件内容
//正儿八经的模拟接口
import Mock from 'mockjs'
import banner from './banner.json' //json数据被引入之后会变为真正的数组,不再是json串了
import floor from './floor.json' //json数据被引入之后会变为真正的数组,不再是json串了
//第一个参数,是以后我们要请求的模拟接口路径
//第二个参数,是访问这个接口后返回的数据
// '/mock/banner' /mock不能省,因为这个并不是去发送ajax请求,
// 发请求可以省,是因为我们在axios配置了baseUrl
// 这个不是发请求,是模拟整个接口
Mock.mock('/mock/banner',{code:200,data:banner})
Mock.mock('/mock/floor',{code:200,data:floor})
//最后切记在入口文件去引入一下,代表这个文件一开始就会执行
2.在入口文件main.js导入mock,
//对axios的二次封装
// 配置基础路径和超时限制
// 添加进度条信息 nprogress
// 返回的响应不再需要从data属性当中拿数据,而是响应就是我们要的数据
// 统一处理请求错误, 具体请求也可以选择处理或不处理
import axios from 'axios'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
const service = axios.create({
baseURL: '/mock', // 配置基础路径
timeout: 20000, //和超时限制
});
//请求拦截器
//请求拦截器内部一般不会处理错误的信息
service.interceptors.request.use(config => {
//config是发送请求的配置对象,必须处理完返回这个配置对象
//开启我们的进度条
NProgress.start()
return config
});
// 响应拦截器
service.interceptors.response.use(
response => {
//停止进度条
NProgress.done()
//返回响应的时候,直接返回响应的data
return response.data
},
error => {
NProgress.done()
alert('请求出错' + error.message || '未知错误')
//以后不允许用户继续处理: 中断promise链
return new Promise(() => {}) //返回pending状态的promise 中断
//以后它允许用户继续对错误进行处理
// return Promise.reject(error)
}
);
export default service
4.在api---index.js中,使用mock的接口去请求 banner数据
引入二次封装的ajax; import mockAjax from '@/ajax/mockAjax'
// 使用mock的接口去请求 banner数据 get 请求 /banner
export const reqBannerList = () => mockAjax.get('/banner')
export const reqFloorList = () => mockAjax.get('/floor')
5.在入口文件main.js中导入mock接口函数
//这个是为了测试接口请求函数 后期也会使用这样的方式去使用
import * as API from '@/api'
// console.log(API)
// API.reqBannerList()
// API.reqFloorList()
6.在store---home.js,中,将mock请求的数据保存在vuex中
home.js内容
import {reqCategoryList,reqBannerList,reqFloorList} from '@/api'
const state = {
categoryList : [],
bannerList:[],
floorList:[]
}
const mutations = {
//直接修改数据
RECEIVECATEGORYLIST(state,categoryList){
state.categoryList = categoryList
},
RECEIVEBANNERLIST(state,bannerList){
state.bannerList = bannerList
},
RECEIVEFLOORLIST(state,floorList){
state.floorList = floorList
}
}
const actions = {
//异步请求数据
//async 和 await的用法
async getCategoryList({commit}){
const result = await reqCategoryList()
if(result.code === 200){
commit('RECEIVECATEGORYLIST',result.data)
}
},
async getBannerList({commit}){
const result = await reqBannerList()
if(result.code === 200){
commit('RECEIVEBANNERLIST',result.data)
}
},
async getFloorList({commit}){
const result = await reqFloorList()
if(result.code === 200){
commit('RECEIVEFLOORLIST',result.data)
}
},
}
const getters = {
bannerList(state){
return state.bannerList
}
}
export default {
state,
mutations,
actions,
getters
}
computed: {
// 总的store 内部的state比较特殊 state总的内部会有home,数据是放在home对象内部
// 其它的getters mutations actions 都没有
// ...mapState({
// bannerList : state => state.home.bannerList
// })
...mapGetters(["bannerList"])
},
在html模板中填充数据
<div class="swiper-wrapper"> <div class="swiper-slide" v-for="(banner, index) in bannerList" :key="banner.id"> <img :src="banner.imgUrl" /> </div> </div>
此时mock模拟接口的图片需要放在public文件夹中,图片才会显示
computed:{
...mapState({
floorList: state => state.home.floorList
})
}
组件数据
注:此时数据在父组件home中,需要将数据传给子组件floor组件中,父子通信,属性传递
<template> <div> <TypeNav></TypeNav> <ListContainer></ListContainer> <Recommend></Recommend> <Rank></Rank> <Like></Like> <Floor v-for="(floor, index) in floorList" :key="floor.id" :floor="floor"></Floor> <Brand></Brand> </div> </template>
子组件floor接收数据 props:['floor'],
html模板填充数据
<div class="blockgary"> <ul class="jd-list"> <li v-for="(keyword, index) in floor.keywords" :key="index">{{keyword}}</li> </ul> <img :src="floor.imgUrl" /> </div>
<div class="split"> <span class="floor-x-line"></span> <div class="floor-conver-pit"> <img :src="floor.recommendList[0]" /> </div> <div class="floor-conver-pit"> <img :src="floor.recommendList[1]" /> </div> </div>
二, 轮播图swiper基本使用及动态数据
1.安装5版本的swiper, npm i swiper@5 -S 目前最新是6,不稳定
2.在listContainer组件中,引入swiper,
<!-- <div class="swiper-container" ref="banner"> <div class="swiper-wrapper"> <div class="swiper-slide" v-for="(banner, index) in bannerList" :key="banner.id"> <img :src="banner.imgUrl" /> </div> </div> <div class="swiper-pagination"></div> <div class="swiper-button-prev"></div> <div class="swiper-button-next"></div> </div> -->
3. 实例化swiper对象
mounted() {
this.getBannerList();
//为什么Swiper在实例的时候放在mounted当中 静态数据是可以的
//动态数据就不行
// 静态数据一上来就加载完成了,我们页面的结构也就形成了,然后创建swiper 理所当然就可以
//动态数据 是我们异步请求的,mounted里面发请求完之后 立即实例化swiper,此时请求的数据不一定回来
//而我们的页面结构是依赖动态的数据进行创建的
// new Swiper(this.$refs.banner, {
// // direction: "vertical", // 垂直切换选项,默认是水平切换
// // loop: true, // 循环模式选项
// // 如果需要分页器
// pagination: {
// el: ".swiper-pagination"
// },
// // 如果需要前进后退按钮
// navigation: {
// nextEl: ".swiper-button-next",
// prevEl: ".swiper-button-prev"
// }
// // 如果需要滚动条
// // scrollbar: {
// // el: ".swiper-scrollbar"
// // }
// });
},
注:此时swiper没有效果,因为页面还没有渲染成型,更深的说,this.getBannerList();发送ajax,是异步的,数据还没有请求过来,页面就还未渲染
// watch: {
// bannerList: {
// handler() {
// //Vue.nextTick或者vm.$nextTick是一样的功能
// //在最近的一次dom更新之后执行nextTick里面传的回调函数
// this.$nextTick(() => {
// new Swiper(this.$refs.banner, {
// // direction: "vertical", // 垂直切换选项
// // autoplay:true,//等同于以下设置
// loop: true, // 循环模式选项
// // 如果需要分页器
// pagination: {
// el: ".swiper-pagination"
// },
// // 如果需要前进后退按钮
// navigation: {
// nextEl: ".swiper-button-next",
// prevEl: ".swiper-button-prev"
// }
// // 如果需要滚动条
// // scrollbar: {
// // el: ".swiper-scrollbar"
// // }
// });
// });
// },
// immediate:true //立即执行,在最近dom更新之前就会执行
// },
// }
注:此时swiper轮播图还是没有数据,因为,数据跟新了,但是此时有v-for, 页面还未渲染,此时需要引入vm.$nextTick
floor组件依次引入swiper,进行轮播图切换
抽离公共的swiper组件,注册为全局组件,将数据传入swiper组件