准备工作
index.html中添加视口 发大 缩小无效
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
在assets/styles下 引入文件 分别是 全局样式表 以及iconfont 还有解决border1边框的问题 将他们分别 在main.js中引入
// 解决1px边框像素问题
import './assets/styles/border.css';
// 统一浏览器显示样式
import './assets/styles/reset.css'
// 引入rem
import './utils/rem'
// 引入iconfont
import './assets/styles/iconfont.css'
解决300毫秒点击延迟问题
cnpm install fastclick --save
在main.js中引入
import fastClick from 'fastclick'
fastClick.attach(document.body)
使用stylus css预处理器
下载插件
cnpm install stylus --save -dev
cnpm install stylus-loader@3.0.2 --save -dev
在build/webpack.base.conf.js中修改在’@': resolve(‘src’),后添加一条
'styles': resolve('src/assets/styles'),
分为三个部分 首页 详情 搜索城市
首页
使用轮播图 时 使用插件
cnpm install vue-awesome-swiper@2.6.7 --save
在main.js中引入
import VueAwesomeSwiper from 'vue-awesome-swiper'
import "swiper/dist/css/swiper.css"
Vue.use(VueAwesomeSwiper)
使用的方法
<swiper :options="swiperOption">
<!-- slides -->
<swiper-slide>
<img class="swiper-img" src="http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/201912/0b26e9760c2673c63c05e1efce1275ea.jpg_750x200_495c0a72.jpg" >
</swiper-slide>
<swiper-slide>
<img class="swiper-img" src="http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/201912/0b26e9760c2673c63c05e1efce1275ea.jpg_750x200_495c0a72.jpg" >
</swiper-slide>
<!-- Optional controls -->
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
<div>test</div>
九宫格也利用到 swiper
<div class="icons">
<swiper >
<swiper-slide v-for="(page,index) in pages" :key="index">
<div class="icon" v-for="item in page" :key="item.id">
<div class="icon-img">
<img class="icon-img-content" :src="item.imgUrl" >
</div>
<p class="icon-desc">{{item.desc}}</p>
</div>
</swiper-slide>
</swiper>
</div>
//展示了8个 发现丢失了2个 要利用到 computed 之后重新循环页面的数组
computed:{
pages () {
const pages = []
this.iconList.forEach((item, index) => {
//page当前下标的数据应该展示在轮播图的第几页 index是3 下标是2 Math.floor(2/8)向下取整为0 Math.floor(8/8)向下取整为1
const page = Math.floor(index / 8)
if (!pages[page]) {
pages[page] = []
}
pages[page].push(item)
})
return pages
}
}
.icons >>> .swiper-container
height : 0
padding-bottom: 50%
.icon
position: relative
overflow: hidden
float: left
width: 25%
height: 0
padding-bottom: 25%
.icon-img
position: absolute
top: 0
left: 0
right: 0
bottom: .44rem
box-sizing: border-box
padding: .05rem
.icon-img-content
display: block
margin: 0 auto
height: 100%
.icon-desc
position: absolute
left: 0
right: 0
bottom: 0
height: .44rem
line-height: .44rem
text-align: center
color:#333
首页的剩下的都是 请求数据之后渲染
详情页
在首页的查看详情一个点击事件然后传id 在详情页接收id
之后请求数据 然后通过父传子渲染数据在相对的地方
created() {
this.$axios
.get("/static/mock/detail.json", {
params: {
id: this.$route.params.id,
},
})
.then((res) => {
console.log(res);
this.sightName = res.data.data.sightName;
this.bannerImg = res.data.data.bannerImg;
this.gallaryImgs = res.data.data.gallaryImgs;
this.list = res.data.data.categoryList;
});
},
头部的内容
//在header组件中
data () {
return {
showAbs: true,
}
},
//判断 先显示 滚动到一定区域 class="header-fixed"显示出来
class="header-abs"
v-show="showAbs">
class="header-fixed"
v-show="!showAbs"
methods : {
handleScroll(){
//document.documentElement.scrollTop pc端使用 document.body.scrollTop 移动端使用
console.log(document.body.scrollTop)
const top = document.body.scrollTop
if (top > 60) {
this.showAbs = false
} else {
this.showAbs = true
}
},
},
<div class="header-fixed" v-show="!showAbs" :style="opacityStyle">
data () {
return {
showAbs: true,
opacityStyle: {
opacity: 0
}
}
},
//当页面滚动的时候 在60-140区间有个渐隐渐显的过渡效果
if (top > 60) {
let opacity = top / 140
opacity = opacity > 1 ? 1 : opacity
this.opacityStyle = { opacity }
this.showAbs = false
} else {
this.showAbs = true
}
//父传子
<DetailList :list = "list"></DetailList>
//在list组件中
<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>
</div>
.item-title-icon
position: relative
left: .06rem
top: .06rem
display: inline-block
width: .36rem
height: .36rem
background: url(http://s.qunarzz.com/piao/image/touch/sight/detail.png) 0 -.45rem no-repeat
margin-right: .1rem
background-size: .4rem 3rem
.item-title
line-height: .8rem
font-size: .32rem
padding: 0 .2rem
城市
获取数据 再通过父传子的方法 在对应的对应的地方 渲染数据
methods: {
getCityInfo() {
this.$axios.get("static/mock/city.json").then(this.handleGetCityInfoSucc);
},
handleGetCityInfoSucc(res) {
res = res.data;
if (res.ret && res.data) {
const data = res.data;
this.cities = data.cities;
this.hotCities = data.hotCities;
}
},
handleLetterChange(letter) {
this.letter = letter;
}
},
mounted() {
this.getCityInfo();
},
搜索的功能
利用关键字来进行搜索
搜索出来的内容进行滚动
代码如下
<div class="search">
<div class="search">
<input v-model="keyword" class="search-input" type="text" placeholder="输入城市名或拼音" />
</div>
<div class="search-content" ref="search" v-show="keyword">
<ul>
<li class="search-item border-bottom" v-for="item of list" :key="item.id" @click="handleCityClick(item.name)" >
{{ item.name }}
</li>
<li class="search-item border-bottom" v-show="hasNoData">
没有找到匹配数据
</li>
</ul>
</div>
</div>
methods: {
handleCityClick(city) {
this.$store.commit("changeCityValue", city);
this.$router.push("/")
}
},
watch: {
keyword() {
//函数节流
if (this.timer) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
const result = [];
for (let i in this.cities) {
this.cities[i].forEach(value => {
//如果我们能从name spell当中搜索到 我们就把它添加到result当中
if (
value.spell.indexOf(this.keyword) > -1 ||
value.name.indexOf(this.keyword) > -1
) {
result.push(value);
}
});
}
this.list = result;
}, 100);
}
},
mounted() {
//搜索出来内容的滚动
this.scroll = new Bscroll(this.$refs.search);
},
computed: {
hasNoData() {
return !this.list.length;
}
}
在城市数据的页面中 给每一个城市一个点击事件 赋给首页的 头部右边
handleCityClick(city) {
this.$store.commit("changeCityValue", city);
this.$router.push("/");
}
字母联动
给字母列表标签三个事件
@touchstart="handleTouchStart(item)"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
代码如下
handleTouchStart() {
this.touchStatus = true;
},
handleTouchMove(e) {
console.log(e);
if (this.touchStatus) {
//A字符距离顶部的距离
const startY = this.$refs["A"][0].offsetTop;
console.log(startY);
if (this.timer) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
const touchY = e.touches[0].clientY - 79;
console.log(touchY);
// index触控位置的下标 20量为字符的高度
const index = Math.floor((touchY - this.startY) / 20);
console.log(index);
if (index >= 0 && index < this.letters.length) {
console.log(this.letters[index]);
this.$emit("change", this.letters[index]);
}
}, 16);
}
},
handleTouchEnd() {
this.touchStatus = false;
},
},
updated() {
this.startY = this.$refs["A"][0].offsetTop;
},