1.复习
1)完成商品分类的三级列表路由跳转一级路由传参(合并参数)
2)完成search模块中对于typenav的使用(过渡动画)
3)对于typenav请求次数也进行了优化
4)swiper
swiper插件:经常制作轮播图,移动端,pc端都可以使用
使用步骤:
第一步:引入相关依赖包(swiper.js|css)
第二步:页面的结构必须要有
第三步:初始化swiper实例,给轮播图添加动态效果
5)mock数据,通过mockjs模块实现
2.轮播图问题
最完美的方法解决轮播图
定时器:setTimeout()
mouted:组件挂载完毕,正常说组件结构(dom)已经有了
为什么swiper实例在mouted当中直接书写不可以?因为结构没有完整
watch+nexTick:数据监听已有数据的变化
export default{
name:“”,
mounted(){
// 派发action,通过vuex发送ajax请求,将数据存储在仓库中
this.$store.dispatch(“getBannerList”);
},
watch:{
//监听bannerlist数据的变化
// 由空数组变为有数据
bannerList:{
// 对象的写法
handler(newValue,oldValue){
// 现在通过watch监听bannerlist属性值的变化
//如果执行handler方法,代表组件实例身上应该已经有了
// 当前的函数执行,只能保证bannerlist数据已经有了,没办法保证v-for已经执行结束
// v-for执行完毕才有结构【现在的watch无法保证】
// 在new swiper实例之前,页面结构必须要有
var mySwiper = new Swiper (‘.swiper’, {
direction: ‘vertical’, // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: ‘.swiper-pagination’,
clickable:true
},
// 如果需要前进后退按钮
navigation: {
nextEl: ‘.swiper-button-next’,
prevEl: ‘.swiper-button-prev’,
},
// 如果需要滚动条
scrollbar: {
el: ‘.swiper-scrollbar’,
},
})
}
在下次dom更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的dom
export default {
name: “”,
mounted() {
// 派发action,通过vuex发送ajax请求,将数据存储在仓库中
this.$store.dispatch(“getBannerList”);
},
watch: {
//监听bannerlist数据的变化
// 由空数组变为有数据
bannerList: {
// 对象的写法
handler(newValue, oldValue) {
// 现在通过watch监听bannerlist属性值的变化
//如果执行handler方法,代表组件实例身上应该已经有了
// 当前的函数执行,只能保证bannerlist数据已经有了,没办法保证v-for已经执行结束
// v-for执行完毕才有结构【现在的watch无法保证】
this.$nextTick(() => {
// 在new swiper实例之前,页面结构必须要有
var mySwiper = new Swiper(“.swiper-container”, {
// direction: “vertical”, // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: “.swiper-pagination”,
clickable: true,
},
// 如果需要前进后退按钮
navigation: {
nextEl: “.swiper-button-next”,
prevEl: “.swiper-button-prev”,
},
// 如果需要滚动条
// scrollbar: {
// el: “.swiper-scrollbar”,
// },
});
});
},
},
},
优化
更改id为ref
更改为this.
r
e
f
s
.
m
y
S
w
i
p
e
r
t
h
i
s
.
refs.mySwiper this.
refs.mySwiperthis.nextTick(() => {
// 在new swiper实例之前,页面结构必须要有
var mySwiper = new Swiper(this.$refs.mySwiper, {
// direction: “vertical”, // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: “.swiper-pagination”,
clickable: true,
},
3.开发floor
仓库没有也行,无法触发watch事件
切记:仓库当中state的数据格式,不要乱写
3.1getFloorList在哪里触发
需要在home路由组件中触发,不能再floor组件内部发action,因为我们需要v-for遍历组件
api—》》index.js
// 获取floor列表数据
export const reqFloorList = ()=>mockrequests.get(‘/floors’)
store–》》index.js
const state = {
// state中默认初始值不要瞎写
// 服务器返回对象,返回数组【根据接口初始化】
categoryList: [],
// 轮播图的数据
bannerList: [],
// floor组件的数据
floorList: []
}
const mutations = {
CATEGORYLIST(state, categorylist) {
state.categoryList = categorylist;
},
GETBANNERLIST(state, bannerlist) {
state.bannerList = bannerlist;
},
GETFLOORLIST(state, floorList) {
state.floorList = floorList;
}
}
const actions = {
// 通过api里面的接口函数调用,向服务器大请求,获取服务器数据
async categoryList({ commit }) {
let result = await reqCategoryList();
// console.log(result);
if (result.code == 200) {
commit(“CATEGORYLIST”, result.data);
}
},
// 获取首页轮播图的数据
async getBannerList({ commit }) {
let result = await reqGetBannerList();
// console.log(result);
if (result.code == 200) {
commit(“GETBANNERLIST”, result.data);
}
},
// 获取floor数据
async getFloorList({ commit }) {
let result = await reqFloorList();
if (result.code == 200) {
// 提交mutation
commit(‘GETFLOORLIST’, result.data);
}
}
}
// 计算属性
const getters = {}
export default {
state,
mutations,
actions,
getters
}
home–》》index.vue
export default {
name: “”,
components: {
ListContainer,
Recommend,
Rank,
Like,
Floor,
Brand,
},
mounted(){
// 派发action,获取floor组件的数据
this.$store.dispatch(‘getFloorList’);
}
};
v-for也可以在自定义标签使用
组件通信的方式:
pros:用于父子组件通信
自定义事件:@on @ emit 可以实现子给父通信
全局事件总线:¥bus 全能
pubsub-js:vue当中几乎不用 全能
插槽:vuex
home---->>>>index.vue
props父传子
floor–>>>>>index.vue
轮播图
import Swiper from “swiper”;
export default {
name: “”,
props: [“list”],
//组件挂载完毕的地方
mounted(){
// 第一次书写swiper的时候,在mouted不可以,现在可以运行
// 第一次写轮播图的时候,是在当前组件内部发送请求、动态渲染解析【前台至少等服务器数据回来】
// 本次是父传子,第一次是异步请求
// 现在为什么可以,请求是父组件发的,父组件通过props传递过来,而且结构都已经有了的情况下执行的mounted
var mySwiper = new Swiper(this.$refs.floor1Swiper, {
// direction: “vertical”, // 垂直切换选项
loop: true, // 循环模式选项
autoplay: true, //自动循环
// 如果需要分页器
pagination: {
el: “.swiper-pagination”,
clickable: true,
},
// 如果需要前进后退按钮
navigation: {
nextEl: “.swiper-button-next”,
prevEl: “.swiper-button-prev”,
},
// 如果需要滚动条
// scrollbar: {
// el: “.swiper-scrollbar”,
// },
});
}
};
4.carsouel共用
把首页当中的轮播图拆分为全局共用的组件
在comments下创建Carousel
main.js注册为全局组件
import TypeNav from ‘@/components/TypeNav’
// 引入轮播图全局组件
import Carousel from ‘@/components/Carousel’
//第一个参数是全局组件的名字
// 第二个参数,哪一个组件
Vue.component(TypeNav.name,TypeNav);
Vue.component(Carousel.name,Carousel);
修改floor下的index.vue
完整代码:
{{ list.name }}
{{ keyword }}
删掉主轮播图:
删除引入,已经全局引入
import Swiper from “swiper”;
watch: {
//监听bannerlist数据的变化
// 由空数组变为有数据
bannerList: {
immediate:true,
// 对象的写法
handler(newValue, oldValue) {
// 现在通过watch监听bannerlist属性值的变化
//如果执行handler方法,代表组件实例身上应该已经有了
// 当前的函数执行,只能保证bannerlist数据已经有了,没办法保证v-for已经执行结束
// v-for执行完毕才有结构【现在的watch无法保证】
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …ew Swiper(this.refs.mySwiper, {
// direction: “vertical”, // 垂直切换选项
loop: true, // 循环模式选项
autoplay: true, //自动循环
// 如果需要分页器
pagination: {
el: “.swiper-pagination”,
clickable: true,
},
// 如果需要前进后退按钮
navigation: {
nextEl: “.swiper-button-next”,
prevEl: “.swiper-button-prev”,
},
// 如果需要滚动条
// scrollbar: {
// el: “.swiper-scrollbar”,
// },
});
});
},
},
},
切记:以后再开发项目的时候,如果看见一个组件在很多地方都用的到,把它变成全局组件
注册一次,可以在任意地方使用
5.search模块开发
静态页面+静态组件拆分
发送请求(API)
vuex(三连环)
组件获取仓库数据,动态展示数据
api—》》index.js
// 上面的简化版本
export const reqCategoryList = ()=>requests({url: ‘/product/getBaseCategoryList’, method: ‘get’});
// 获取banner首页轮播图的接口
export const reqGetBannerList = ()=>mockrequests.get(‘/banner’);
// 获取floor列表数据
export const reqFloorList = ()=>mockrequests.get(‘/floors’)
// 获取搜索模块数据。 地址/api/list 请求的方式post 需要带参数
/*
参数
{
“category3Id”: “61”,
“categoryName”: “手机”,
“keyword”: “小米”,
“order”: “1:desc”,
“pageNo”: 1,
“pageSize”: 10,
“props”: [“1:1700-2799:价格”, “2:6.65-6.74英寸:屏幕尺寸”],
“trademark”: “4:小米”
}
*/
// 当前这个函数需要外接参数
// 当前的接口给服务器传递的参数至少是一个空对象
export const reqGetSearchInfo = (params)=>requests({url:‘/list’,method:“post”,data:params})
//测试
// import {reqCategoryList} from ‘@/api’
// reqCategoryList();
// import {reqGetSearchInfo} from ‘@/api’
// 至少是一个空对象{}
// console.log(reqGetSearchInfo({}));
export default {
name: “Search”,
components: {
SearchSelector,
},
mounted() {
// 先测试接口返回的数据格式
this.$store.dispatch(“getSearchList”, {});
},
computed: {
…mapState({
//与上面结构对应
goodsList:state=>state.search.searchList.goodsList
})
},
};
// 计算属性,为了简化仓库当中数据而生
const getters = {
// 当前参数state,当前仓库中的state并非大仓库中的state
goodsList(state){
// console.log(state);
// 这样书写是有问题的
return state.searchList.goodsList;
},
trademarkList(state){
return state.searchList.trademarkList;
},
attrsList(state){
return state.searchList.attrsList;
}
}
修改mapstate为mapgetters
// import { mapState } from “vuex”;
import SearchSelector from “./SearchSelector/SearchSelector”;
import {mapGetters} from “vuex”
export default {
name: “Search”,
components: {
SearchSelector,
},
mounted() {
// 先测试接口返回的数据格式
this.$store.dispatch(“getSearchList”, {});
},
computed: {
// …mapState({
// goodsList:state=>state.search.searchList.goodsList
// })
…mapGetters([‘goodsList’])
},
};
</sc
优化:
const getters = {
// 当前参数state,当前仓库中的state并非大仓库中的state
goodsList(state){
// console.log(state);
// 这样书写是有问题的
// 如果服务器的数据回来了,没有问题是一个数组
// 没有网络返回空数组
return state.searchList.goodsList || [];
},
trademarkList(state){
return state.searchList.trademarkList || [];
},
attrsList(state){
return state.searchList.attrsList || [];
}
}
6.ES6新语法
html
修改searchselect
遍历显示数据
- {{trademark.tmName}}
{{attrvalue}}