vue2.0仿去哪儿网移动端Webapp遇到的问题

vue2.0仿去哪儿网移动端Webapp遇到的问题

github地址:https://github.com/tedqin/Travel
demo:https://tedqin.github.io/Travel/

使用vue2.0对去哪儿网的移动端web页面的复现,做个总结。

为什么使用单页面应用

多页面应用

  • 每次页面跳转,后端返回一个新的html
    • 优点:首屏时间快、seo效果好(搜索引擎可以识别跳转的多个链接)
    • 缺点:页面切换慢(每次跳转需发送http请求)

单页面应用

  • js感知路由变化,动态清除页面内容并将新页面渲染
    • 优点:页面切换快
    • 缺点:首屏时间慢,seo差

移动web端配置

  • 使用rem单位
  • 防止手指放大缩小页面,修改index.js
<meta name="viewport" content="width=device-width, 
initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

组件开发

合理拆分组件,提高开发效率。父组件通过import方式导入子组件,并且

export default {
  name: 'xxx',
  components: {注册子组件名}

插槽

使用场景:当组件的内容希望父组件去定制

stylus

style库,增加开发效率。
其中,.a >>> .b具有穿透scoped限制的效果

防抖

为了防止图片加载的过程中,页面抖动(图片未加载完毕的时候,文字会在上方,加载完毕后会抖动)

.wrapper
    width: 100%
    height: 0
    overflow: hidden
    padding-bottom: 26.7% //图片的宽高比

vuex进行非父子组件数据传递

一般使用

vuex中有几个关键:单向数据的改变过程
state存放公用数据,组件改数据必须调用actions,做一些异步处理或者批量的同步操作。然后actions调用mutations,只有通过改变mutations的值才能改变state

  • 在state中设置默认值
    attr = 'aaa'
  • 在组件中通过dispatch向actions派发数据(如果没有异步请求,可以直接使用commit,跳过这步)
    this.$store.dispatch('actionsName', data)
  • 在actions中通过commit向mutations发送数据

      actionnName(tcx, data) {
          tcx.commit('mutationsName', data)
          }
    
  • 然后在mutations中修改state中的值

      mutationsName(state, data) {
          state.attr = data
          }
    

高级使用

  • 引入mapState, mapMutations import [mapState, mapMutations] from 'vuex
  • 把mapState添加到计算属性(compute)中,把mapMutations添加到方法(methods)中
      computed: {
          ...mapState({
              currentCity: 'city
          })
      },
      methods: {
          ...mapMutations(
              ['changeCity']
          )
      }
    

axios发送ajax请求

  • 使用生命周期函数mounted函数获取ajax数据,此时vue实例被挂载,但dom还没有渲染,可以节省性能
  • 请求url:axios.get('xxx/xxx.json')
  • axios返回的是promise对象,可以使用then

      methods: {
          getCityInfo () {
            axios.get('/Travel/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
            }
            ...
    
  • 对以上代码的解释:
    • 在mounted钩子函数里面定义一个A方法,只要页面加载完毕就执行A方法
    • A方法用于获取后端的数据,它是一个promise函数,只要获取到了函数就then一个B函数
    • B函数可以接收一个res参数,这个参数就是返回的结果
  • ajax请求一般放在最外层的组件,这样只需要一次请求就可以获取所有页面的内容

ajax获取动态数据

  • 在路由里的地址后面写:id,表示把对应的id参数存在了id变量中
  • 在获取ajax请求的地址上,可以写axios.get('xxx/xxx.json?id=' + this.$route.params.id)
  • 也可以写axios.get('xxx/xxx.json', {params: {id: this.$route.params.id}})
  • vue中的内置路由组件
    <router-link to='/city'></router-link>
  • 使用前先在router/index.js中配置路由
  • 可以通过配置tag属性改成别的标签

单行内容超出范围

当单行文字内容超出显示范围,而显示......时,可以

overflow: hidden
white-space: nowrap
text-overflow: ellipsis

betterscroll

页面滚动插件

函数节流

当鼠标在字母表上来回移动的时候,touchMove执行的频率是非常高的,通过函数节流限制下执行的频率:增加延时器

localstorage

自动缓存,刷新页面的时候已经选择的城市不发生改变

  • 相当于cookie,但是用法要简单很多
  • 用法:
    localStorage.arrt = va;ue
  • 最好使用try catch包裹,因为在部分浏览器会报错

keepalive

优化问题:缓存页面数据,防止切换页面会发生多次ajax请求

<keep-alive>
    <router-view/>
</keep-alive>

它的意思是,路由内容每被加载一次,就把路由中的内容放到内存之中,下一次再进这个路由的时候,不需要再次渲染这个组件去重新执行钩子函数,只需要你从内存把以前的内容拿出来显示到页面上就可以

组件中name属性

  • 在递归组件时使用
  • keepalive取消缓存在exclude=’组件name’中使用
  • vue devtool调试工具中显示项目结构的名字

组件异步加载

正常情况下,单页应用会在进入首页时加载所有组件
可以删除import特定的组件,然后通过component: () => import('@/pages/home/Home)按需加载

全局事件解绑

  • window是全局事件,无论那个页面都会监听这个事件,会影响到其他页面,所以要解绑
  • 在有keep-alive时会出现两个新的钩子函数:
    • activated 在页面被显示时执行
    • deactivated 在页面即将被隐藏或页面被替换的时候执行

简写

  • @表示src目录
  • es6中,键值对相同写一个就可以

组件一览

  • home
    • Header 头部
    • Icon 原型图标区域
    • Recommend 推荐
    • Swiper 图片轮播
    • Weekend 周末推荐
  • city
    • Header 头部
    • Alphabet 右侧城市首字母下拉列表
    • List 城市列表
    • Search 搜索
  • detail
    • Header 头部
    • Banner 主页面
    • List 图片详情页的轮播

部署到GitHub pages

参考 https://medium.com/@Roli_Dori/deploy-vue-cli-3-project-to-github-pages-ebeda0705fbd

webpack

后期更新