‘去哪儿‘项目总结

7 篇文章 0 订阅
5 篇文章 0 订阅

准备工作
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;
  },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值