1 banner
1.1 动态路由
- 给首页的 recommend 标签包裹 router-link
- vue 把 router-link 渲染 成 a 标签,a 标签的样式需要处理(变蓝,下划线)。
- vue 把 router-link 替换成 li 标签,a 标签样式不用处理。
要加上属性
"tag=li"
- router->index.js加上动态路由
1.2 细节处理
- 渐变色
background-image: linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8))
- inconfont 每下载一次,代码会变?要及时更新
1.3 画廊 组件拆分 轮播组件
bulid->webpack.base.config.js,添加一个别名 alias common。
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
......
'common': resolve('src/common')
}
},
banner 组件中,import Gallary子组件
<template>
<div>
<div class="banner" @click="handleBannerClick">
<common-gallary :imgs="imgUrl" v-show="showGallary" @close="handleGallaryClose"></common-gallary>
</div>
</div>
</template>
<script>
import CommonGallary from 'common/gallary/Gallary'
export default {
name: 'DetailBanner',
data () {
return {
imgUrl: ['http://img1.qunarzz.com/sight/p0/1606/d1/d1cd47a17354fc0690.img.jpg_350x240_03b11936.jpg', 'http://img1.qunarzz.com/sight/p0/1606/10/10dfd9bb220c7cc590.img.jpg_350x240_2cccce17.jpg'],
showGallary: false
}
},
components: {
CommonGallary
},
methods: {
handleBannerClick () {
this.showGallary = true
},
handleGallaryClose () {
this.showGallary = false
}
}
}
</script>
编写 Gallary 组件代码,src->common->gallary->Gallary.vue,轮播组件参考开发笔记(二)。
<template>
<div class="container" @click="handleGallaryClick">
<div class="wrapper">
<swiper :options="swiperOptions">
<swiper-slide v-for="(item,index) in imgs" :key="index">//列表遍历
<img class="swiper-img" :src="item">
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
</div>
</div>
</template>
<script>
export default {
name: 'CommonGallary',
props: {
imgs: Array
},
data () {
return {
swiperOptions: {
pagination: '.swiper-pagination',
paginationType: 'fraction',
observer: true,
observeParents: true
}
}
},
methods: {
handleGallaryClick () {
this.$emit('close') //向外触发close事件,点击后关闭当前组件 设置为不可见
}
}
}
</script>
1.4 header 渐隐渐现的效果
1.4.1 JS 更改 DOM 元素的内联样式 opacity
JS 获取页面 scroll 的距离,通过距离和 opacity 的关系,计算opacity。
<template>
<div>
<router-link tag="div" to="/" class="header-abs" v-show="showAbs">
<div class="iconfont header-abs-back"></div>
</router-link>
<div class="header-fixed" v-show="!showAbs" :style="OpacityStyle">
<router-link to="/">
<div class="iconfont header-fixed-back"></div>
</router-link>
景点详情
</div>
</div>
</template>
<script>
export default {
name: 'DetailHeader',
data () {
return {
showAbs: true,
OpacityStyle: {
opacity: 0
}
}
},
methods: {
handleScroll () {
const top = document.documentElement.scrollTop
if (top > 60) {
let opacity = top / 140
opacity = opacity > 1 ? 1 : opacity
this.OpacityStyle = { opacity }
this.showAbs = false
} else {
this.showAbs = true
}
}
},
activated () {
window.addEventListener('scroll', this.handleScroll)
}
}
</script>
1.4.2 对全局事件的解绑 (!import
)
上述代码
activated () {
window.addEventListener('scroll', this.handleScroll)
}
带来的问题!
事件没有绑定到 header 组件中,而是绑定到了 window 上,全局都有效果,对其他组件也产生了效果
deactivated
页面即将被隐藏,即将被替换成新的页面的时候,执行该钩子函数。
解决:解绑
deactivated () {
window.removeEventListener('scroll', this.handleScroll)
}
1.5 使用递归组件实现详情列表页
面对这样的数据如何展示?
list: [{
title: '成人票',
children: [{
title: '成人三馆联票',
children: [{
title: '成人三馆联票 - 某一连锁店销售'
}]
}, {
title: '成人五馆联票'
}]
}, {
title: '学生票'
}, {
title: '儿童票'
}, {
title: '特惠票'
}]
通过递归组件的形式:
<template>
<div>
<div class="item" v-for="(item,index) of list" :key="index">
<div class="item-title border-bottom">
<span class="item-title-icon"></span>
{{item.title}}
</div>
<div class="item-children" v-if="item.children"><!--如果当前item还有孩子就展示该div,并遍历当前item的孩子-->
<detail-list :list="item.children"></detail-list> <!--🎈🎈递归组件-->
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DetailList',//给组件命名可以在父组件中直接使用,也可以在需要递归组件时直接使用
props: {
list: Array
}
}
2 Ajax 请求数据
2.1 动态路由(接上步骤)
每次 ajax 请求希望把 id 带给后端,访问对应 id 的数据。id是动态路由的参数,可以通过this.$route.params.id
获取。
<template>
<div>
</div>
</template>
<script>
import axios from 'axios'//🎈
export default {
name: 'Detail',
components: {
},
methods: {
getDetailInfo () {
axios.get('/api/detail.json?id=' + this.$route.params.id)//🎈相当于下面的代码
}
},
mounted () {
this.getDetailInfo()//🎈
}
}
</script>
上述功能代码写好,发现只有在首次进 detail 页面的时候才会发 ajax 请求。
原因是:
detail 通过 keep-ali 做了缓存 ,所以 mounted 只会执行一次。
解决:若想每一次重新进页面的时候都重新发一次 ajax 请求, 那就要
- 法一:参考 Home.vue,配合使用 activated 生命周期钩子
- 法二:在 keep-alive 的时候 exclude 掉 Detail 页面,Detail 页面便不会被缓存了。每次进页面 mounted 都会被执行,App.vue:
<keep-alive exclude="Detail"> <router-view/> </keep-alive>
- 注:当 exclude 某个页面后,这个页面及其单页面子组件中
activated
钩子函数也要换回mounted
- 注:当 exclude 某个页面后,这个页面及其单页面子组件中
2.2 Ajax 请求数据全流程
参见 Home.vue 案例 ajax
2.3 滚动行为 每次路由切换到新的页面 scroll 始终都在顶部
滚动行为:
代码的意思:每次进行路由切换的时候,让显示的页面x初始为0,y初始也为0,始终回到最顶部。加到 router->index.js 中。
scrollBehavior (to, from, savedPosition) {
return { x: 0, y: 0 }
}
2.4 思考: 给组件的命名 name 什么时候能用到?
- 在父组件中 import 子组件,并在 template 中直接用标签展示子组件。
- 递归组件。
- 设置了 keep-alive 后,想取消对某个页面的缓存的时候,用到
exclude = XXX
。 - 便于在 Chrome 中使用 vue 调试工具的时候 看的更直观