【VUE】-使用Vue高仿最新版去哪儿网 涉及诸多常用知识点总结

前言:花了近两个月时间研究ES6语法和VUE,然后手写了去哪儿网最新版的页面,至今也算是初出茅庐,为了避免遗忘,赶紧在此总结学到的所有比较重要常用的知识点.

项目地址:https://github.com/laohanjianshen/qunar

部分截图:

更多的细节图就不一一贴了,整个项目也几乎涉及到了VUE中常用的各种知识点,入门是绝对够了.


目录

1.同步组件&异步组件

2.icon-font的使用和flex布局

3.使用Vue-Awesome-Swiper实现各种轮播效果

4.一些小技巧及computed实现分页

5.使用axios向服务器发送请求获取数据

6.使用better-scroll插件实现酷炫的滚动效果

7.使用watch和scrollToElement实现点击字母跳转至对应的DOM元素

8.使用handleTouch实现在字母A~Z上滑动时城市列表也按字母进行联动.

9.声明式路由和编程式路由

10.使用VueX实现组件间传值

11.利用全局事件监听实现头部动态隐藏/显示效果

12.使用递归组件

13.使用插槽创建公用的动画组件(渐进/渐退效果)

14.使用本机IP可以访问项目设置

15.解决部分手机浏览器不支持高级es的语法的bug,比如es5,es6的语法.


1.同步组件&异步组件

同步组件:在页面加载的同时组件不论是否被用到,都会预先加载.

异步组件:在页面加载时做到按需加载,如果该组件尚未被用到,就不会请求跟该组件关联的内容.

不难看出,前者的优势是首次加载的时候慢,但可以减少发送请求的次数,后者是首次加载页面快,但增加了发送请求的次数,两者各有优劣,在组件不够大的情况下,建议使用同步组件,减少发送请求的次数,从而可以提高性能,在组件比较庞大时(起码大于1MB),可以采用异步组件的方式,提高页面渲染速度.

#同步组件引入方式:
import Detail from '@/pages/home/Home'

{
      path: '/',
      name: 'Home',
      component: Home
}


#异步组件引入方式:
{
      path: '/city',
      name: 'City',
      component: () => import('@/pages/city/City')
}

2.icon-font的使用和flex布局

在首页搜索框这里可以看到诸如箭头,放大镜等图标,这些小图标如果使用图片的话,多个页面加起来会增加不少的数据量,增加服务器压力,但如果使用icon-font就可以轻松解决,用起来也十分方便,我在前面的vue基础篇有提到过详细用法,这里不赘述了.

首页头部搜索框这块采用了flex布局,左侧的返回,中间的搜索,右侧的城市分别用boxA,boxB,boxC来布局,让Afloat:left,让Cfloat:right,然后让中间的boxBflex:auto或者flex:正数 即可让它刚好撑开处在中间.

3.使用Vue-Awesome-Swiper实现各种轮播效果

轮播图在各种开发中出现的频率应该说是极高了,重复造轮子没必要,而且造的还不如别人好,这里推荐一款非常好用的轮播图插件,相关文档也非常全.

GitHub地址:https://github.com/surmon-china/vue-awesome-swiper

#安装
npm install vue-awesome-swiper --save

#安装好了在main.js中引入
import VueAwesomeSwiper from 'vue-awesome-swiper'
Vue.use(VueAwesomeSwiper)

引入后把你需要轮播的内容放在<swiper-slide>标签内即可

更多细节我也不赘述了,这个插件有极其全面的中英文文档,可以参考.

4.一些小技巧及computed实现分页

 首页整个Icons区域的布局用了点小技巧来实现图片的等比例缩放:

  .icons
    height 0
    padding-bottom 50%
    overflow hidden

将height设为0,然后用padding-bottom来指定高度为父元素宽度的百分比,这里因为icons的父元素是body,也就是页面宽度的50%,高度会随着手机屏幕的宽度自动缩放,从而实现了等比例显示.

Tip:padding-bottom 如果用%来表示的话,计算是根据父元素的width的值进行计算的.

Icon下面的文字长度如果超标了,我们希望用符号"..."来显示多出的文字,可以将方法封装至公用样式库中的elispse中,以后需要调用时直接调用elipse方法即可.

ellipse()
  overflow hidden
  white-space nowrap
  text-overflow ellipsis

效果如图:

使用computed完成分页:

computed: {
    pages () {
      const pages = []
      this.list.forEach((item, index) => {
        //这里让每页显示8条
        const page = Math.floor(index / 8)
        if (!pages[page]) {
          pages[page] = []
        }
        pages[page].push(item)
      })
      return pages
    }
  }

5.使用axios向服务器发送请求获取数据

如图,城市列表中的城市内容需要通过向后端服务器发送请求获取json数据再进行渲染,以往是通过ajax发送请求,在vue中一般使用axios,个人感觉就是ajax的增强版.

#安装
npm install axios --save

#引入
import axios from 'axios'

