美文网首页
Vue2.5 去哪儿网App实战项目开发知识梳理

Vue2.5 去哪儿网App实战项目开发知识梳理

作者: 极简博客 | 来源:发表于2022-07-08 14:57 被阅读0次

简介

本文是作者通过学习 慕课网 Vue 2.5 去哪儿网课程的总结。由于在下才疏学浅,可能有很多不足之处,欢迎指正。

一、移动端ios出现click事件300ms延迟。

1.1 引入fastclick插件

npm install fastclick --save

1.2 在main.js文件中引入并使用

import fastClick from 'fastclick'

fastClick.attach(document.body)

二、stylus(富于表现力、动态的、健壮的 CSS) 的使用

2.1 使用

<style lang="stylus" scoped>
    @import '~styles/varibles.styl'
    .parent
      position relative
      .child
        position absolute
        background $bgColor
</style>

2.2 解析

  • 通过缩进控制上下层关系
  • 通过@import引入全局变量,使用$bgColor调用
  • lang="stylus" 表明为stylus, scoped 指定仅在当前文件使用
  • stylus学习网址

三、iconfont 图标使用

3.1 创建图标项目,添加文件到开发项目中

  • 将喜欢的图标加入购物车,然后添加至项目,下载到本地即可

  • 将压缩文件解压,在src/assets/styles/ 文件夹中导入以下四个文件

    iconfont.eot、iconfont.svg、iconfont.ttf、iconfont.woff

  • 在 src/assets/ 中导入iconfont.css,并将url修改为本地路径

  • 在main.js中引入 import 'styles/iconfont.css'

3.2 在代码中的使用

<span class="iconfont">&#xe632;</span>

四、@表示的意思

4.1 注意

@默认表示src所在路径,在<style ></style>中使用需要加~@修饰

4.2 例子

import Home from '@/pages/home/Home'

<style lang="stylus" scoped>
  @import '~styles/varibles.styl'
</style>

4.3 拓展

// 通过修改webpack.base.conf.js 可以自定义变量解析路径,参照@
resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'styles': resolve('src/assets/styles'),
      'common': resolve('src/common'),
    }
  }

五、vue-awesome-swiper轮播插件

5.1 引入

// 下载插件
npm install --save vue-awesome-swiper@2.6.7
// 在项目main.js中全局引入
import VueAwesomeSwiper from 'vue-awesome-swiper'
import "swiper/dist/css/swiper.css"
Vue.use(VueAwesomeSwiper)

5.2 使用

<template>
  <div class="wrapper">
    <swiper ref="mySwiper" :options="swiperOption" v-if="showSwiper">
      <swiper-slide v-for="item of list" :key="item.id">
        <img class="swiper-image" :src="item.imgUrl" />
      </swiper-slide>
      <div class="swiper-pagination" slot="pagination"></div>
    </swiper>
  </div>
</template>

<script>
export default {
  name: 'HomeSwiper',
  props: {
    list: Array
  },
  data () {
    return {
      swiperOption: {
        pagination: '.swiper-pagination',
        loop: true,
        // 以下两个元素为父类元素DOM发生变化时自定刷新swiper
        observeParents: true,
        observer: true
      }
    }
  },
  computed: {
    showSwiper () {
      return this.list.length
    }
  }
}
</script>

5.3 存在页面加载抖动问题

  • 5.3.1 分析原因

    由于网络延迟,而图片加载缓慢,导致图片挤压高度

  • 5.3.2 设置固定宽高比

    // 高度设置为0导致,padding-bottom会参照宽度去设置padding-bottom
    <style lang="stylus" scoped>
      .wrapper
          overflow hidden
          width 100%
          height 0
          padding-bottom 31.25%
    </style>
    
  • 5.3.3 拓展

    父元素display:flex布局,子元素flex:1;min-width:0,表示自适应父元素剩余的宽度,且不会超出父元素的宽度

六、axios 实现跨平台请求(ajax)

6.1 下载插件

npm install axios --save

6.2 使用

import axios from 'axios'
axios.get('/api/index.json', {
  params: {
    id: 1
  }
})
.then(function (response) {
  console.log(response);
})
.catch(function (error) {
  console.log(error);
});

6.3 自定义路径转发

// config/index.js 修改配置使得/api路由为/static/mock
proxyTable: {
 '/api': {
    target: 'http://127.0.0.1:8080',
    pathRewrite: {
        '^/api': '/static/mock'
    }
 }
}

6.4 拓展

// 修改package.json 添加 --host 0.0.0.0 使得以ip访问,默认不能通过ip访问
"scripts": {
    "dev": "webpack-dev-server --host 0.0.0.0 --inline --progress --config  build/webpack.dev.conf.js",
    "start": "npm run dev",
    "lint": "eslint --ext .js,.vue src",
    "build": "node build/build.js"
}

七、better-scroll滚动插件使用

