Vue2.5仿去哪儿app 实战项目笔记
利用vuex实现跨页面数据共享 公共画廊组件 导航栏的渐变出现
利用vuex实现跨页面数据共享
要同时改变两个页面的数据,但city.vue和home.vue之间没有一个共同的父级组件,所以无法通过类似前面的父级组件进行数据中转。所以可以用vuex来进行数据管理。
vuex就是通过把所有的公用数据放到一个公共的数据空间去存储,某一个组件改变了这个公用数据,其他组件也能感知到并动态变化。
其中:
- state: 存放所有公用数据
- Actions: 异步处理或者批量的同步操作
- Mutation: 对state进行最后的修改
整体来说,就是components调用acions,actions调用mutations,mutations改变state.
使用vuex
1、创建store文件夹和index.js
//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '上海'
//这个数据分别被home.vue中的header组件,
//city.vue中的list组件所用
}
})
2、组件通过调用$store调用数据
在建立store后,即city数据由前端存储和改变,代替掉原来通过ajax返回后端数据。
要使所有组件都能用公用数据,需在main.js中声明store。
这样,当在city.vue中改变当前城市,需要使得home.vue中的当前城市也一起动态变化。
<!--在list.vue和header.vue调用公共数据city-->
<div class="header-right">
{ {this.$store.state.city} }
<!--调用store中的公共数据-->
<span class="iconfont icon-down"></span>
</div>
3、在组件中改变公共数据
在city页面中的list组件和search组件,通过点击实现当前城市的切换,用到vuex中的actions
changeCity (city) {
//this.$store.dispatch('changeCity', city)
this.$store.commit('changeCity', city)
this.$router.push('./')
//修改完当前城市后,自动跳转回主页
}
//store/index.js
/**可略过Actions,组件直接去调用mutations,修改数据。
action: {
changeCity(ctx, city) {
ctx.commit('changeCity',city)
}
},
**/
mutations: {
changeCity (state, city) {
state.city = city
}
}
})
公共画廊组件
在详情页,需要用到一个公共画廊组件。当点击详情页面中的图片时,画廊会跳出并覆盖整个页面,通过轮播图模式可左右滑动。并且底部有pagination,显示当前页面位置。
其中画廊中的图片,通过父子组件传值获取。
//gallary.vue
//gallary.vue作为banner.vue的组件,与其实父子组件的关系
props: {
imgs: {
type: Array,
default () {
return []
}
}//从banner.vue获取数据
},
data () {
return {
swiperOption: {
pagination: '.swiper-pagination',
paginationType: 'fraction',
observeParents: true,
observer: true
}
}
},
methods: {
turnGallary () {
this.$emit('close')
//在gallary.vue中向外(banner.vue)触发事件,在banner.vue中处理
}
}
顶部导航栏的渐变出现
详情页首页没有导航栏,下拉详情页时,当下拉到一定像素,顶部渐变出现导航栏。所以header.vue中包括两个结构,用过v-show
指令控制其交替出现。
<div>
<router-link rag="div" to="/" class="header-abs" v-show="showABS">
<span class="iconfont"></span>
</router-link>
<div class="header-fixed" v-show="!showABS" :style="opacityStyle">
景点详情
<router-link to='/'>
<span class="iconfont"></span>
</router-link>
</div>
</div>
data () {
return {
showABS: true,
opacityStyle: {
opacity: 0
//控制
}
}
},
methods: {
handleScroll () {
const top = document.documentElement.scrollTop
if (top > 60) {
//当下拉60像素后,顶部渐变出现导航栏
let opacity = top / 140
opacity = opacity > 1 ? 1 : opacity
this.opacityStyle = { opacity }
this.showABS = false
} else {
this.showABS = true
}
}
},
mounted () {
window.addEventListener('scroll', this.handleScroll)
//获取滚动条
}