#语法
#发送get请求
axios.get('$url')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
#发送post请求
axios.post('$url', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

6.使用better-scroll插件实现酷炫的滚动效果

better-scroll可以实现像app那样的屏幕滚动效果,而且使用起来非常简单,在github上获赞无数,而且有完善的中英文文档可以参考.

Github地址:https://github.com/ustbhuangyi/better-scroll

该插件支持的DOM结构如图:

#安装
npm install better-scroll --save

#引入
import BScroll from 'better-scroll'

#使用
 mounted () {
    this.scroll = new BScroll('.wrapper')
 },

7.使用watch和scrollToElement实现点击字母跳转至对应的DOM元素

如图,当我点击B字母时,自动滚动到B开头的所有城市:

值得注意的是,better-scroll的scrollToElement中传入的参数必须是DOM元素才会生效.

  watch: {
    letter () {
      if (this.letter) {
        const element = this.$refs[this.letter][0]
        this.scroll.scrollToElement(element)
      }
    }
  }

8.使用handleTouch实现在字母A~Z上滑动时城市列表也按字母进行联动.

由于每个字母间的间距是固定的,然后每个字母距离首字母的高度可以计算出来,用计算出来的高度除以字母间距可以推算出当前所处的字母是哪个字母,再利用scrollToElement就可以实现滑动时的联动效果.

    handleTouchStart () {
      this.touchStatus = true
    },
    handleTouchMove (e) {
      if (this.touchStatus) {
        if (this.timer != null) {
          clearTimeout(this.timer)
        }
        //使用箭头函数,限制滑动时脚本运行的次数,提高性能
        this.timer = setTimeout(() => {
          const startY = this.startY
           //这里的值可以先console.log观察一下,最终去确定具体减多少合适
          const touchY = e.touches[0].clientY - 82 - 31
          const index = Math.floor((touchY - startY) / 24)
          this.$emit('change', this.letters[index])
        }, 16)
      }
    },
    handleTouchEnd () {
      this.touchStatus = false
    }
  }

9.声明式路由和编程式路由

#声明式路由(类似于a标签)
<router-link :to="...">DOM</router-link>

#编程式路由(跳转写在js中)
router.push(...)

10.使用VueX实现组件间传值

比如我在store.js中的state里定义了一个常量count,并将初始值赋值为1,现在我在某一个子组件中改变该count,并且让所有调用过该count的组件中的count值也都一起改变,可以这么做:

在该组件components中->dispatch触发actions->提交commit->触发Mutations->改变state,通过mutations改变state后,其他调用过count的组件中的count值会自动更新,这点有点像java中的volatile关键字的作用.

11.利用全局事件监听实现头部动态隐藏/显示效果

当下拉该界面至图片上的返回按钮消失时,头部内容就会被展示出来,当页面上拉至图片上的返回按钮出现时,头部内容会被隐藏.

  //当页面被挂载时添加该监听事件
  mounted () {
    window.addEventListener('scroll', this.handleScroll)
  },
  //用完后清除事件,以免对其它组件造成影响
  destroyed () {
    window.removeEventListener('scroll', this.handleScroll)
  }

  //在handleScroll中处理滚动事件
  handleScroll () {
    const top = document.documentElement.scrollTop
     if (top >= 40) {
          this.showAbs = false
     } else {
          this.showAbs = true
     }
  }
    

12.使用递归组件

组件是可以在它们自己的模板中调用自身的,比如这块内容的实现就借助了递归组件:

13.使用插槽创建公用的动画组件(渐进/渐退效果)

效果:

Hearder部分在下拉展示的过程中,会有一个渐进展示的动画效果,像这种效果可能会被其他地方用到,所以做一个公用的渐进/渐退效果的组件,就可以一处编写,到处使用了.

<!--vue中的动画效果要借助transition标签来实现,slot作为插槽,让出在其中的DOM具有动画效果-->
<template>
    <transition>
      <slot></slot>
    </transition>
</template>

<!--动画效果实现,使用transition默认的class名字 如v-enter v-leave-to 等-->
<style lang="stylus" scoped>
  .v-enter,.v-leave-to
    opacity 0
  .v-enter-active,.v-leave-active
    transition 1s
</style>

调用: 

14.使用本机IP可以访问项目设置

在package.json中的dev中添加

--host 0.0.0.0

这样就可以通过ip地址直接访问项目了,如果是同公司同一网段的IP均可以直接通过你电脑的Ip地址访问到你的项目,方便联调.

15.解决部分手机浏览器不支持高级es的语法的bug,比如es5,es6的语法.

#安装
npm install babel-polyfill --save

#引入
import  babel-polyfill

16.使用ref获取DOM

虽然vue是mvvm,大部分情况下不需要操作DOM,但偶尔还是需要操作一下的,在vue中可以使用ref来获取指定DOM.


<div class="test" ref="dom"></div>
#使用this.$refs.refName即可获取指定的dom元素
let dom = this.$refs.dom

17.使用$emit实现子组件向父组件触发事件

子组件向父组件触发事件是会经常被用到的

#比如一个component名为city的子组件向父组件触发事件并传值
<div class="test" @click="handleChildClick"></div>

handleChildClick () {
    this.count++;
    this.$emit('change',this.count)
}

#父组件
<city @change="handleChildChange"></city>

handleChildChange (count) {
    this.xxx = count
}

18.用精灵图,提高网页性能

精灵图就是利用background-position将一张大图上的图片仅显示你想展示的那一块内容,这么说可能不太好理解,以下面这幅图为例,如果我在一个页面中需要展示A~K这些所有字母,如果我把A~K切成一张张小图,用<img src="xxx">去写的确可以很简单的实现图片的展示,但这A~K张图片要发送A~K次请求才能拿到所有图,势必会影响网页性能,所以可以将A~K放在一张大图上,然后利用定位在需要的地方显示对应的字母即可,这样整张大图仅需要加载一次,就可以实现A~K的展现,减少了请求次数,提高了网页性能,代价是布局麻烦,如果页面的UI稍有改动,可能会让你很多css内容都要改一遍,所以精灵图一般在网页排版确定的情况下,为了提升少量网页性能时使用.

暂时更新到这里,本篇会持续更新,在今后凡有所学,就会在后面追加一些vue开发的技巧.

发布了89 篇原创文章 · 获赞 70 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/lovexiaotaozi/article/details/89361242