for="item of hot" :key="item.id" @click="handleCityClick(item.name)">
methods: {
handleCityClick (city) {
this.$store.dispatch('changeCity', city)
alert(city)
}
},
/src/store/index.js
export default new Vuex.Store({
state: {
city: '南京'
},
actions: {
changeCity (ctx, city) {
console.log(city)
ctx.commit('toChangeCity', city)
}
},
mutations: {
toChangeCity (state, city) {
state.city = city
}
}
})
vuex还支持字段映射
import { mapState } from 'vuex'
computed: {
...mapState(['city'])
}
or
import { mapMutations } from 'vuex'
handleCityClick (city) {
...
this.toChangeCity(city)
},
...mapMutations(['toChangeCity'])
通过js来打开路由页面
this.$router.push('/')
使用keep-alive优化性能
创建分支 city-keepalive-14
修改App.vue
此时又需要处理数据动态改变时页面需要重新请求数据,例如当前城市改变时,需求加载当前城市的信息
使用keep-alive后,mounted周期函数只会被调用一次,但是activated周期函数会每次都会被调用。所以...
在Home.vue中使用vuex,并在computed计算属性中映射一个city对象,同时定义一个属性lastCity标记上一个城市。
然后在activated周期函数中判断当前选择城市和上一个城市是否相等,不相等则将当前城市作为参数重新请求一次ajax。
import { mapState } from 'vuex'
data () {
return {
lastCity: '',
}
},
computed: {
...mapState(['city'])
},
methods: {
getHomeInfo () {
axios.get('/api/index.json?city=' + this.city)
.then(this.getHomeInfoSucc)
}
},
mounted () {
this.lastCity = this.city
console.log('mounted')
this.getHomeInfo()
},
activated () {
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
}
console.log('activated')
}
另外也可以使用来排除一部分页面,使其不使用缓存,例如城市详情页,修改App.vue
"Detail">
特别注意: exclude会导致页面中不再回调activated (), 但是会调用created (),所以一些需要重新初始化的方法或者属性需要在created () 调用。
例如:src/pages/detail/components/Header.vue
七、城市详情页面
Banner
创建分支detail-banner-15
将li标签换成router-link:
解决router-link默认会改成标签颜色问题
注意需要同时在router-link标签上增加tag属性,指定需要渲染成li标签,同时指定to属性。
"li" v-for="item of list" :key="item.id" :to="'/detail/' + item.id">
...
注册动态路由,获取路由参数
{
path: '/detail/:id',
name: 'Detail',
component: Detail
}
参考 http:
创建DetailBanner组件
渐变效果
background-image: ar-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8))
共用组件画廊
swiper 中文网
http:
代码见 /src/common/gallary/Gallary.vue
Header渐隐渐显效果
创建分支 detail-header-16
特别注意:获取滚动条滚动的垂直距离scrollTop的兼容问题
通过绑定:style的opacity属性来动态改变透明度
"div" to="/" class="header-abs"
v-show="showAbs" :style="opacityAbsStyle">
class="iconfont back-icon-back">
class="header-fixed" v-show="!showAbs" :style="opacityFixedStyle">
"/">
class="iconfont header-fixed-back">
景点详情
data () {
return {
showAbs: true,
opacityAbsStyle: {
opacity: 1
},
opacityFixedStyle: {
opacity: 0
}
}
},
methods: {
handleScroll () {
const scrollTop = (window.parent.document.documentElement.scrollTop || window.parent.document.body.scrollTop)
|| (document.body.scrollTop + document.documentElement.scrollTop)
|| (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0)
if (top > 40) {
let opacity = top / 130
opacity = opacity > 1 ? 1 : opacity
this.opacityFixedStyle = {
opacity
}
this.showAbs = false
} else {
this.showAbs = true
let opacity = top / 40
opacity = opacity > 1 ? 1 : opacity
this.opacityAbsStyle = {
opacity: (1 - opacity)
}
}
}
},
activated () {
window.addEventListener('scroll', this.handleScroll)
}
对全局事件解绑
处理上一节window.addEventListener
activated () {
window.addEventListener('scroll', this.handleScroll)
}
解绑事件:
deactivated () {
window.removeEventListener('scroll', this.handleScroll)
}
使用递归组件实现详情页列表
创建分支 detail-list-17
json数据
list: [{
title: '成人票',
children: [{
title: '成人三管联票',
children: [{
title: '成人三管联票 - 某一连锁店销售'
}]
}, {
title: '成人五管联票'
}]
}, {
title: '学生票'
}, {
title: '儿童票'
}, {
title: '特惠票'
}]
递归调用detail-list组件(List.vue)
class="item" v-for="(item,index) of list" :key="index">
class="item-title border-bottom">
class="item-title-icon">
{{item.title}}
if="item.children" class="item-children">
"item.children">
ajax获取数据
创建分支 detail-ajax-18
注意一下,使用属性绑定时加上冒号
![H5-Vue2.5开发去哪儿网App_从零基础入门到实战项目-开发笔记 H5-Vue2.5开发去哪儿网App_从零基础入门到实战项目-开发笔记]()
class="banner-img" :src="bannerImg">
显示文本,使用{{属性xxx}}即可
class="banner-title">{{this.sightName}}
使用计算属性控制是否显示一个列表部分(避免按空数组初始化,导致有数据变化时的当前显示的索引为列表的最后一个)
"swiperOption" v-if="isShowGallary">
···
computed: {
isShowGallary () {
return this.imgs.length > 0
}
}
路由行为
打开新页面显示到顶部,不能受到上一页上下滚动的距离影响
https:
修改router/index.js
export default new Router({
routes: [{
path: '/',
name: 'HelloWorld',
component: Home
}],
scrollBehavior: function (to, from, savedPosition) {
return savedPosition || { x: 0, y: 0 }
}
})
更多关于路由介绍
https:
在项目中使用基本动画
创建分支 detail-animation-19
代码在src/common/fade/FadeAnimation.vue (淡入淡出效果)
export default {
name: 'FadeAnimation'
}
应用在在src/pages/detail/components/Banner.vue中
"bannerImgs" v-show="showGallary">
开发结束,非常感谢您阅读此文!
个人网站 tech.jiangjiesheng.cn
QQ:596957738
微信:596957738
EMail: dev@jiangjiesheng.com