vue项目---仿写音乐app----遇到的问题及解决总结

0.https://y.qq.com/m/index.html
1. 基于router-link的导航跳转 :

    html:
        <router-link tag="div" :to="item.path" 
            class="tab-item tCenter" v-for="(item,index) in tabLists"
            exact       
        ><span class="tab-link">{{item.title}}</span></router-link>
    css:    
            .tab-link
                padding-bottom:5px
            &.router-link-active    
                .tab-link
                    color:#ffcd32
                    border-bottom:2px solid #ffcd32
    js:
        tabLists:[{"path":"/","title":"推荐"},{"path":"/singer","title":"歌手"},{"path":"/rank","title":"排行"},{"path":"/search","title":"搜索"}],                
    index.js:
        {
          path: '/',
          component: Home,
          children:[{
              path: '/',
              component: Recommend,
          }, {
              path: '/singer',
              component: Singer,
          },{
              path: '/rank',
              component: Rank,
          },{
              path: '/search',
              component: Search,
          }]
        }
    注意:以上代码中 exact关键字 能帮助只允许一个router-link被激活,&.router-link-active定义了标签被激活的样式。    
    
2. 在vue中引用模块函数,如果是export default function fun(){},则import fun from "./"即可,如果是export function fun(){},则需要import {fun} from "./"

3. jsonp是可以实现跨越请求获取数据的,不是通过ajax,是通过新建一个标签,其src指向从而实现跨越请求。
    //引入jsonp
    import originJsonp from "jsonp"
    
    //封装一个名叫jsonp的函数,url表示纯地址,data表示地址后面的参数,option为第三方插件jsonp的参数,返回一个promise,在这个promise中调用原始的第三方插件jsonp
    //根据执行的结果的是否保存执行promise
    export default function jsonp (url,data,option){
        url+=(url.indexOf("?")<0?"?":"&")+param(data);  //拼接url,如有原参数url有?号表示已经存在至少一个参数了,直接在后面拼接&,然后拼接param(data),如果没有?则先拼接?在拼接param(data)
        //最后拼接的样式如:https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg?g_tk=5381&uin=0&format=json&inCharset=utf-8&outCharset=utf-8&notice=0&platform=h5&needNewCode=1&_=1533171846949    
        return new Promise((resolve,reject)=>{
            originJsonp(url,option,(err,data)={  //调用第三方插件jsonp
                if(!err){
                    resolve(data)
                }else{
                    reject(err)
                }
            })
        })
    }
    
    //定义一个param函数,将参数data拼接在一起 data 格式{uname:"Ace",upwd:"123456"}
    function param(data){
        let url="";
        for(var k in data){
            let val=data[k] !== undefined ? data[k]:"";
            url+=`&${k}=${encodeURLCompoent(val)}`   ;   //ncodeURLCompoent是url地址的格式转换,让浏览器能识别
        }  //拼接结果的url = &uname=Ace&upwd=123456
        
        
        return url? url.substring(1):"";  //如果url存在就去掉第一个&返回uname=Ace&upwd=123456,否则返回“”
    }

4. 封装一个接口函数,调用该函数,直接向接口发生jsonp获取接口的数据
    import jsonp from "../common/js/jsonp.js"   //引用jsonp获取recommend推荐相关的数据
    import {commonParams,options} from "./config.js"   //获取通用参数
    
    //https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg接口需要配置如下参数
    //g_tk: 5381
    //uin: 0                     //qq号,没登录默认为0
    //format: json
    //inCharset: utf-8
    //outCharset: utf-8
    //notice: 0
    //platform: h5               //平台来源h5
    //needNewCode: 1
    //_: 1533171846949
    
    export function getRecommend(){
        const url="https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg";
        
        const data=Object.assign({},commonParams,{     //Object.assign()是es6的新语法,表示将多个对象合并成一个对象
            platform: 'h5',
            needNewCode:1,
            uin: 0 
        })
        
        return jsonp(url,data,options)
    }
    
    //在适当的时候调用接口函数getRecommend
    getRecommend().then((res)=>{
        if(res.code===ERR_OK){
            console.log(res)
        }
    })
    
5. 新思路,将通用的对dom操作的封装成一个通用的js文件如dom.js,如给标签添加删除class样式,可以封装成dom函数。可重复使用

