vue2.5去哪儿(慕课网)学习笔记
vue2.5去哪儿(慕课网)学习笔记
文章目录
- vue2.5去哪儿(慕课网)学习笔记
- 项目预热
- 安装环境
- 使用到的一系列Git指令
- vue-cli创建的项目的基本介绍
- 单文件组件与Vue中的路由
- 多页应用与单页应用
- 项目代码的初始化
- 在项目中使用[iconfont](https://www.iconfont.cn/)
- 项目实战 - 旅游网站首页开发
- 首页header区域开发
- 准备工作
- Header.vue页面开发
- 零散的知识点
- 使用轮播图
- 图标区域的开发
- 零散知识点
- 推荐区域的开发
- 零散知识点
- 周末游区域的开发
- 零散知识点
- Ajax获取首页数据
- 零散知识点
- 使用axios进行ajax
- 旅游网站城市列表页面开发
- 配置路由
- 搜索框(Search.vue)
- 城市选择列表
- 零散的知识点
- Better-scroll的使用
- 字母表的设计(alphabet.vue)
- 零碎的知识点
- 兄弟组件的联动-点击转到对应区域
- 兄弟组件的联动-在字母表上下拖拽转到对应区域
- 搜索功能的实现
- 零散的知识点
- 使用Vuex实现数据共享
- 使用Vuex
- 使用localstorage记住用户的选择
- 优化
- 使用keep-alive优化网页性能
- 旅游网站详情页面开发
- 详情页动态路由及banner布局
- 公用图片画廊组件拆分
- 实现Header渐隐渐显效果(起初显示一个返回按钮,下滑的时候按钮消失,显示另一个返回的箭头)
- 对全局时间的解绑
- list.vue的设计编写
- 使用Ajax获取动态数据
- 组件中的name值有什么用
- 页面拖拽在多个页面之中相互影响
- 在项目中加入基础动画
- 优化收尾
- Vue项目的接口联调
- Vue项目的真机测试
- Vue项目打包上线
项目预热
安装环境
- 安装Node.js
- 官网下载安装包进行安装
- 输入 node -v ,如果显示版本号则安装成功
- 输入 npm -v,安装包管理工具的验证
- 注册码云账号并关联本地仓库
- 码云创建仓库[语言:Javascript;开源许可:MIT ]
- 本地安装Git
- 验证:输入 git --version ,显示版本号即为成功
- 关联本地与云仓库
- 码云->设置-> SSH公钥->本地Git窗口中输入一系列linux指令生成公钥
- 复制线上仓库SSH地址,在需要的文件中使用Git窗口输入:git clone ‘复制的内容’
- 使用vue-cli脚手架创建工程
- 全局安装vue-cli
npm install --global vue-cli
- 创建项目
vue init webpack ‘文件夹名称’
- 运行项目
npm run dev
- 全局安装vue-cli
使用到的一系列Git指令
- 查看git状态
- git status
- 提交项目到云端
- git add . 将项目添加到缓存
- git commit -m ‘注释’ 将项目添加到本地仓库
- git push 将项目添加到云端仓库
- 分支的创建与切换
- 直接在码云的界面创建分支或者使用指令
- git pull 将线上创建的分支信息拉回本地
- git checkout ‘分支名称’ 切换操作的分支
- git merge ‘分支名称’ 将分支进行合并
- git branch 查看分支
vue-cli创建的项目的基本介绍
- README.md 介绍项目
- package.json 记录了依赖的包
- package-lock.json 确定依赖的包的版本信息
- LICENSE 开源协议的说明
- index.html 项目默认的首页模板文件
- .gitignore 记录不希望上传到云仓库的文件与目录
- .eslintrc.js 语法规范文件
- .eslintignore 记录不需要检查语法的文件与目录
- .editorconfig 配置了编辑器的语法
- .babelrc 语法解析器,将vue转化为浏览器可以识别的代码
- static目录 存放静态资源
- node_modules目录 存放依赖的包
- src目录 存放项目的源代码
- App.vue 项目最原始的根组件
- main.js 项目的入口文件
- router目录 路由组件
- components目录 项目要用的组件
- assets 目录 存放图片资源
- config目录 存放项目配置文件
- index.js 存放基础的配置信息
- dev.env.js 开发环境的配置信息
- prod.env.js 线上环境的配置信息
- build目录 存放打包的webpack的配置内容
- webpack.base.conf.js 基础的配置项
- webpack.dev.conf.js 开发环境配置项
- webpack.prod.conf.js 线上环境配置项
单文件组件与Vue中的路由
/main.js 项目的入口文件
import Vue from 'vue'
import App from './App'
import router from './router'new Vue({el: '#app',
router,
components: { App },
template: '<App/>'
})
/App.vue 项目默认的渲染文件
<template><div id="app"><keep-alive exclude="Detail"><router-view/> //显示当前地址所对应的内容</keep-alive></div>
</template>
<script>export default {name: 'App'}
</script>
<style>
</style>
router/main.js 路由配置文件
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/pages/home/Home'
import City from '@/pages/city/City'
import Detail from '@/pages/detail/Detail'
Vue.use(Router)
export default new Router({routes: [{path: '/',name: 'Home',component: Home}, {path: '/city',name: 'City',component: City}, {path: '/detail/:id',name: 'Detail',component: Detail}],
})
多页应用与单页应用
- 多页应用
- 每次请求一个HTML
- 首屏时间快,SEO效果好
- 页面切换慢
- 单页应用
- vue中使用: 列表页面 进行跳转
- 使用JS感知页面的变化,然后清除当前页面的内容,显示新的内容
- 特点
- 页面切换快
- 首屏时间慢,SEO差
- 使用JS渲染
项目代码的初始化
1./index.html
<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport"content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> //页面的比例始终是一比一,用户端不可以进行窗口的扩大缩小<title>Travel</title></head><body><div id="app"></div></body>
</html>
- 引入重置页面的样式表 reset.css和一像素边框border.css和‘300毫秒延迟点击问题’fastclick库
- 将文件添加进来
- 在main.js中添加代码
import ‘./assets/styles/reset.css’
import ‘./assets/styles/border.css’ - 关于fastckick库
- npm install fastclick --save
- 引入
import fastclick from ‘fastckick’
- 使用
fastclick.attach(document.body)
在项目中使用iconfont
- 收集图标
- 创建帐号
- 新建项目
- 浏览图标库,将要使用的图表添加到购物车
- 将购物车的内容添加至项目
- 在项目中‘下载至本地’
- 使用图标
- 解压文件包
- 将iconfont.eot,iconfont.svg,iconfont.ttf,iconfont.woff 添加到项目的assets/styles/iconfont/中
- 将iconfont.css文件放到iconfont文件夹同级,修改下其中涉及到其他文件的路径
- 引入文件
- 在main.js中引入iconfont
import ‘./assets/styles/iconfont.css’
- 在main.js中引入iconfont
- 使用
- 在需要使用的地方
图标代码
图表代码可以在购物车中的图表上查看
- 在需要使用的地方
- 解压文件包
项目实战 - 旅游网站首页开发
首页header区域开发
准备工作
- 安装stylus
install stylus --save
install stylus-loader --save - 设计布局
- home.vue 作为展示的容器,内部使用各个组件来搭页面
- 在同一级创建目录‘components’,内部新建header.vue
- 在 home.vue中引入并在components这个区域中命名它
Header.vue页面开发
零散的知识点
- 限制样式只在当前页面有用,使用scoped对css区域进行修饰
- 关于stylus
- 在reset.css中的html中的font-size: 50px 指示了 1rem=50px
- 想要靠近可以设置负值
- 将常使用的值设为变量
- 在styles文件夹中添加varibles.styl
设置变量 $bgColor = #00bcd4
- 在的首行进行引入
import ‘~styles/assets/styles/varibles.styl’
- 使用的时候,在值的部分输入
$bgColor
- 在styles文件夹中添加varibles.styl
- 将常用的路径设置为常量(符号表示)
- 在build/webpack.base.conf.js中,resolve: 中的alias:中添加一个键值对
‘styles’ : resolve(‘src/assets/styles’),
- 在build/webpack.base.conf.js中,resolve: 中的alias:中添加一个键值对
使用轮播图
- 查看插件与语法
- 在GitHub上搜索vue-awesome-swiper
- 新版可能存在bug,建议使用老版本
- 安装
- npm install vue-awesome-swiper@2.6.7 --save
- 引入
- 在main.js中引入和使用
import ‘swiper/dist/css/swiper.css’
import VueAwesomeSwiper from ‘vue-awesome-swiper’
Vue.use(VueAwesomeSwiper,‘可以给个参数’)
- 在main.js中引入和使用
- 使用,建立swiper.vue
<template><div class="wrapper"><div class="iconw"><div class="iconw-img"><swiper :options="swiperOption" v-if="showSwiper" > //应用轮播插件<swiper-slide v-for="item of list" :key="item.id"><img class="swipper-img" :src="item.imgUrl" /></swiper-slide><div class="swiper-pagination" slot="pagination"></div> //应用下面的选择点</swiper></div></div></div></template>
<script>
export default {name: 'HomeSwiper',props: {list: Array},data () {return {swiperOption: {pagination: '.swiper-pagination',loop: true //可以从最好一个滚回到第一个}}},computed: {showSwiper () {return this.list.length}}
}
</script><style lang="stylus" scoped>.wrapper >>> .swiper-pagination-bullet-active //样式穿透,将设置应用在非当前页面的class样式中,不受scoped的限制background: #fff.wrapperoverflow: hiddenheight: 0padding-bottom: 30.9% //将高度设置为宽度的30.9%background: green.iconwposition: relative.iconw-imgposition: absolutetop: 0left: 0right: 0.swipper-imgwidth: 100%
</style>
图标区域的开发
零散知识点
- 利用computed进行计算:每8个图表放一个页面
data () {return {swiperOption: {autoplay: false //不允许自动播放
}
}
},
computed: {pages () {const pages = []this.list.forEach((item, index) => {const page = Math.floor(index / 8)if (!pages[page]) {pages[page] = []}pages[page].push(item)})return pages}
}
- 将图标名字长的部分进行隐藏,显示三个点
.icon-descposition: absoluteleft: 0right: 0bottom: 0height: .44remline-height: .44remtext-align: centercolor: $darkTextColor//以下三句话实现隐藏加点overflow: hiddenwhite-sapce: nowraptext-overflow: ellipsis
推荐区域的开发
零散知识点
- 1像素边框的使用
<li class="item **border-bottom** ">
周末游区域的开发
零散知识点
- 有些时候希望组件的内容可以被调用的组件进行定制,使用 slot=""
Ajax获取首页数据
零散知识点
- json数据的最后一个大括号后面不要加逗号,否则可能出错
使用axios进行ajax
- 进行安装相应的模块
npm install axios --save
- 处理请求的api在开发环境进行重定向(转发)
- 开发中只有static中的文件可以被访问到,故在static文件夹中新建mock文件夹,然后建立index.json
- 在config/index.js中的dev中的proxyTable中添加对象
proxyTable: {'/api': {target: 'http://localhost:8080',pathRewrite: {'^/api': '/static/mock'}}
- 在Home.vue进行使用
- 首先引入
import axios from ‘axios’
- 在mounted进行使用
mounted () {this.getHomeInfo() }, methods: {getHomeInfo () {axios.get('/api/index.json?city=' + this.city).then(this.getHomeInfoSucc)},getHomeInfoSucc (res) {res = res.dataif (res.ret && res.data) {const data = res.datathis.swiperList = data.swiperListthis.iconList = data.iconListthis.recommendList = data.recommendListthis.weekendList = data.weekendListthis.cities = data.cities}} }
- 调用其他vue页面的时候将参数传递进去
<city-al :citise="cities"><city-al>
- 被调用的页面进行接收
props:{
cities:Object
} - 被调用的页面在接收后进行使用
<li class="item" v-for="item of letters" :key="item" :ref="item">{{item}}</li>
- 首先引入
旅游网站城市列表页面开发
配置路由
/router/index.js
import Vue from 'vue'import Router from 'vue-router'import Home from '@/pages/home/Home'import City from '@/pages/city/City'import Detail from '@/pages/detail/Detail'Vue.use(Router)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} //页面切换后从顶部开始显示内容
}
})
Header中点击城市名,将页面跳转到城市选择页面
<router-link to='/city'><div class="header-right">{{this.city}}<span class="iconfont arrow-icon"></span></div>
</router-link>
搜索框(Search.vue)
搜索框样式
<style lang="stylus" scoped>@import '~styles/varibles.styl'.searchheight: .72rempadding: 0 .1rembackground: $bgColor.search-inputbox-sizing: border-boxwidth: 100%height: .62rempadding: 0 .1remline-height: .62remtext-align: centerborder-radius: .06remcolor: #666.search-contentz-index: 1overflow: hiddenposition: absolutetop: 1.58remleft: 0right: 0bottom: 0background: #eee.search-itemline-height: .62rempadding-left: .2remcolor: #666background: #fff</style>
城市选择列表
零散的知识点
- 修改之前引入的1像素边框的颜色
.border-topbottom
&:beforeborder-color: #ccc
&:afterborder-color: #ccc
Better-scroll的使用
- 安装
npm install better-scroll --save
- 使用规范
- 查看Git官网的项目,来认识他的使用规范
- 两层div里面放需要的内容,如其他的div,或者li等标签
- 使用
- 利用ref来获取dom
- 在需要使用scroll的div中添加
<div class="list" ref="wrapper">
- 在需要使用scroll的div中添加
- 引入
import Bscroll from ‘better-scroll’
- 在mounted中实例化
mounted () {
this.scroll = new Bscroll(this.$refs.wrapper)
},
- 利用ref来获取dom
字母表的设计(alphabet.vue)
零碎的知识点
- 通过点击获取li标签里面的文本
console.log(e.target.innerText)
- 样式
<style lang="stylus" scoped>@import '~styles/varibles.styl'.listdisplay: flexlist-style:noneflex-direction: columnjustify-content: centerposition: absolutetop: 1.58remright: 0bottom: 0width: .4rem.itemline-height: .44remtext-align: centercolor: $bgColor</style>
兄弟组件的联动-点击转到对应区域
目的:实现点击一个字母(alphabet.vue),将城市选择(cityList.vue)跳转到字母对应的区域
首先在字母的li上绑定一个事件
<li @click="handleLetterClick" >{{key}}</li>
实现这个方法
methods: {
handleLetterClick: function (e) {
this.$emit(‘change’, e.target.innerText)
},主页面中对这个组件进行监听
<city-alphabet :cities=“cities” @change=“handleLetterChange”>
实现handleLetterChange这个方法
handleLetterChange (letter) {
this.letter = letter
}将letter传递给cityList.vue组件
<city-list :cities="cities" :hot="hotCities" :letter="letter"></city-list>
cityList.vue中进行接收
props: {
hot: Array,
cities: Object,
letter: String
},利用侦听器进行侦听,若letter改变,则显示对应的区域
watch: {letter () {if (this.letter) {const element = this.$refs[this.letter][0]this.scroll.scrollToElement(element)}} }
在li标签中进行显示
<div class="area" v-for="(item,key) of cities" :key="key" :ref="key"> <div class="title border-topbottom">{{key}}</div> //key中的值为A,B,C,D... <div class="item-list"> <div class="item border-bottom" v-for="innerItem of item" :key="innerItem.id" > {{innerItem.name}} //为具体的城市名称 </div> </div> </div>
兄弟组件的联动-在字母表上下拖拽转到对应区域
目的:实现在字母表(alphabet.vue)上滑动,将城市选择(cityList.vue)跳转到字母对应的区域
- 在li标签中绑定一个事件
<li class="item" v-for="item of letters" :key="item" :ref="item"
@touchstart.prevent="handleTouchStart"
@touchmove="handleTouchMove" @touchend="handleTouchEnd">{{item}}</li>
- 实现对应的三个方法
props: {cities: Object}, computed: {letters () {const letters = []for (let i in this.cities) {letters.push(i)}return letters} }, data () {return {touchStatus: false,startY: 0,timer: null}}, updated () { //当页面的数据被更新,页面完成了渲染this.startY = this.$refs['A'][0].offsetTop //A距离顶部的高度}, methods: {handleTouchStart () {this.touchStatus = true},handleTouchMove (e) {if (this.touchStatus) {if (this.timer) { //提高效率,避免过于频繁的刷新clearTimeout(this.timer)}this.timer = setTimeout(() => {const touchY = e.touches[0].clientY - 79const index = Math.floor(touchY - this.startY) / 20 //算出当前手指的位置对应的字母下标if (index >= 0 && index < this.letters.length) {this.$emit('change', this.letters[index])}}, 16)}},handleTouchEnd () {this.touchStatus = false} }
搜索功能的实现
Search.vue接收来自主页面的cities这个参数,并设置一个div,在查询内容不为空的条件下(v-show)显示,展示查询结果。
零散的知识点
- 运算放在computed中
<template><div><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"@click="handleCityClick(item.name)" :key="item.id"> {{item.name}}</li><li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li></ul></div></div>
</template>
<script>
import Bscroll from 'better-scroll'
import { mapMutations } from 'vuex'
export default {name: 'CitySearch',props: {cities: Object},mounted () {this.scroll = new Bscroll(this.$refs.search)},data () {return {keyword: '',list: [],timer: null}},computed: {hasNoData () {return !this.list.length}},methods: {handleCityClick (city) {this.changeCitys(city)this.$router.push('/')},...mapMutations(['changeCitys'])},watch: {keyword () {if (this.timer) {clearTimeout(this.timer)}if (!this.keyword) {this.list = []return}this.timer = setTimeout(() => {const result = []for (let i in this.cities) {this.cities[i].forEach((value) => {if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) {result.push(value)}})}this.list = result}, 100)}}}
</script>
使用Vuex实现数据共享
此时city与home,没有公用的组件,数据传递可以适用bus或者vuex。vuex是传递大量数据的数据框架
使用Vuex
- 安装
npm install vuex --save
- 新建src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({state: state,mutations: mutations,getters: {doubleCity (state) {return state.city + ' ' + state.city}}
})
- 在main.js中引入
import store from ‘./store’
new Vue({el: '#app',store: store,router,components: { App },template: '<App/>'
})
- 在Header.vue中进行操作,将显示城市的内容改为
this.store.state.city之所以每个页面都可以使用store.state.city 之所以每个页面都可以使用store.state.city之所以每个页面都可以使用store,是因为他在主js中引入,之后被派发到每一个页面
- 在城市选择页面List.vue,将当前城市改为
this.$store.state.city
- 实现点击一个城市名,则将首页的城市显示为该城市名
methods: {handleCityClick (city) {this.changeCitys(city)this.$router.push('/')},...mapMutations(['changeCitys'])
},
- store/mutations.js
export default {changeCitys (state, city) {state.city = citytry {localStorage.city = city} catch (e) {}}
}
- store/state.js
let defaultCity = '上海'try {if (localStorage.city) {defaultCity = localStorage.city}} catch (e) {}export default {city: defaultCity}
使用localstorage记住用户的选择
默认首页的城市为上海,当用户切换后,刷新页面会重新变为上海,
优化
- vuex方法写法优化
先引入
<script>
import { mapState, mapGetters } from 'vuex'
this.$store.state.city 的写法优化
computed: {
…mapState([‘city’]),
}
使用时
{{this.city}}this.$store.state.city 的写法优化2
computed: {
…mapState({
currentCity: ‘city’
})
使用时
{{this.currentCity}}
2.vuex中的getters
类似于computed的作用,可以使用数据计算数据
使用keep-alive优化网页性能
- 在App.vue中添加代码keep-alive
意思是;路由的内容加载一次以后,就将内容放到内存之中,下一次再取这个路由的时候直接从内存中取出,不需要重新渲染
- 发送ajax数据请求的时候带一个参数city
axios.get(’/api/index.json?city=’ + this.city).then(this.getHomeInfoSucc)
引入city这个参数的方法是vuex
- import { mapState } from ‘vuex’
- computed: {
…mapState([‘city’])
},
此时由于包含在keep-alive中并不会重新发送请求,可以使用activated,他在页面每次重新显示的时候被加载
activated () {if (this.lastCity !== this.city) {this.lastCity = this.citythis.getHomeInfo() //这个方法发送ajax请求}
},
旅游网站详情页面开发
详情页动态路由及banner布局
- 在内容的外部包裹路由跳转
<router-link tag="li" :to=" '/detail/'+ item.id">
- 在index.js中加入该路由信息(带有参数)
{path: '/detail/:id',name: 'Detail',component: Detail}
- 实现文字区域背景图片的渐变色
background-image: linear-gradient(top, rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.8))
公用图片画廊组件拆分
detail/banner.vue
<template>
<div>
<div class="banner" @click="handleBannerClick">
<img class="banner-img" :src="bannerImg">
<div class="banner-info" >
<div class="banner-title">{{this.sightName}}</div>
<div class="banner-number"><span class="iconfont banner-icon"></span>{{this.bannerImgs.length}}</div>
</div>
</div>
<fade-animation>
<common-gallary :imgs="bannerImgs" v-show="showGallary" @close="handleGallaryClose"></common-gallary>
</fade-animation>
</div>
</template>
<script>
import commonGallary from 'common/gallary/Gallary'
import FadeAnimation from 'common/fade/Fade'
export default {name: 'DetailBanner',
props: {sightName: String,
bannerImg: String,
bannerImgs: Array
},
data () {return {showGallary: false
}
},
methods: {handleBannerClick () {this.showGallary = true
},
handleGallaryClose () {this.showGallary = false
}
},
components: {commonGallary,
FadeAnimation
}
}
</script>
<style lang="stylus" scoped>
.banner
position: relative
overflow: hidden
height: 0
padding-bottom: 51%
.banner-img
width: 100%
.banner-info
display: flex
position: absolute
left: 0
right: 0
bottom: 0
line-height: .6rem
color: #fff
background-image: linear-gradient(top, rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.8))
.banner-title
flex:1
font-size: .32rem
padding: 0 .2rem
.banner-number
margin-top: .14rem
padding: 0 .4rem
line-height: .32rem
height: .32rem
border-radius: .2rem
background: rgba(0, 0, 0, .8)
font-size: .24rem
.banner-icon
font-size: .24rem
</style>
common/gallary.vue
<template>
<div class="container" @click='handleGallaryClick'>
<div class="wrapper">
<swiper :options="swiperOptions">
<swiper-slide v-for="(item,index) in imgs" :key="index">
<img class="gallary-img" :src="item" />
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
</div>
</div>
</template>
<script>
export default {name: 'CommonGallery',
props: {imgs: {type: Array,
default () {return ['https://img1.qunarzz.com/vs_ceph_vs_tts/4d217b8b-a26b-4c50-80ef-c37bcbb8005a.jpg', 'http://img1.qunarzz.com/vs_ceph_vs_tts/b60743c9-5a9c-407a-8e4f-a73344f63ffc.jpg_r_500x333x90_5a5cead1.jpg']
}
}
},
data () {return {swiperOptions: {pagination: '.swiper-pagination',
paginationType: 'fraction',
observeParents: true,
observer: true
}
}
},
methods: {handleGallaryClick () {this.$emit('close')
}
}
}
</script>
<style lang="stylus" scoped>
.container >>> .swiper-container
overflow: inherit
.container
display: flex
z-index: 99
position: fixed
flex-direction: column
justify-content: center
left: 0
right: 0
top: 0
bottom: 0
background: #000
.wrapper
height: 0
width: 100%
padding-bottom: 100%
.gallary-img
width: 100%
.swiper-pagination
color: #fff
bottom: -1rem
</style>
实现Header渐隐渐显效果(起初显示一个返回按钮,下滑的时候按钮消失,显示另一个返回的箭头)
detail/header.vue
<template>
<div>
<router-link tag="div" to="/" class="header-abs" v-show='showAbs'>
<div class="iconfont header-abs-back"></div>
</router-link>
<div class="header-fixed" v-show="!showAbs"
:style="opacityStyle"
>
<router-link to="/">
<div class="iconfont header-fixed-back"></div>
</router-link>
景点详情
</div>
</div>
</template>
<script>
export default {name: 'DetailHeader',
data () {return {showAbs: true,
opacityStyle: {opacity: 0
}
}
},
activated () {window.addEventListener('scroll', this.handleScroll)
},
deactivated () {window.removeEventListener('scroll', this.handleScroll)
},
methods: {handleScroll () {const top = document.documentElement.scrollTop
if (top > 60) {let opacity = top / 140
opacity = opacity > 1 ? 1 : opacity
this.opacityStyle = {opacity
}
this.showAbs = false
} else {this.showAbs = true
}
}
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.header-abs
position: absolute
left: .2rem
top: .2rem
width: .8rem
height: .8rem
line-height: .8rem
text-align: center
border-radius: .4rem
background: rgba(0,0,0,.8)
.header-abs-back
color: #fff
font-size: .4rem
.header-fixed
z-index: 2
position: fixed
top: 0
left: 0
right: 0
height: $headerHeight
line-height: $headerHeight
text-align: center
color: #fff
background: $bgColor
font-size: .32rem
.header-fixed-back
position: absolute
top: 0
left: 0
width: .64rem
text-align: center
font-size: .4rem
color: #fff
</style>
对全局时间的解绑
- 在header.vue中的方法
window.removeEventListener(‘scroll’, this.handleScroll)
该方法是对全局的影响,使用deactivated()钩子进行消除影响
list.vue的设计编写
- 关于递归组件
组件的name值,常用于递归组件的调用
<template>
<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 v-if="item.children" class="item-children">
<detail-list :list="item.children"></detail-list>
</div>
</div>
</div>
</template>
<script>
export default {name: 'DetailList',
props: {list: Array
}
}
</script>
<style lang="stylus" scoped>
.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
.item-children
padding: 0 .2rem
</style>
detail.vue中写了一些模拟数据
使用Ajax获取动态数据
将detail/list的数据通过Ajax获取
detail.vue
<template>
<div>
<detail-banner :sightName="sightName"
:bannerImg="bannerImg"
:bannerImgs='gallaryImg'
></detail-banner>
<detail-header></detail-header>
<div class="content" >
<detail-list :list="list"></detail-list>
</div>
</div>
</template>
<script>
import detailBanner from './components/Banner'
import DetailHeader from './components/Header'
import DetailList from './components/List'
import axios from 'axios'
export default {name: 'Detail',
components: {detailBanner,
DetailHeader,
DetailList
},
data () {return {sightName: '',
bannerImg: '',
gallaryImg: [],
list: []
}
},
methods: {getDetailInfo () {// axios.get('/api/detail.json?id=' + this.$route.params.id)
axios.get('/api/detail.json', {params: {id: this.$route.params.id
}
}).then(this.handleGetDataSucc)
},
handleGetDataSucc (res) {res = res.data
if (res.ret && res.data) {const data = res.data
this.sightName = data.sightName
this.bannerImg = data.bannerImg
this.gallaryImg = data.gallaryImgs
this.list = data.categoryList
}
}
},
mounted () {this.getDetailInfo()
}
}
</script>
<style lang="stylus" scoped>
.content
height: 50rem
</style>
组件中的name值有什么用
- 递归组件使用
- 取消对个别页面的缓存
- 浏览器中vue调试工具看到的也是名字
页面拖拽在多个页面之中相互影响
在router/index.js中添加scrollBahavior
Vue.use(Router)
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}
}
})
在项目中加入基础动画
- 在详情的点击进入图片轮播这里加入基础动画
- common/Fade.vue
<template>
<transition>
<slot>
</slot>
</transition>
</template>
<script>
export default {name: 'Fade'
}
</script>
<style lang="stylus" scoped>
.v-enter, .v-leave-to
opacity: 0
.v-enter-active, .v-leave-active
transition: opacity .5s
</style>
- 引入之后,注册,然后包裹在轮播组件之外
优化收尾
Vue项目的接口联调
Vue项目的真机测试
- 修改package.json文件
这样你就可以通过ip访问这个开启的项目了 - 手机与电脑在同一个局域网,然后访问项目开启的端口即可
Vue项目打包上线
- 运行命令 npm run build
- 项目目录中出现dist这个目录,这个目录中的文件就是上线的代码
- 如果打包后在后端服务器中放到某个文件夹中
- /config/index.js
- 重新进行打包,然后将打包结果放到服务器中
- /config/index.js
vue2.5去哪儿(慕课网)学习笔记相关推荐
- Maven慕课网学习笔记
-唯快不破-maven快速入门 -稳扎稳打-maven核心知识 -实用为先-maven建立web项目 唯快不破-maven快速入门 Maven介绍与环境搭建 Maven是基于项目对象模型(POM),可 ...
- Android App压力测试(慕课网学习笔记)
转载:https://blog.csdn.net/a923751813/article/details/72884826 一 背景 1. 为什么开展压力测试 目标1:提高产品稳定性(产品稳定性是一项 ...
- JavaWeb黑马旅游网-学习笔记08【旅游线路详情】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- JavaWeb黑马旅游网-学习笔记02【注册功能】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- 通过慕课网学习Python
通过慕课网学习Python.慕课网-Python入门 老师是:廖雪峰大神.我觉得他讲的非常好.另外,慕课网的练习形式我很喜欢,所以给大家推荐一下. 我买了两本书:<Python编程从入门到实践& ...
- JavaWeb黑马旅游网-学习笔记07【旅游线路查询】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- Angular官网学习笔记
Angular官网学习笔记 一.Angular概述 **什么是Angular:**一个基于TypeScript构建的开发平台包括: 一个基于组件的框架,用于构建可伸缩的Web应用 一组完美集成的库,涵 ...
- JavaWeb黑马旅游网-学习笔记09【旅游线路收藏】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- JavaWeb黑马旅游网-学习笔记06【旅游线路分页展示分页展示】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- JavaWeb黑马旅游网-学习笔记05【分类数据展示功能】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
最新文章
- android窗口管理机制
- 【设计模式】建造者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
- Python 基础语法(二)
- IO模型(epoll)--详解-03
- python周志_Python几周学习内容小结
- 接口测试从零开始系列_mock技术使用
- java util 中set,List 和Map的使用
- Python刷题-2
- Waymo也商业化了!“早期乘客”项目开始测试收费,凤凰城人民掏了腰包
- html内容写入txt文件内容,写入内容到文件里面 - FileWriter《 HTML5:文件系统 》
- NOD32 V5 企业版部署方案
- oozie控制台命令
- java初级求职简历,初级Java软件工程师求职简历范文
- 如何让企业微信的消息在微信里显示?
- 搜索命令:whereis/which/locate/find/grep
- 入库出库JAVA技术详情_基于Java_EE的入库出库管理系统
- win10切换输入法快捷键_改掉Win10难用的输入法
- MYSQL 删除百万级数据
- 中值滤波去雾算法matlab,去雾算法-引导滤波程序
- 聊一聊关于加解密、加签验签的那些事