去哪儿项目总结

本文详细介绍了如何配置Vue.js项目,包括使用stylus预处理器、集成vue-awesome-swiper轮播插件、大图预览、解决3000ms延迟问题、字体图标处理、1px边框像素问题以及rem屏幕自适应。此外,还讲解了首页的头部、轮播图、九宫格图标和热销推荐的实现,城市列表页的搜索、城市数据展示及返回顶部功能,以及详情页的大图展示。
摘要由CSDN通过智能技术生成

目录

一.项目配置

二.首页

三.城市列表

四.详情页面


一.项目配置


创建vue-cli2项目
使用stylus预处理器,下载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'),
配置完后 重启

1.轮播插件

在github上搜索vue-awesome-swiper并下载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)

2.大图展示

下载:npm install vue-directive-image-previewer --save

// 大图
import VueDirectiveImagePreviewer from 'vue-directive-image-previewer'
import 'vue-directive-image-previewer/dist/assets/style.css'
Vue.use(VueDirectiveImagePreviewer, {
  zIndex: 9999,  //层级显示
  previewSize: 3 //三倍图
})

3.3000毫秒延迟

下载依赖 cnpm install fastclick --save

import fastClick from 'fastclick'

fastClick.attach(document.body)

4.字体图标问题

main中

import '../src/assets/styles/iconfont.css'

@font-face {
  font-family: "iconfont"; /* Project id 2787742 */
  src: url('./iconfont/iconfont.woff2?t=1654309550836') format('woff2'),
       url('./iconfont/iconfont.woff?t=1654309550836') format('woff'),
       url('./iconfont/iconfont.ttf?t=1654309550836') format('truetype');
}
 
.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
 
.icon-add:before {
  content: "\e664";
}
 
.icon-arrow-right:before {
  content: "\e665";
}
 
.icon-camera:before {
  content: "\e667";
}
 
.icon-fabulous:before {
  content: "\e66f";
}
 
.icon-arrow-left-bold:before {
  content: "\e685";
}
 
.icon-arrow-up-bold:before {
  content: "\e686";
}
 
.icon-arrow-down-bold:before {
  content: "\e687";
}
 
.icon-arrow-right-bold:before {
  content: "\e688";
}
 
 
.icon-gouwuchekong:before {
  content: "\e600";
}
 
.icon-fangdajing:before {
  content: "\e612";
}
 

5.1px边框像素问题

import '../src/assets/styles/border.css'

@charset "utf-8";
.border,
.border-top,
.border-right,
.border-bottom,
.border-left,
.border-topbottom,
.border-rightleft,
.border-topleft,
.border-rightbottom,
.border-topright,
.border-bottomleft {
    position: relative;
}
.border::before,
.border-top::before,
.border-right::before,
.border-bottom::before,
.border-left::before,
.border-topbottom::before,
.border-topbottom::after,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::before,
.border-topleft::after,
.border-rightbottom::before,
.border-rightbottom::after,
.border-topright::before,
.border-topright::after,
.border-bottomleft::before,
.border-bottomleft::after {
    content: "\0020";
    overflow: hidden;
    position: absolute;
}
/* border
 * 因,边框是由伪元素区域遮盖在父级
 * 故,子级若有交互,需要对子级设置
 * 定位 及 z轴
 */
