美文网首页
vue进阶之——仿去哪App

vue进阶之——仿去哪App

作者: 无题syl | 来源:发表于2020-04-11 17:30 被阅读0次

    去哪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页面时,还是第一次浏览时的位置

    相关文章

      网友评论

          本文标题:vue进阶之——仿去哪App

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