课程章节: 项目实战 - 旅游网站详情页面开发
主讲老师: Dell
课程内容:
今天学习的内容包括:
路由之前使用方式:用router-link包裹在标签最外面,相当于a标签,所以样式会变掉。
改进方式:
将需要包裹渲染的标签直接用router-link替代,tag里写上标签名即可。
例如:
需要包裹<li>
标签,将li标签改成<li tag="li"></li>
即可
滚轮事件
1,window.addEventListener(‘scroll’, (e)=>{})
2,用document.documentElement.scrollTop来获取滚动条滚了多长的距离
课程收获:
9.1 心得:
router-link变色:改css/直接把li换router-link,属性tag=‘li’
动态绑定:
:to="'/detail/' + item.id"
路由设置:
path: '/detail/:id'
动态路由:后面带参数,在变量id中
防止页面抖动:
.banner
overflow: hidden
height: 0
padding-bottom: 55%
渐变:
background-image: linear-gradient(top, rgba(0,0,0,0),
rgba(0,0,0,0.8))
监听路由参数变化重新获取数据
watch: {
'$route': function (to, from) {
if (to.params.id != from.params.id) {
// 加载数据
this.getProducts()
}
}
}
router-link :to="" router跳转to的值为表达式时会报错,使用v-if来解决
路径异步获取时导致的to报错问题
因为先渲染的页面再获取到url的值
9.2 心得:
全局共用组件src/common
画廊:src/common/gallary/Gallary.vue
设置common路径:webpack config
‘common’: resolve(‘src/common’)
在Banner中引入
swiper配置项:搜索swiper
swiperOptions: {
pagination: '.swiper-pagination',
paginationType: 'fraction'
}
显示pagination:
.container >>> .swiper-container
overflow: inherit
轮播宽度计算问题:swiper插件监听到自身元素或父级元素DOM发生变化自动自我刷新一次
observeParents:true
observer: true
外部接收数据:
props: {
imgs: {
type: Array,
default () {
return ['imgUrl1','imgUrl2']
}
}
}
关闭画廊:
画廊点击@click="handleGallaryClick"=>向上触发close=>
banner调用,common-gallery@close="handleGallaryClose"
swiper插件只要监听到该swiper元素或者父级元素发生DOM结构改变时,会自动的自我刷新一次,可以解决swiper宽度计算的问题
data() {
return {
swiperOptions: {
pagination: '.swiper-pagination',
paginationType: 'fraction',
observeParents: true,
observer: true
}
}
}
9.3 心得:
实现Header渐隐渐显效果
-
创建分支:detail-header
git pull
git checkout detail-header -
在src/pages/details/components/中创建Header.vue,添加必要的代码。
-
在Detail.vue中引入Header.vue组件
-
编写Header.vue代码
<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
}
}
},
// i因为用了keepalive,所以页面只要展示,activated钩子函数就会执行
activated () {
window.addEventListener('scroll', this.handlScroll)
},
methods: {
handlScroll () {
// 获取窗口滚动的距离
const top = document.documentElement.scrollTop
// 实现渐隐渐显效果
if (top > 60) {
let opacity = top / 140
opacity = opacity > 1 ? 1 : opacity
this.opacityStyle = {
opacity: opacity
}
this.showAbs = false
} else {
this.showAbs = true
}
}
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.header-abs
position: absolute
left: .2rem
top: .2rem
width: .8rem
height: .8rem
line-height: .8rem
text-align: center
border-radius: .4rem
background: rgba(0, 0, 0, .8)
.header-abs-back
color: #fff
font-size: .4rem
.header-fixed
position: fixed
top: 0
left: 0
right: 0
height: .86rem
line-height: .86rem
text-align: center
color: #fff
background: $bgColor
font-sieze: .32rem
.header-fixed-back
position: absolute
top: 0
left: 0
text-align: center
font-size: .4rem
width: .64rem
color: #fff
</style>
- 提交到线上
git add .
git commit -m 'header-animation'
git push
git checkout master
git merge detail-header
git push
9.5 心得:
1、全局事件解绑
window全局事件,无论哪个页面都会监听这个事件,会影响到其它页面,所以要解绑。
2、在有keep-alive时会出现两个生命周期函数: activated和deactivated
activated 在页面被显示时执行
deactivated 在页面即将被隐藏或页面被替换的时候执行
3、所以为了使全局事件不影响其它页面,我们在activated中绑定(addEventListener),然后在deactivated中解绑(removeEventListener)
deactivated 页面将被隐藏/被替换成新的页面时会执行
只在详情页面执行,其他页面解绑
deactivated () {
window.removeEventListener('scroll', this.handleScroll)}
9.6 心得:
递归组件:在组件的自身调用组件的自身假设一个组件要用自己时通过自己名字来使用自己
<div v-if="item.children" class="item.children">
<detail-list :list="item.children"></detail-list>
</div>
把children当做list再传给自己
组件中name属性的作用
递归组件时使用
keepalive 取消缓存在exclude='组件name’里使用
vue devtool调试工具中显示项目结构的名字
注意:组件里的name属性和在其他组件里import时的名字无关,比如detail页面的banner组件name为DetailBanner,在detail组件里使用时,可以通过import banner2 from './compnents/Banner,然后使用banner2。
9.7 心得:
动态获取路由id
mounted() {
this.getDetailInfo()
}
methods: {
getDetailInfo() {
axios.get('/api/detail.json',{
params: {
id: this.$router.params.id
}
}).then(this.handleGetDataSucc)
},
handleGetDataSucc(res) {
res = res.data
if(res.ret && res.data) {
const data = res.data
this.sightName = data.sightName
}
}
}
不被缓存,每次进入页面的时候mounted钩子都会被重新执行
每次做路由切换时,都让先进入显示的页面的xy轴初始位置都为0
scrollBehavior (to, from, savedPosition) {
return {x: 0, y: 0}
}
9.10 心得:
轮播渐隐渐显
common组件中,/fade/FadeAnimation.vue
使用<transition>
包裹动画效果
内部使用一个slot插槽
.v-enter, .v-leave-to
opacity: 0
.v-enter-active, v-leave-active
transition: opacity .5s