1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 使用Vue框架开发去哪儿旅游网移动端实战项目(六)

使用Vue框架开发去哪儿旅游网移动端实战项目(六)

时间:2019-07-25 20:08:21

相关推荐

使用Vue框架开发去哪儿旅游网移动端实战项目(六)

第六章 旅游网站首页开发

首页导航栏

根据设计稿完成页面的布局:

在正式编写代码之前,先来介绍一下stylus这是一种与less、sass一样的功能,可以帮助我们快速完成css代码的编写。请使用一下命令进行安装:

npm install stylus --savenpm install stylus-loader --save

开始编写header页面:

<template><div class="header"><div class="header-left">返回</div><div class="header-input">输入城市景点/游玩/主题</div><div class="header-right">城市</div></div></template><script>export default {name: 'HomeHeader'}</script><!-- 要使用stylus使用lang标识,只想对当前组件有效使用scoped --><style lang="stylus" scoped>.headerdisplay: flexcolor: #fffbackground: #00bcd4line-height: .86rem.header-leftwidth: .64remfloat: left.header-inputflex: 1background: #fffmargin-top: .12remheight: .64remline-height: .64remmargin-left: .2remborder-radius: .05remcolor: #ccc.header-rightwidth: 1.24remfloat:righttext-align: center</style>

如果页面出现顶部有空白的情况,解决办法是在App.vue中的style中设置内边距和外边距的值为0,一般情况下不会有出现,除非你真是出现了。

<style>*{padding: 0;margin: 0;}</style>

现在我们向把“返回”换成一个图标的形式,就会用到下一节要说的内容。

iconfont的使用和代码优化

首先我们进入iconfont官网,没有账号的先进行注册,注册好了记得新建一个项目(travel)。

如果你已经注册好,点击图标库>官方图标库>选择任意一个,找到我们的需要的图标并且添加到购物车之中>点击右边的购物车并点击添加至项目>然后下载到本地

这时我们会得到一个包,我们只需要用到其中几个文件就可以。我们把需要用到的文件拷贝到我们项目中。

我们可以看到图中,我把除了.css的的文件放在了style文件夹中,把其它类型的文件放在了新建的iconfont文件夹中。

这时我们在编辑器中打开iconfont.css文件,我们需要修改一下它所使用到的文件的路径

下面的这一部分可以注释掉或者删除。根据自己的理解来使用,这里我选择不使用这种方法,因为它写的都是中文的拼音。

接下来我们将iconfont.js引入到入口文件中。

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

完成以上的步骤,如果没有出错的话,我们就可以开始在页面中开始使用这些图标了。

Header.vue文件中这样写:

<template><div class="header"><div class="header-left"><span class="iconfont">&#xe696;</span></div><div class="header-input"><span class="iconfont">&#xe64d;</span>输入城市景点/游玩/主题</div><div class="header-right">城市<span class="iconfont">&#xe64a;</span></div></div></template>

上面代码中的Unicode代码可以在iconfont官方你的项目文件中选择Unicode并复制代码,就可以得到了。这也就为什么我们前面要注释那些样式代码的原因了。

图标是有了,但是我们还需要做一些位置的优化:

<template><div class="header"><div class="header-left"><div class="iconfont back-icon">&#xe696;</div></div><div class="header-input"><span class="iconfont search-icon">&#xe64d;</span>输入城市景点/游玩/主题</div><div class="header-right">城市<span class="iconfont arrow-icon">&#xe64a;</span></div></div></template><style lang="stylus" scoped>.headerdisplay: flexcolor: #fffbackground: #00bcd4line-height: .86rem.header-leftwidth: .64remfloat: left.back-icontext-align: centerfont-size: .4rem.header-inputflex: 1background: #fffmargin-top: .12remheight: .64remline-height: .64remmargin-left: .02remborder-radius: .05rempadding-left: .2remcolor: #ccc.search-iconpadding-right: .1rem.header-rightwidth: 1.24remfloat:righttext-align: center.arrow-iconfont-size: .24rem</style>

完成以上的内容我们就可以看到现在的效果:

代码的优化:

由于我们这个项目的主题颜色,是绿色。在以后的很多组件都会用到这个颜色。我们可以定义一个变量,需要的时候直接引用就可以了。

