vue进阶之——仿去哪App

2020-04-11  本文已影响0人  无题syl

去哪App源码:

https://gitee.com/syinling/syl-travel.git

一.技术栈:

Vue-cli+axios+better-scroll+sass-loader+swiper+mockjs+iconfont

二.关于移动端适配问题的css样式

import '../assets/style/reset.css'      各种浏览器适配样式

import '../assets/style/border.css'   1像素边框问题

三.vue-cli项目框架搭建

cmd进入系统命令命令:

全局安装这个工具

1.npm install -g @vue/cli

2.vue create  travel

个人建议:自己可以先创建自己的模板,项目可以套用这个,就不需要反复下载安装包了

安装:vue-router/vuex/vue-axios/各种需要的插件

在项目src文件夹下,创建store/router目录

````

import Vuefrom 'vue'

import Vuex from 'vuex'

import cityListfrom './modules/citylist.js'

Vue.use(Vuex);

let store =new Vuex.Store({

modules:{

cityList     //store也可以有路由

},

});

export default store;

router也一样    main.js中记得引用

+page文件夹  存放各个页面

+mock文件夹  mock数据

+utils文件夹   存放第三方例如axios代码

+plugin文件夹  可以自定义混入插件 代码实例:

export  default {

install(Vue) {

Vue.mixin({

filters:{

// filterABC(value) {

//    return 'ABCDEFGHJKLMNPQRSTWXYZ'[(value%15)];

//}

            },

methods:{

},

data(){

return {

}

}

});

}

}

````

mian.js中引用 这个插件:

````

import SylPluginfrom '@/plugin'

Vue.use(SylPlugin,{});

+config文件夹  可以说明全局的变量

例:

const BASE_URL_DEV='';

const BASE_URL_TEST='http://xxxx.xxx.xx.xx:8081';

const BASE_URL_PRO='http://xxxx.xxx.xx.xx:8082';

//减少使用魔法数字,使用解构类型,让代码更加语义化

const MODE_TYPE={

DEV:0,

TEST:1,

PRO:2

};

const MODE=MODE_TYPE.DEV;

export const BASE_URL=[BASE_URL_DEV,BASE_URL_TEST,BASE_URL_PRO][MODE];

export const SUBJECT_TYPE={

DX:0,

DUOX:1,

PD:2,

JD:3,

};

····

在根目录下可以加上vue.config.js 设置代理等 

项目搭建完毕

四.项目vue新增知识点

4.1. `home页面----header.vue 中  城市名称的缓存  页面刷新,城市不变`

home页面中的获取首页信息gethomeInfo根据城市的变化而重新请求,当选择城市不变时,不需要再次请求

因为有多个组件用到城市,所以把获取城市信息放在store中,另外在store的data中定义当前城市citecity

在store mitations中,利用localStorage,把当前城市赋值给本地存储

````

changecity(state,payload){

try{  //使用try{}catch{}避免因部分浏览器未开启本地缓存服务而报错

localStorage.setItem('site',payload);

state.sitecity=localStorage.getItem('site');

}catch(e) {

console.log(e);

}

//state.sitecity=payload;

},

````

在data中,这只默认城市,以及获取当前缓存城市

````

sitecity:localStorage.getItem('site')||'北京',

````

在城市列表页,cityList.vue中

````

movecity(city){

// console.log('111');

  if(city!==this.sitecity){

//避免相同城市二次请求  应该写在另一个请求上

//城市不一样时 状态state变成false

        this.changecity(city);

}

this.$router.push('/')

}

````

点击热门城市时,触发movecity方法   cityList --->store(改变城市)-->sitecity改变

当city!==this.sitecity时,也就是说同一城市时,直接跳转到首页(这里可以不用判断  哈哈)

在home页面中

````

created() {

//加上keep-alive 这个函数在初始时走一次  之后在切换路由时,就不走了

//如果没加,则重进页面会再次执行

// console.log('111');

            this.getHomeInfo();

},