6. 新思路:创建一个滑动加载better-scroll的组件,在任何时候,需要页面滑动的时候,包裹该组件即可
    <div class="bscroll" ref='wrap'>
        <slot></slot>    //这里是需要包裹的页面滑动的内容
    </div>
    import BScroll from "better-scroll"
    export default{
        props:{
            data:{
                type:Array,
                default:null
            },
            isClick:{
                type:Boolean,
                default:true
            },
            probeType:{    //该属性时当 probeType 为 1 的时候,会非实时(屏幕滑动超过一定时间后)派发scroll 事件;当 probeType 为 2 的时候,会在屏幕滑动的过程中实时的派发 scroll 事件        
                type:Number,    //当 probeType 为 3 的时候,不仅在屏幕滑动的过程中,而且在 momentum 滚动动画运行过程中实时派发 scroll 事件。如果没有设置该值,其默认值为 0,即不派发 scroll 事件
                default:1
            },
            listenScroll:{   //是否监听滚动事件的滚动位置,默认情况是不监听
                type:Boolean,
                default:false
            }
        },
        mounted(){
            this.$nextTick(()=>{
                this._initScroll();
            })
        },
        methods:{
            _initScroll(){
                if(!this.$refs.wrap){return}    //即初始化时刚开始传递过来的参数可能是undefined
                this.scroll=new BScroll(this.$refs.wrap,{
                    click:this.isClick,
                    probeType:this.probeType
                })
                if(this.listenScroll){    //如果调用该better-scroll组件传入的参数要求监听滚动距离,即this.listenScroll=true,就给better-scroll滚动时通过自定义事件传递滚动位置数据
                    var me=this;
                    this.scroll.on("scroll",(pos)=>{
                        me.$emit("scroll",pos)
                    })
                }
            },
            enable(){    //同步better-scroll的enable方法
                this.scroll && this.scroll.enable()
            },
            disable(){    //同步better-scroll的disable方法
                this.scroll && this.scroll.disable()
            },
            refresh(){    //同步better-scroll的refresh方法,重新计算滚动高度
                this.scroll && this.scroll.refresh()
            },
            scrollTo(){     //同步better-scroll的scrollTo方法,滚动到页面指定位置高度,因为需要带有参数,所有用apply()调用原来函数 的可传入参数
                this.scroll && this.scroll.scrollTo.apply(this.scroll,arguments)
            },
            scrollToElement(){     //同步better-scroll的scrollToElement方法,滚动到页面指定位置元素标签处,因为需要带有参数,所有用apply()调用原来函数 的可传入参数
                this.scroll && this.scroll.scrollToElement.apply(this.scroll,arguments)
            }
        },
        watch:{
            data(){  //传入的数据发生改变,重新计算滚动高度
                this.$nextTick(()=>{
                    this.refresh();
                })
            }
        }
        
    }
//    引用better-scroll页面组件
    import ReBscroll from "../base/bscroll.vue"
    <div class="abs recommend">      //注意recommend必须有相对/觉得定位、recommend-scroll继承父元素的高宽,或者recommend-scroll必须相对绝对定位,且宽高
        <re-bscroll class="recommend-scroll">
            <div >
                <!--1.轮播图-->
                <re-swiper :imgLists="imgLists" ></re-swiper>
                <!--2.热门歌曲列表-->
                <recommend-list :lists="lists"></recommend-list>
            </div>
        </re-bscroll>
    </div>
    .recommend
        width: 100%
        top: 88px
        bottom: 0
        overflow:hidden
        .recommend-scroll
            height: 100%
            
    scrollEle(a){
        this.$refs.listView.scrollToElement(this.$refs.listGroup[a],0);   //接受子元素传递过来的字母下标索引,并滚动到该位置
    }

7. <img @load="imgLoad"/>  //表示图片的onload加载完成之后执行的函数,如用于,在使用了better-scroll插件计算滚动高度时,需要在图片加载完成撑起图片高度之后,在重新计算滚动高度
    即this.refresh(); 如在imgLoad方法中 if(!this.checkload){this.refresh();this.checkload=true } ,表示第一张图片加载完成之前this.checkload不存在,带图片加载完成之后
    就执行一次计算滚动页面高度,然后定义this.checkload=true,之后图片在加载完成时,应该已经撑起滚动页面高度,且this.checkload已经存在,避免了很多图片,每张图片加载一次
    就要重复计算页面高度的繁琐执行。
    
8. vue-lazyload:图片懒加载的第三插件,即    页面滚动到底部时才执行加载更多的图片,避免的一次性加载太多图片。
    npm install vue-lazyload --save
    在main.js中
    import VueLazyLoad from "vue-lazyload"
    Vue.use(VueLazyLoad,{
        loading:require("./common/image/default.png");   //加载中暂时存放的图片,相对main.js的替代图片的位置
    })
    使用:
    <img  v-lazy="url"/>  //将src/:src被v-lazy代替即可,也可用于背景图,详情见官网
    
9. swiper无法实现loop:true可能选原因是远程获取图片,远程的图片动态不定时改变。


10. 根据对象的key值排序Object.keys(map).sort((a,b)=>{ })

11. vue支持@touchstart事件:<div class="abf tCenter singer-abc" @touchstart="touchWhich"/>

12. 解决[Intervention] Unable to preventDefault inside passive event listener due to target being treated as报错:
    两个方案:

    12.1、注册处理函数时,用如下方式,明确声明为不是被动的
    window.addEventListener('touchmove', func, { passive: false })
    
    12.2、应用 CSS 属性 touch-action: none; 这样任何触摸事件都不会产生默认行为,但是 touch 事件照样触发。
    touch-action 还有很多选项,
    
13. 配置跳转子路由:  子路由并非真正的页面,只是覆盖在父路由上的一层蒙层,所有层级z-index要高
    children:[{
          path: ':id',
          component: SingerDetail,
          }]
    this.$router.push({
        path:`/singer/${a.id}`
    })

猜你喜欢

转载自blog.csdn.net/qq_42231156/article/details/82949894
今日推荐