首先需要在src/assets/styles目录下新建一个varibles.styl这样的一个文件,表示是一个stylus格式的文件。并且在文件中写上一下内容。该文件可以用来写一些变量。

$bgColor = #00bcd4

下面就就要在Header.vue文件中进行引入了。

<style lang="stylus" scoped>@import '../../../assets/styles/varibles.styl'.headerbackground: $bgColor</style>

我们发现啊,引入的文件路径太长,有什么办法可以解决呢?我们可以使用@符号来代替路径前面的前缀。

<style lang="stylus" scoped>@import '~@/assets/styles/varibles.styl'.headerbackground: $bgColor</style>

但是呢,像assets/styles/这样的是路径我们使用的太频繁且冗长,其实也是可以对它起个命名。我们需要在webpack-base.conf.js文件中添加一下内容就可以了。

resolve: {extensions: ['.js', '.vue', '.json'],alias: {'vue$': 'vue/dist/vue.esm.js','@': resolve('src'),//添加下面这一句'styles': resolve('src/assets/styles'),}}

修改完成之后,我们就可以对使用了assets/styles/这种路径的地方进行改写为styles就可以了。因为修改了配置文件,修改之后会出现报错的情况,所以需要重启一下服务。

main.js

import 'styles/reset.css'import 'styles/border.css'import 'styles/iconfont.css'

Header.vue

@import '~styles/varibles.styl'

最后当然也别忘记将写完的代码提交到线上仓库。使用一下命令就可以了。提交前记得先退出服务

git add .git commit -m 'addHeader'git push

总结:

首先介绍了如何去使用iconfont图标库,然后通过对webpack的配置对代码进行简化,也介绍了如何使用stylus及应用stylus变量。

首页轮播图

在企业级开发项目中,我们都是在不同的branch分支中进行开发的,最后再合并到master分支上。所以我们需要在GitHub中创建一个轮播图的分支。

如何创建分支?

这里我们选择使用命令来创建

# 创建分支git checkout -b index-swiper# 将本地创建的分支更新到线上仓库git push origin index-swiper# 查看本地分支git branch -r# 查看当前所在分支git status

写轮播图我们选择使用那你第三方的库(vueAwesomeswiper),该库可以帮助我们快速构建轮播效果。要使用该库需要先安装它。使用一下命令即可安装相应版本的库文件。

npm install vue-awesome-swiper@2.6.7 --save

下载好之后,我们需要将以下的代码引入到我们项目之中的mian.js

//引入到入口文件import Vue from 'vue'import VueAwesomeSwiper from 'vue-awesome-swiper'// require stylesimport 'swiper/dist/css/swiper.css'Vue.use(VueAwesomeSwiper, /* { default global options } */)

创建swiper组件:在components文件夹中新建Swiper.vue文件。并且写上如下的代码:

<template><swiper :options="swiperOption"><img class="swiper-image" src="http://mp-piao-/mp_piao_admin_mp_piao_admin/admin/1/8c458e9fe5b5f4575b1d7ec0489a9ff8.jpg_750x200_f0fbf511.jpg"></swiper-slide><swiper-slide><img class="swiper-image" src="http://mp-piao-/mp_piao_admin_mp_piao_admin/admin/12/d6df0db510d7b9aaa3d9ce4cffafeca1.jpg_750x200_abb38f14.jpg"></swiper-slide><div class="swiper-pagination" slot="pagination"></div>//<div class="swiper-button-prev" slot="button-prev"></div>//<div class="swiper-button-next" slot="button-next"></div>//<div class="swiper-scrollbar" slot="scrollbar"></div></swiper></template><script>export default {name: 'HomeSwiper',data(){return {swiperOption: {}}}}</script><style lang='stylus' scoped>.swiper-imagewidth:100%</style>

这里再介绍一个问题:就是在加载很慢的时候,轮播以下的内容,会有明显的抖动为题。要解决这个问题只需做一下修改就可以了。

<template><div class="wrapper"> //....</div></template><style lang='stylus' scoped>.wrapperoverflow: hiddenwidth: 100%height: 0// 26.67%是图片的宽高比padding-bottom: 26.67%background: #eee.swiper-imagewidth:100%</style>

接下来我们我给轮播图加控制点及进行相关的优化;

<template><div class="wrapper"> <swiper :options="swiperOption"><swiper-slide v-for="item of swiperList" :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',data(){return {swiperOption: {pagination: '.swiper-pagination', //显示控制点loop:true //让轮播可以循环的切换},swiperList:[{id:'001',imgUrl:'http://mp-piao-/mp_piao_admin_mp_piao_admin/admin/1/8c458e9fe5b5f4575b1d7ec0489a9ff8.jpg_750x200_f0fbf511.jpg'},{id:'002',imgUrl:'http://mp-piao-/mp_piao_admin_mp_piao_admin/admin/12/d6df0db510d7b9aaa3d9ce4cffafeca1.jpg_750x200_abb38f14.jpg'}]}}}</script><style lang='stylus' scoped>// 这是改变控制点的默认颜色,'>>>'代表穿透 在wrapper下只要出现后面的样式就会执行.wrapper >>> .swiper-pagination-bullet-activebackground: #fff.wrapperoverflow: hiddenwidth: 100%height: 0// 26.67%是图片的宽高比padding-bottom: 26.67%background: #eee.swiper-imagewidth:100%</style>

完成以上内容就可以把完成的代码提交到线上仓库。再将当前的分支内容合并到master分支中。

# 切换到主分支中git checkout master# 合并分支git merge origin/index-swiper# 最后提交git push

在实际开发过程中,都是按照以上的步骤来进行的。

图标区域的布局

同前面讲的操作,这一节我们也要新建一个分支来进行开发新的内容。创建分支就不再累述,直接查看前面章节即可。

创建Icons组件:在components文件夹中新建Icons.vue文件。并且写上如下的代码:

<template><div>icon</div></template><script>export default {name:'HomeIcons'}</script><style lang="stylus" scoped></style>

Home.vue

<template><div><home-header></home-header><home-swiper></home-swiper><home-icons></home-icons></div></template><script>import HomeHeader from './components/Header'import HomeSwiper from './components/Swiper'import HomeIcons from './components/Icons'export default {name: 'Home',components: {HomeHeader, HomeSwiper,HomeIcons}}</script>

完整Icons.vue代码:

<template><div class="icons"><div class="icon"><div class="icon-img"><img class="icon-img-content" src="/piao/fusion/1803/95/f3dd6c383aeb3b02.png"></div><p class="icon-desc">景点门票</p></div></div></template><script>export default {name:'HomeIcons'}</script><style lang="stylus" scoped>@import '~styles/varibles.styl'.iconsoverflow: hiddenheight: 0padding-bottom: 50%.iconposition:relativefloat: leftwidth: 25%height:0padding-bottom: 25%.icon-imgposition:absolutetop:0left:0right:0bottom:.44rembox-sizing:border-boxpadding:.1rem.icon-img-contentdisplay:blockmargin:0 autoheight:100%.icon-descposition:absoluteleft:0right:0bottom:0height:.44remline-height:.44remtext-align:centercolor:$darkTextColor</style>

图标区域逻辑实现

需求:当图标很多的时候,可以实现左右滑动的效果。以及循环渲染数据。

完整代码:

<template><div class="icons"><swiper :options="swiperOption"><!-- 循环渲染数据 添加swiper-slide标签可以实现左右滑动 --><swiper-slide v-for="page,index of pages" :key="index"><div class="icon" v-for="item of page" :key="item.id"><div class="icon-img"><img class="icon-img-content" :src="item.imgUrl"></div><p class="icon-desc">{{item.desc}}</p></div></swiper-slide><div class="swiper-pagination" slot="pagination"></div></swiper></div></template><script>export default {name:'HomeIcons',data (){return {// 显示控制点swiperOption: {pagination: '.swiper-pagination'},// 将数据写在data中 视图层直接循环渲染iconList:[{id:'001',imgUrl:'/piao/fusion/1803/95/f3dd6c383aeb3b02.png',desc:'景点门票'},{id:'002',imgUrl:'/piao/fusion/1803/47/c2b659e048b11602.png',desc:'主题乐园'},{id:'003',imgUrl:'/piao/fusion/1803/ab/6f7d6e44963c9302.png',desc:'泡温泉'},{id:'004',imgUrl:'http://mp-piao-/mp_piao_admin_mp_piao_admin/admin/3/a40ee278d67000f2a29d2e20f6a029b3.png',desc:'自然风光'},{id:'005',imgUrl:'/piao/fusion/1804/5a/13ceb38dcf262f02.png',desc:'一日游'},{id:'006',imgUrl:'/piao/fusion/1803/97/02f5043b51b2102.png',desc:'鼓浪屿'},{id:'007',imgUrl:'/piao/fusion/1803/96/c70f1e85ae4a4f02.png',desc:'武夷山'},{id:'008',imgUrl:'/piao/fusion/1803/50/26ffa31b56646402.png',desc:'亲子游'},{id:'009',imgUrl:'/piao/fusion/1803/b8/c5dcdb58deec2402.png',desc:'玩转贵安'},{id:'010',imgUrl:'/piao/fusion/1803/b6/37560ece9c62b502.png',desc:'城市观光'}]}},// 通过计算属性来计算需要轮播的页数computed:{pages (){const pages = []this.iconList.forEach((item,index) => {//假如index=3 通过向上取整page=0 则该index展示在第一页 index>=8 则展示在第二页const page = Math.floor(index/8)if (!pages) {pages = []}pages.push(item)}) return pages}}}</script><style lang="stylus" scoped>@import '~styles/varibles.styl'.icons >>> .swiper-containeroverflow: hiddenheight: 0padding-bottom: 60%.iconposition:relativefloat: leftwidth: 25%height:0padding-bottom: 25%.icon-imgposition:absolutetop:0left:0right:0bottom:.44rembox-sizing:border-boxpadding:.1rem.icon-img-contentdisplay:blockmargin:0 autoheight:100%.icon-descposition:absoluteleft:0right:0bottom:0height:.44rempadding:.1remline-height:.44remtext-align:centercolor:$darkTextColor// 当文字描述过长,显示省略点overflow:hiddenwhite-space:nowraptext-overflow:ellipsis</style>

提交到线上仓库:

git add .git commit -m 'desc'git push --set-upstream origin index-iconsgit checkout master# 合并到master分支git merge origin/index-iconsgit push

开发推荐组件

老规矩创建分支"index-recommend",创建Recommend组件:在components文件夹中新建Recommend.vue文件。记得要在Home.vue中引用该组件。

完整代码:

<template><div><div class="recommend-title">猜你喜欢</div><ul><li :key='item.id' class="item border-bottom" v-for="item of recommendList"><img class="item-img" :src="item.imgUrl"><div class="item-info"><p class="item-title">{{item.title}}</p><p class="item-desc">{{item.desc}}</p><button class="item-button">查看详情</button></div></li></ul></div></template><script>export default {name: 'HomeRecommend',data (){return {recommendList:[{id:'001',imgUrl:'/sight/p0/1703/9d/9dd5987e5c7701f2a3.water.jpg_200x200_8b16531c.jpg',title:'福州明谷行馆',desc:'最好玩的地方'},{id:'002',imgUrl:'/sight/p0/1703/9d/9dd5987e5c7701f2a3.water.jpg_200x200_8b16531c.jpg',title:'福州明谷行馆',desc:'最好玩的地方'},{id:'003',imgUrl:'/sight/p0/1703/9d/9dd5987e5c7701f2a3.water.jpg_200x200_8b16531c.jpg',title:'福州明谷行馆',desc:'最好玩的地方'}]}}}</script><style lang="stylus" scoped>@import '~styles/varibles.styl'.recommend-titlemargin-top:.2remline-height: .8rembackground: #eeetext-indent:.2rem.itemoverflow:hiddendisplay:flexheight:1.9rem.item-imgwidth:1.7remheight:1.7rempadding:.1rem.item-infoflex:1padding:.1remmin-width:0.item-titleline-height:.54remfont-size:.32remellipsis().item-descline-height:.4remcolor:#cccellipsis().item-buttonmargin-top:.16remcolor:#fffline-height:.44rembackground:#ff9300padding:0 .1remborder-radius:.06rem</style>

周末去哪儿

还是在同样的分支下进行开发,只不过需要新建一个组件’Weekend.vue’。

完整代码:

<template><div><div class="recommend-title">周末去哪儿</div><ul><li :key='item.id' class="item border-bottom" v-for="item of recommendList"><div class="item-img-wrapper"><img class="item-img" :src="item.imgUrl"></div><div class="item-info"><p class="item-title">{{item.title}}</p><p class="item-desc">{{item.desc}}</p></div></li></ul></div></template><script>export default {name: 'HomeWeekend',data (){return {recommendList:[{id:'001',imgUrl:'/sight/source/1505/68/de862f94e383a6.jpg_r_640x214_f9df927b.jpg',title:'福州明谷行馆',desc:'最好玩的地方'},{id:'002',imgUrl:'/sight/source/1505/68/de862f94e383a6.jpg_r_640x214_f9df927b.jpg',title:'福州明谷行馆',desc:'最好玩的地方'},{id:'003',imgUrl:'/sight/source/1505/68/de862f94e383a6.jpg_r_640x214_f9df927b.jpg',title:'福州明谷行馆',desc:'最好玩的地方'}]}}}</script><style lang="stylus" scoped>@import '~styles/varibles.styl'.recommend-titlemargin-top:.2remline-height: .8rembackground: #eeetext-indent:.2rem.item-img-wrapperoverflow:hiddenheight:0padding-bottom:33.9%.item-imgwidth:100%.item-infoflex:1padding:.1remmin-width:0.item-titleline-height:.54remfont-size:.32remellipsis().item-descline-height:.4remcolor:#cccellipsis()</style>

Ajax获取首页数据

在前面的章节中,我们都是把数据给写死的,这节我们使用ajax动态的获取数据。

第一步还是先创建分支"index-ajax“。在vue中发送ajax可以由很多的工具供我们使用,比如fetchvue-resource、现在vue官方推荐使用axios,在于它非常的强大,它可以跨平台的发送请求。在浏览器可以帮你发送XHR的请求,在node服务器可以发送HTTP的请求。我们就用axios。

# 安装axiosnpm install axios --save

在一个网站中,一般都由n个组件组成,如果每个组件都发送一个请求的话,显然性能是非常的低。所以我们一般都是写在Home组件中统一发送一个。

在使用ajax的时候,作为前端的我们再没有获得数据文件之前,我们都是使用模拟的数据。所以请求的地址一般都是些的本地文件。但是在实际的开发环境中,需要把地址替换一下,但是在上线之前去修改代码时有风险的,那要怎么做才能解决一些问题?

我们可以在项目中的config/index.js文件中的proxyTable属性中去添加以下内容,表示但我们请求服务器地址的时候,但时服务器有没有找到该文件,vue则会自动的代替为我们的本地地址文件。

//该功能为webpack-dev-server提供proxyTable: {'/api':{target: 'http://localhost:8080',pathRewrite:{//当访问以api开头的就跳转'^/api':'/static/mock'}}}

我们现在本地创建一个模拟的数据。模拟的数据我们放在static文件夹之下。我们新建一个文件夹mock以及mock下的index.json文件。

由于该文件是我们自己创建的数据,并不希望把它提交到我们的仓库中去,所以我们可以在gitignore中把该文件给忽略。

添加该文件夹路径即可static/mock

Home.vue

<script>//....省略了其他组件代码import axios from 'axios'export default {name: 'Home',components: {HomeHeader, HomeSwiper,HomeIcons,HomeRecommend,HomeWeekend},methods:{getHomeInfo (){// 虽然这里我们写的是api的开头的地址,但是vue已经帮我们跳转到了我们本地的json文件axios.get('/api/index.json').then(this.getHomeInfoSucc)},getHomeInfoSucc (res){//成功获取到本地json数据console.log(res)}},mounted (){this.getHomeInfo()}}</script>

首页父子组件数据传递

接着上一节的内容写,我们直接先Home.vue中写。在data函数中定义相关的变量,并将这些变量传递给组件

<template><div><home-header :city="city"></home-header><home-swiper :list="swiperList"></home-swiper><home-icons :list="iconsList"></home-icons><home-recommend :list="recommendList"></home-recommend><home-weekend :list="weenkendList"></home-weekend></div></template><script>data (){return {city:"",swiperList:[],iconsList:[],recommendList:[],weenkendList:[]}}</script>

再到各组件中改写一下:把我们前面写死的代码都给删除了。使用props接收一下传递过来的值。

<template><div class="wrapper"><!-- v-if 的作用是解决轮播默认显示的最后一张,因为在没有获取到数据之前,渲染是一个空数组。判断如果是空数组就不进行渲染 --><swiper :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,//使用autoplay就可以实现间隔3秒自动切换轮播图autoplay:3000}}},computed:{showSwiper(){return this.list.length}}}</script>

其它的组件也是同上面的写法一致。模仿着写就可以了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。