.border::before {
    box-sizing: border-box;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    border: 1px solid #eaeaea;
    transform-origin: 0 0;
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
    left: 0;
    width: 100%;
    height: 1px;
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
    top: 0;
    width: 1px;
    height: 100%;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
    border-top: 1px solid #eaeaea;
    transform-origin: 0 0;
}
.border-right::before,
.border-rightbottom::before,
.border-rightleft::before,
.border-topright::after {
    border-right: 1px solid #eaeaea;
    transform-origin: 100% 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::before {
    border-bottom: 1px solid #eaeaea;
    transform-origin: 0 100%;
}
.border-left::before,
.border-topleft::after,
.border-rightleft::after,
.border-bottomleft::after {
    border-left: 1px solid #eaeaea;
    transform-origin: 0 0;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
    top: 0;
}
.border-right::before,
.border-rightleft::after,
.border-rightbottom::before,
.border-topright::after {
    right: 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::after {
    bottom: 0;
}
.border-left::before,
.border-rightleft::before,
.border-topleft::after,
.border-bottomleft::before {
    left: 0;
}
@media (max--moz-device-pixel-ratio: 1.49), (-webkit-max-device-pixel-ratio: 1.49), (max-device-pixel-ratio: 1.49), (max-resolution: 143dpi), (max-resolution: 1.49dppx) {
    /* 默认值,无需重置 */
}
@media (min--moz-device-pixel-ratio: 1.5) and (max--moz-device-pixel-ratio: 2.49), (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 2.49), (min-device-pixel-ratio: 1.5) and (max-device-pixel-ratio: 2.49), (min-resolution: 144dpi) and (max-resolution: 239dpi), (min-resolution: 1.5dppx) and (max-resolution: 2.49dppx) {
    .border::before {
        width: 200%;
        height: 200%;
        transform: scale(.5);
    }
    .border-top::before,
    .border-bottom::before,
    .border-topbottom::before,
    .border-topbottom::after,
    .border-topleft::before,
    .border-rightbottom::after,
    .border-topright::before,
    .border-bottomleft::before {
        transform: scaleY(.5);
    }
    .border-right::before,
    .border-left::before,
    .border-rightleft::before,
    .border-rightleft::after,
    .border-topleft::after,
    .border-rightbottom::before,
    .border-topright::after,
    .border-bottomleft::after {
        transform: scaleX(.5);
    }
}
@media (min--moz-device-pixel-ratio: 2.5), (-webkit-min-device-pixel-ratio: 2.5), (min-device-pixel-ratio: 2.5), (min-resolution: 240dpi), (min-resolution: 2.5dppx) {
    .border::before {
        width: 300%;
        height: 300%;
        transform: scale(.33333);
    }
    .border-top::before,
    .border-bottom::before,
    .border-topbottom::before,
    .border-topbottom::after,
    .border-topleft::before,
    .border-rightbottom::after,
    .border-topright::before,
    .border-bottomleft::before {
        transform: scaleY(.33333);
    }
    .border-right::before,
    .border-left::before,
    .border-rightleft::before,
    .border-rightleft::after,
    .border-topleft::after,
    .border-rightbottom::before,
    .border-topright::after,
    .border-bottomleft::after {
        transform: scaleX(.33333);
    }
}

6.rem屏幕自适应

1全局中:

// 使用js实训屏幕的自适应

// import '../src/utils/rem.js'

// // html根元素的字体大小(相对值)=(设备的可是宽度/原图大小)*倍数 750像素  原图的width宽度========rem原理
// function change(){ document.documentElement.style.fontSize=(document.documentElement.clientWidth||document.body.clientWidth)*100 / 750+ 'px'
 
// console.log("1rem="+(document.documentElement.clientWidth||document.body.clientWidth)*100/750+"px" );
// }
// change()
// // // 窗口大小改变事件
// // window.onresize=function(){
    // change()
// // }

2.app.vue中

<script>
function change(){ document.documentElement.style.fontSize=(document.documentElement.clientWidth||document.body.clientWidth)*100 / 750+ 'px'
 
console.log("1rem="+(document.documentElement.clientWidth||document.body.clientWidth)*100/750+"px" );
}
change()
</script>

二.首页


1.头部
将头部拆成组件,组件内容左侧icon图标,中间input框,右侧城市
使用弹性盒子实现头部布局,最右侧盒子加min-width属性,实现头部的自适应

2.轮播
将轮播拆成组件
在github上搜索vue-awesome-swiper并下载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)


代码实现:

<div class="banner">
        <swiper :options="swiperOption" ref="mySwiper">
            <swiper-slide v-for="item in swiperList" :key="item.id">
                <img class="swiper-img" :src="item.imgUrl" >
            </swiper-slide>
            <div class="swiper-pagination"  slot="pagination"></div>
        </swiper>
</div>


声明数组,获取数据,使用v-for循环遍历数据,实现轮播图
样式实现
样式穿透

.banner >>> .swiper-pagination-bullet-active
    background white

.banner
    overflow: hidden
    width: 100%
    height: 0
    padding-bottom: 26.67%
    .swiper-img
        width 100%;
        .swiper-pagination-bullet-active
            background:white !!!import 


3.九宫格图标
将九宫格图标拆成组件,实现布局
 

<div class="swiper">
       <div class="icons">
            <swiper :options="swiperOptions">
                <swiper-slide v-for="(page,index) in pages" :key="index">
                    <div class="icon" v-for="item in page" :key="item.id">
                        <div class="img">
                            <img class="content" :src="item.imgUrl" >
                        </div>          
                        <p class="desc">{{item.desc}}</p>
                    </div>
                </swiper-slide>
            </swiper>   
        </div>
  </div>


首先声明一个数组,用于获取数据,v-for循环遍历,但是每页只能显示八个,在计算属性中声明一个空数组,然后实现数组的当前下标应该展示在轮播图的第几页,一页八个图标,向下取整Math.floor(8/8)向下取整为1

 const page = Math.floor(index / 8)
                if (!pages[page]) {
                pages[page] = []
                }
                pages[page].push(item)

4.热销推荐,周末去哪
通过获取数据,v-for循环遍历到页面中

三.城市列表


点击首页右上角城市,跳转到城市列表页
1.搜索
给inp框绑定input事件,v-model双向数据绑定搜索的关键字,获取到数据,对关键字的首字母和名字进行模糊搜索,如果有则添加渲染出来
2.城市数据列表
通过获取数据,将热门城市渲染出来,在城市列表中,拿到数据,ABCD等是通过拿到index下标来获取到的,然后获取到详细城市,渲染出来
3.点击右侧首字母,拿到数据
将右侧首字母固定定位到页面中,给首字母添加点击事件,并获取到当前元素距离顶部的距离,如果当前元素的顶部距离和

search(){
            var arr=[]
            for(var i in this.list){
                this.list[i].forEach((item)=>{
                    if(item.spell.indexOf(this.keyword)>-1 ||item.name.indexOf(this.keyword)>-1){
                        arr.push(item)
                    }
                })
            }
            if(this.keyword==''){
                this.data=[]
            }else{
                this.data=arr
            }
        }


4.返回顶部
写一个返回顶部的盒子,点击返回顶部,让滚动距离为0 :scroll(0, 0);


四.详情页面

1.大图

先获取数据通过v-for循环遍历将图片展示出来,将大图拆分成组件,

挂载到详情页中,定义一个flag为false,给图片设置点击事件,flag值取反,大图v-show绑定flag

传递一个事件并把flag传递过去,在大图组件中通过props来接收flag,通过$emit接收传递过来的事件,实现大图展示

样式实现:

.banners {
    width: 100%;
    height: 100%;
    background: #000;
    z-index: 9999;
    position: fixed;
    top: 0;
    left: 0;
    display: flex;
    justify-content: center;
    align-items: center;

    .swiper-img {
        width: 100%;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值