7.1 使用

  • 下载插件:npm install better-scroll --save
  • 引入better-scroll:import Bscroll from "better-scroll"
  • 定义标签dom: < div ref="myRef"></div>
  • 实例化bscroll: this.scroll=new Bscroll(this.$refs.div)即可;
  • Bscroll提供滚动到指定DOM位置的API,this.scroll.scrollToElement(this.$refs.myRef)

7.2 注意

  • 默认它会阻止touch事件。所以在配置中需要加上click: true,否则@click会在移动端失效
mounted(){
    this.scroll=new Bscroll(this.$refs.wrapper, { mouseWheel: true, click: true, tap: true })
}
  • v-for 会导致this.$refs.myRef得到的结果为数组,获取单个Dom需要指定下标,如:[0]

八、vuex

8.1 使用场景

  • 如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择

8.2 下载插件

  • npm install vuex --save
  • 对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块
  • [图片上传失败...(image-42936e-1657263417528)]
  • 在main.js中引入
import store from "./store"
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})
  • 使用
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'CityList',
  props: {
    hot: Array,
    cities: Object,
    letter: String
  },
  computed: {
    ...mapState({
      currentCity: 'city'  // 获取modules中city赋值到属性currentCity
    })
  },
  methods: {
    handleCityClick (city) {
      // this.$store.commit('changeCity', city) 简化
      this.changeCity(city)
      this.$router.push('/')
    },
    ...mapMutations(['changeCity'])
  },
  watch: {
    // 监听letter变化 由于v-for修饰导致获取到数组所有增加[0]获取dom元素对象
    letter () {
      if (this.letter) {
        const element = this.$refs[this.letter][0]
        this.scroll.scrollToElement(element)
      }
    }
  },
  mounted () {
    this.scroll = new Bscroll(this.$refs.wrapper, {mouseWheel: true, click: true, tap: true})
  }
}

九、localStorage本地存储

let defaultCity='重庆';  
try{    
    //防止用户关闭缓存造成报错
    if(localStorage.city){
        defaultCity=localStorage.city
    }
}catch(e){}
        
export default new Vuex.Store({
    state:defaultCity,     //首页头部显示的城市,默认为localStorage.city或者重庆
})

十、keep-alive代码优化,将加载的页面存储到缓存中

10.1 使用

<!--App.vue 文件-->
<template>
  <div id="app">
    <!-- 显示的是当前路由地址所对应的内容 keep-alive 将首次路由的内容加到内存中避免重复调用mounted -->
    <keep-alive exclude="Detail">
      <router-view/>
    </keep-alive>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>

</style>

10.2 代码判断是否触发axios重新加载数据

// 由于改变城市页面跟着变动,所以不能还是使用缓存中的数据,当页面重新显示时调用activated函数
activated () {
    // 城市改变时重新渲染页面
    if (this.lastCity !== this.city) {
        this.lastCity = this.city
        this.getHomeInfo()
    }
}

十一、页面跳转

11.1 router-link

<!--tag使用避免了a标签改变了li表示内里的文字颜色,相当于<li></li>且自带跳转页面的功能-->
<router-link
        tag="li"
        class="item border-bottom"
        v-for="item of list"
        :key="item.id"
        :to="'/detail/' + item.id"
      >
</router-link>

11.2 this.$router.push('/')

this.$router.push('/')

11.3 拓展

// 获取url后的参数
this.$route.params.id

十二、滚动事件

12.1 创建

// 页面展示执行
activated () {
    window.addEventListener('scroll', this.handleScroll)
}

12.2销毁

// 页面隐藏或者被新页面替换执行 window为全局事件,创建之后需要有销毁,否则每个页面都会触发scroll事件
deactivated () {
    window.removeEventListener('scroll', this.handleScroll)
}

12.3 跳转至其它页面,滚动条置顶

// router/indx.js 文件
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/city',
      name: 'City',
      component: City
    },
    {
      path: '/detail/:id',
      name: 'Detail',
      component: Detail
    }
  ],
  // 切换页面重新定位到顶部
  scrollBehavior (to, from, savedPosition) {
    return {x: 0, y: 0}
  }
})

十三、拓展

13.1 父子组件之间的传值

// 父 > 子
通过属性传值:父组件: :city="city" 子组件:props: { city: String }
// 子 > 父
通过事件触发:子组件:this.$emit('change', params) 父组件:@change="handleLetterChange"

13.2 兄弟组件传值

兄弟1->父组件->兄弟2

13.3 其它组件

使用 vuex | localStorage

13.4 安装淘宝镜像

npm install -g cnpm --registry=https://registry.npm.taobao.org

13.5 Vue生命周期图示

vue生命周期.jpg

相关文章

网友评论

      本文标题:Vue2.5 去哪儿网App实战项目开发知识梳理

      本文链接:https://www.haomeiwen.com/subject/dulvbrtx.html