activated() {

//在页面重新显示时候执行

//把城市换了,再次请求axios 在这写  和监听城市变化 一样啊

        },

watch:{

sitecity(){

this.getHomeInfo();

}

}

````

监听sitecity时是否变化,从而判断要不要重新获取城市详情,所以之前那个判断可以不要

4.2.函数节流

利用setTimeout函数设置延后处理后续代码

城市列表页搜索功能  设置100毫秒后执行搜索

//这里还需研究 在用户输入100毫秒后在执行,函数节流 如果用户在100毫秒内输入完自己想要的内容,这个应该用处不大,如果用户、

//在100毫秒内没输入完自己想要的,函数就开始搜索,出来不是自己真正想要的内容,所以再次输入时,应该清除之前的结果

//是不是函数每走一遍就生成一个setTimeOut()函数呢??? 不销可能存在自己的作用域

代码:

````

<div class="down">

<input type="text" placeholder="请输入城市名或拼音"  v-model="content"></input>

</div>

<div class="search" v-show="content">

<ul>

<li v-for="iteminlist" :key="item.id">{{item.name}}</li>

</ul>

</div>

````

````

content(val){

//当用户输入时  实时触发这个函数

    this.list=[];

if(time){

        clearTimeout(time);

}

let time=setTimeout(()=>{

`//双重循环查找数组`

Object.values(this.citylist).forEach(v=>{

//循环查找数组

            v.forEach(r=>{

if(r.spell.indexOf(val)>-1||r.name.indexOf(val)>-1){

this.list.push(r)

}

})

});

//console.log(this.list);

// if(!this.list.length){

//    // let e=document.createElement('div');

//    document.getElementById('a').innerText='未找到';

// }

    },100);

}

````

4.3.better-scroll插件的使用

better-scroll优点:

可能是目前最好用的移动端滚动插件

使用步骤:

可看文档介绍 · better-scroll

1.安装插件 

npm install better-scroll -s

2.在所需组件中引入

import  BScroll from 'better-scroll'

3.使用组件

在dom中的解构

````

<div ref='wrapper'>

<div class='content'>

//你所滚动的内容

</div>

</div>

````

````

注意:滚动区域外要有父级包围(外要有2层,很重要)

````

父级的css样式

````

.wrapper{

position:absolute;

top:1.3rem;

left:0;

right:0;

bottom:0;

overflow:hidden;

}

````

注意:父级一定要有自己的高度,且子集的高度要高于父级,并且加上overflow:hidden

初始化插件

在组件的mounted生命周期钩子函数中:

````

mounted(){

this.$nextTick(()=>{

this.scroll =new BScroll(this.$refs.wrapper,{click:true});

})

}

````

注意:

1.插件初始化需要具体元素,所以在dom树中,用vue  ref来确定具体dom节点

2.初始化放在nextTick方法中,避免dom树未渲染完成从而造成子元素(滚动内容)高度计算不准确

出现问题:

点击事件  :   可能因不能用,在配置中加上 {click:true}即可

滚动失效:手机滚动和键盘滚动不一样,本来是可以滚动的 (已解决)

返回顶部:未解决

4.4.递归组件的使用

使用场景:

票价的多级显示

递归组件的应用

使用原因:

对于上面的嵌套层级关系,我们完全可以使用循环来操作,但是,我们想一想,如果一天老板要求在水上乐园下面在加一层,二层,甚至更多层,这样一层一层嵌套,循环显然不是明智的算法考虑,所以我们用到了递归组件

定义:

在自己的组件中调用自己

使用说明:

1.个人认为,处理数据时关键一步  嵌套关系的data

```

"list":[

{

"title":"成人票",

"children":[

{

"title":"成人三联馆"

      },{

"title":"情侣双人游"

      },{

"title":"闺蜜团"

      }

]

},{

"title":"老人票",

"children":[

{

"title":"夕阳红旅游团"

      },{

"title":"老人三联馆"

      }

]

},{

"title":"儿童票",

"children":[{

"title":"亲子游"

    },{

"title":"儿童乐园",

"children":[{

"title":"水上游玩"

      },{"title":"侠盗猎车空中游"}]

}]}

]

```

2.模板代码处理

组件名:Recurrence

```

<template>

<div>

<div v-for="(item,index) in list" :key="index">

<div @click="activeIndex=index" style="cursor: pointer;border-bottom: .02rem lightblue solid;line-height: .4rem;padding:.1rem 0 ">

<span class="icon-icon-test iconfont" style="display: inline-block;height: .45rem;font-size: .4rem;text-align: center"></span>

<span style="display: inline-block;height: .45rem;font-size: .4rem;text-align: center;color: black;margin-left: .3rem">{{item.title}}</span>

</div>

<div v-if="item.children" v-show="activeIndex===index" class="item">

<Recurrence :list="item.children"></Recurrence>

</div>

</div>

</div>

</template>

```

3.组件有个来自父级的props:['list'],点击每一级会显示出下一级;

4.5.background-image处理渐变

对于css3 opacity 的认识      规定不透明度。从 0.0 (完全透明)到 1.0(完全不透明)

background-image:linear-gradient(角度,颜色)  to+方向 指定哪个地方结束

to bottom 就是从顶部到底部的过渡  相当于(180deg,rgba(0,0,0,0),rgba(0,0,0,0.8)

底部有阴影

4.6.画廊渐隐渐显效果 vue动画使用

定义一个fade组件,让包含在内的组件,显示或者隐藏有过渡的效果

```

<transition>

<slot></slot>

</transition>

```

```

.v-enter,.v-leave-to{

opacity:0;

}

.v-enter-active,.v-leave-active{

transition:opacity .5s;

}

```

vue动画过渡类

```

<Fade>

<Gallery v-show="isHidden"  @change="isHidden=!isHidden" :list="gallaryImg"></Gallery>

</Fade>

```

4.6.详情页 下拉显示header,渐显的效果

实现向下滚动详情页时,到了一定高度,头部标题切换效果

```

<div>

<div class="fanh" v-show="isfanh">

<router-link class="iconfont icon-fanhui" to="/" tag="div"  style=" font-size: .4rem; line-height: .52rem;"></router-link>

</div>

<div class="header"

        v-show="!isfanh"

    >

<span>

<router-link class="iconfont icon-fanhui" style="color: white;font-size: .4rem" to="/" ></router-link>

</span>

<span style="margin-left: 2.5rem">景点详情</span>

</div>

</div>

```

利用钩子函数设置监听事件

```

activated() {

//只要页面重新渲染就会执行

//监听事件  只要有下滑时,就会触发事件

    document.addEventListener('scroll',this.handelScroll);

},

deactivated() {

//对全局事件解绑  当前页面消失时,执行这个代码

    document.removeEventListener('scroll',this.handelScroll)

}

```

通过变量:isfanh控制是否显示

```

handelScroll(){

//如果向下滑动了60 则就会显示header

    let top=document.documentElement.scrollTop;

if(top>60){

//头部透明渐变效果

        this.isfanh=false

    }else{

this.isfanh=true;

}

}

```

animation过渡效果

css代码:

```

.header{

animation:move 3s linear 0s;

}

@keyframes move {

from{

opacity:0;

}to{

opacity:1      }

}

```

4.7.keep-alive

在App.vue中

```

<keep-alive>

<router-view></router-view>

</keep-alive>

```

对于数据的缓存,避免多次重复请求

```

created() {

//加上keep-alive 这个函数在初始时走一次  之后在切换路由时,就不走了

//如果没加,则重进页面会再次执行

// console.log('111');

    this.getHomeInfo();

},

```

可以把初始化的请求数据放在created中,把每次进入页面都要出发的放在activited中

保持页面的状态

A——>B——>A  希望返回到A页面时,还是第一次浏览时的位置

上一篇下一篇

猜你喜欢

热点阅读