最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

基于vue的移动端web音乐播放器的实现

来源:动视网 责编:小采 时间:2020-11-27 19:33:45
文档

基于vue的移动端web音乐播放器的实现

基于vue的移动端web音乐播放器的实现:这篇文章主要介绍了基于vue的移动端web音乐播放器的实现,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下项目初始项目GitHub地址: https://github.com/bjw1234/vu...项目演示地址: http://music.baijiawei.top学习这
推荐度:
导读基于vue的移动端web音乐播放器的实现:这篇文章主要介绍了基于vue的移动端web音乐播放器的实现,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下项目初始项目GitHub地址: https://github.com/bjw1234/vu...项目演示地址: http://music.baijiawei.top学习这


项目初始化

// 安装vue脚手架工具
npm install vue-cli -g

// 初始化webpack应用
vue init webpack vue-music

项目中使用到的mixin

// 背景图片
bg-image($url)
 background-image: url($url + "@2x.png")
 @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
 background-image: url($url + "@3x.png")

// 不换行
no-wrap()
 text-overflow: ellipsis
 overflow: hidden
 white-space: nowrap

// 扩展点击区域
extend-click()
 position: relative
 &:before
 content: ''
 position: absolute
 top: -10px
 left: -10px
 right: -10px
 bottom: -10px

配置路径别名

resolve: {
 extensions: ['.js', '.vue', '.json'],
 alias: {
 '@': resolve('src'),
 'common': resolve('src/common')
 }
}

移动端300毫秒延时和点透问题

fastclick:处理移动端click事件300毫秒延迟和点透问题。

先执行安装fastclick的命令。

npm install fastclick --save

之后,在main.js中引入,并绑定到body

import FastClick from 'fastclick';

FastClick.attach(document.body);

注意: 当fastclick和其他的模块点击冲突,导致点击事件不可用时,可以给对应的dom添加needsclick类来解决。

对jsonp进一步封装

下载原始的jsonp模块:

npm install jsonp --save

再次封装:

import originJSONP from 'jsonp';

/**
 * 做一个简单的jsonp封装
 * @param url
 * @param data
 * @param option
 * @return {Promise}
 */
export default function jsonp (url, data, option) {
 return new Promise((resolve, reject) => {
 url = `${url}?${_obj2String(data)}`;
 originJSONP(url, option, (err, data) => {
 if (!err) {
 resolve(data);
 } else {
 reject(err);
 }
 });
 });
};

function _obj2String (obj, arr = [], index = 0) {
 for (let item in obj) {
 arr[index++] = [item, obj[item]];
 }
 return new URLSearchParams(arr).toString();
}

vue的生命周期函数

注意: 当使用keep-alive组件时,当切换到其他路由,会调用前组件的deactivated钩子函数,当切回来时,会调用activated函数。

better-scroll组件的使用

注意:

  • 1.better-scroll只处理容器的第一个子元素的滚动。

  • 2.一定得保证子元素超出父元素,这样才能正确的滚动。

  • 初始化:

    import BScroll from 'better-scroll';
    
    let wrapper = document.querySelector('.wrapper');
    let scroll = new BScroll(wrapper,{
     // 配置项
    });
    .wrapper
     position: fixed
     width: 100%
     top: 88px
     bottom: 0
     .scroll
     height: 100%
     overflow: hidden

    问题排查(无法滚动原因:)

  • 1.内层容器的高度没有超过外层容器。

  • 2.dom没有渲染完毕就初始化better-scroll

  • 3.改变了dom的显隐性,没有对scroll进行重新计算。

  • 针对3:当dom显示出来之后,加20毫秒延时,然后调用refresh方法。

  • 开发模式下的请求代理

    当在开发模式下,需要使用一些后台接口,为了防止跨域问题,vue-cli提供了非常强大的http-proxy-middleware包。可以对我们的请求进行代理。
    进入 config/index.js 代码下如下配置即可:

    proxyTable: {
     '/getDescList': {
     target: 'http://127.0.0.1:7070/desclist', // 后端接口地址
     changeOrigin: true,
     // secure: false,
     pathRewrite: {
     '^/getDescList': '/'
     }
     }
    }

    负外边距的作用效果

  • marin-left或者margin-top是负值:它会将元素在相应的方向进行移动。left就是左右方向移动,top就是上下方向移动。也就是会使元素在文档流里的位置发生变化

  • margin-right或者margin-bottom是负值:它不会移动该元素(该元素不变化),但会使该元素后面的元素往前移动。也就是说,如果margin-bottom为负值,那么该元素下面的元素会往上移动;如果margin-right为负值,那么该元素右边的元素会往左移动,从而覆盖该元素。

  • 配置子路由

    需求:在歌手页面下需要一个歌手详情页。

    export default new Router({
     routes:[
     {
     path: '/',
     component: Singer,
     children: [
     {
     path: ':id',
     compoonent: SingerDetail
     }
     ]
     },
     ...
     ]
    });

    当监听到用户点击之后进行路由跳转:

    this.$router.push({
     path: `singer/${singer.id}`
    });
    
    // 别忘了在`Singer`页面中:
    <router-view></router-view>

    Vuex的使用

    Vuex是什么?

    简单来说:Vuex解决项目中多个组件之间的数据通信和状态管理。

    Vuex将状态管理单独拎出来,应用统一的方式进行处理,采用单向数据流的方式来管理数据。用处负责触发动作(Action)进而改变对应状态(State),从而反映到视图(View)上。

    Vuex怎么用?

    安装:

    npm install vuex --save

    引入:

    import Vuex from 'vuex';
    import Vue from 'Vue';
    
    Vue.use(Vuex);

    Vuex的组成部分

    使用Vuex开发的应用结构应该是这样的:

  • State

  • State负责存储整个应用的状态数据,一般需要在使用的时候在根节点注入store对象,后期就可以使用this.$store.state直接获取状态。

    import store from './store';
    ..
    
    new Vue({
     el: '#app',
     store,
     render: h => h(App)
    });

    那么这个store又是什么?从哪来的呢?

    store可以理解为一个容器,包含应用中的state。实例化生成store的过程是:

    const mutations = {...};
    const actions = {...};
    const state = {...};
    
    // 实例化store对象并导出
    export defautl new Vuex.Store({
     state,
     actions,
     mutations
    });
  • Mutations

  • 中文意思是“变化”,利用它可以来更改状态,本质上就是用来处理数据的函数。
    store.commit(mutationName)是用来触发一个mutation的方法。
    需要记住的是,定义的mutation必须是同步函数。

    const mutations = {
     changState(state) {
     // 在这里改变state中的数据
     }
    };
    
    // 可以在组件中这样触发
    this.$store.commit('changeState');
  • Actions

  • Actions也可以用于改变状态,不过是通过触发mutation实现的,重要的是可以包含异步操作。

    直接触发可以使用this.$store.dispatch(actionName)方法。

    简单的多组件数据交互

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    // 状态
    const state = {
     singer: {}
    };
    
    // 跟踪状态的变化
    const mutations = {
     setSinger (state, singer) {
     state.singer = singer;
     }
    };
    
    // 实例化store对象
    export default new Vuex.Store({
     state,
     mutations
    });
    
    // 在singer组件中提交数据
    this.$store.commit('setSinger',singer);
    
    // 在singer-detail组件中接收数据
    let singer = this.$store.state.singer;

    vuex稍微复杂点的使用

    在上面的小栗子中,我们把satemutations等其他一些内容写在了一起,
    但是这种方式不适合大型点的项目。最好能将这些内容拎出来,单独作为一个文件来使用。

    在src/store目录中新建以下文件:

  • state.js 用于存储状态信息

  • const sate = {
     singer: {} 
    };
    
    export default state;
  • mutation-types.js 保存一些常量(mutations中函数的函数名)

  • export const SET_SINGER = 'SET_SINGER';
  • mutations.js 用于更改状态(state中的数据)

  • import * as types from './mutation-types';
    
    // 通过这个函数可以传入payload信息
    const mutations = {
     [types.SET_SINGER](state,singer){
     state.singer = singer;
     }
    };
    
    export default mutations;
  • getters.js 对状态获取的封装

  • export const singer = state => state.singer;
  • actions.js 对mutation进行封装,或者执行一些异步操作

  • // 暂时没有什么异步操作
  • index.js store的入口文件

  • // 入口文件
    import Vue from 'vue';
    import Vuex from 'vuex';
    import state from './state';
    import mutations from './mutations';
    import * as actions from './actions';
    import * as getters from './getters';
    import createLogger from 'vuex/dist/logger';
    
    Vue.use(Vuex);
    
    // 调试环境下开启严格模式
    const debug = process.env.NODE_ENV !== 'production';
    
    // 创建store对象并导出
    export default new Vuex.Store({
     state,
     actions,
     getters,
     mutations,
     strict: debug,
     plugins: debug ? [createLogger()] : []
    });

    使用:

    // main.js中引入
    import store from './store';

    有了以上内容,那么我们就可以在业务中去使用了:

    例如:多组件之间的的数据交互。
    需求:singer组件中需要将用户点击的那个singer对象传递给组件singer-detail组件。

    singer.vue 组件中:

    // 使用这个语法糖
    import { mapMutations } from 'vuex';
    
    methods:{
     ...mapMutations({
     // 将这个函数(setSinger)和mutations中用于修改状态的函数关联起来
     setSinger: 'SET_SINGER'
     });
    }
    
    // 传参
    this.setSinger(singer);
    
    // 语法糖的本质
     this.$store.commit('setSinger', singer);

    singer-detail.vue 组件中:
    我们就可以去使用这个数据了,当然也是使用我们的语法糖啦。

    import { mapGetters } from 'vuex';
    
    export default {
     // 使用一个计算属性
     computed: {
     ...mapGetters([
     'singer' // 这个就是getters.js中的那个singer
     ]);
     },
     created(){
     console.log(this.singer);
     } 
    }
    
    // 语法糖的本质:
    let singer = this.$store.state.singer;

    js中给CSS添加prefix

    我们一定遇到过这种情况:
    需要用JS写CSS动画。但我们又不得不处理前缀的问题。

    所以一般是这样写的:

    this.$refs.image.style.transform = `scale(${scale})`;
    this.$refs.image.style.webkitTansform = `scale(${scale})`;
    ...

    那么问题来了,怎样用JS处理这种情况呢?

    思路:

  • 检测浏览器的能力。

  • 返回带着前缀的CSS样式。

  • 代码实现:

    let elementStyle = document.createElement('p').style;
    
    // 得到合适的浏览器前缀
    let vendor = (() => {
     let transformNames = {
     webkit: 'webkitTransform',
     Moz: 'MozTransform',
     O: 'OTransform',
     ms: 'msTransform',
     standard: 'transform'
     };
    
     for (let key in transformNames) {
     let support = elementStyle[transformNames[key]] !== undefined;
     if (support) {
     return key;
     }
     }
     return false;
    })();
    
    // 对外暴露的方法
    export function prefixStyle (style) {
     if (vendor === false) {
     return style;
     }
     if (vendor === 'standard') {
     return style;
     }
     let result = vendor + style.charAt(0).toUpperCase() + style.substr(1);
     return result;
    }

    使用案例:

    // 导入该模块
    import { prefixStyle } from 'common/js/dom';
    
    // 加了合适前缀的CSS属性
    const TRANSFORM = prefixStyle('transform');
    
    // 使用该CSS属性
    this.$refs.image.style[TRANSFORM] = `scale(${scale})`;

    移动端的touch事件

    随着触屏设备的普及,w3c为移动端web新增了touch事件。

    最基本的touch事件包括4个事件:

  • touchstart 当在屏幕上按下手指时触发

  • 当用户手指触摸到的触摸屏的时候触发。事件对象的 target 就是 touch 发生位置的那个元素。

  • touchmove 当在屏幕上移动手指时触发

  • 即使手指移出了 原来的target元素,但 touchmove 仍然会被一直触发,而且 target 仍然是原来的 target 元素。

  • touchend 当在屏幕上抬起手指时触发

  • 当用户的手指抬起的时候,会触发 touchend 事件。如果用户的手指从触屏设备的边缘移出了触屏设备,也会触发 touchend 事件。

    touchend 事件的 target 也是与 touchstarttarget 一致,即使已经移出了元素。

  • touchcancel 当一些更高级别的事件发生的时候(如电话接入或者弹出信息)会取消当前的touch操作,即触发touchcancel。一般会在touchcancel时暂停游戏、存档等操作。

  • 如果你使用了触摸事件,可以调用 event.preventDefault()来阻止鼠标事件被触发。

    与移动端相关的interface主要有三个:

  • TouchEvent 表示触摸状态发生改变时触发的event

  • 可以通过检查触摸事件的 TouchEvent.type 属性来确定当前事件属于哪种类型。

    dom.addEventListener('touchstart',(e) => {
     // 获取事件类型
     let type = e.type;
     // toch事件发生时那个位置的元素对象
     let target = e.target; 
     
    });
  • Touch 表示用户和触屏设备之间接触时单独的交互点(a single point of contact)

  • screenXscreenY:触点相对于屏幕左边缘或上边缘的x、y坐标。
    clientXclientY:触点相对于浏览器viewport左边缘或上边缘的x、y坐标。(不包含滚动距离)

    pageXpageY:触点相对于document的左边缘或上边缘的x、y坐标。与client不同的是,包含左边滚动的距离。

    target:触摸开始时的element。

    // 获取touchList
    let touchList = e.changedTouches;
    // 获取第i个touch对象
    let touch = touchList[i];
    
    touch.screenX
    touch.clientX
    touch.pageX
    touch.target
    ...
  • TouchList 表示一组touches。当发生多点触摸的时候才用的到。

  • 如果一个用户用三根手指接触屏幕(或者触控板), 与之相关的TouchList对于每根手指都会生成一个 Touch 对象, 共计 3 个.
    可以通过三种方式获取这个对象:

    dom.addEventListener('touchstart',(e) => {
     // 这个 TouchList对象列出了和这个触摸事件对应的那些发生了变化的 Touch 对象
     e.changedTouches
     // 这个TouchList列出了那些 touchstart发生在这个元素,并且还没有离开 touch surface 的touch point(手指)
     e.targetTouches
     // 这个 TouchList 列出了事件触发时: touch suface上所有的 touch point。
     e.touches
    });

    播放器内核开发

    audio标签

    对于音乐的播放,我们使用了audio标签,监听它的事件和操作DOM,可以达到对音乐播放、
    暂停、进度控制等操作。

    <audio ref="audio" :src="currentSongUrl"
     @canplay="songCanPlay"
     @error="songError"
     @ended="songEnd"
     @timeupdate="updateTime">
    </audio>

    audio进行操作

    let audio = this.$refs.audio;
    // 暂停和播放
    audio.pause();
    audio.play();
    
    // Audio对象的属性(部分)
    
    audio.currentTime // 设置或返回音频中的当前播放位置(以秒计)。
    
    audio.duration // 返回音频的长度(以秒计)。
    
    audio.loop // 设置或返回音频是否应在结束时再次播放。(默认false)
    
    audio.volume // 设置或返回音频的音量。[0,1]
    
    // Audio对象多媒体事件(Media Events)
    
    onerror // 加载发生错误时的回调
    
    ontimeupdate // 当播放位置改变时调用
    updateTime(e) {
     if(this.currentSongReady){
     // 获取当前播放的进度
     this.currentSongTime=e.traget.currentTime;
     }
    }
    oncanplay // 能够播放时调用
    
    // 通过监听这个事件,设置标志位,这个标志位可以帮助我们
    // 防止用户快速切换歌曲引起一些错误。
    songCanPlay(){
     this.currentSongReady = true;
    }
    
    
    onended // 到达结尾时调用
    
    onplay、onpause...

    进度条组件

    1.progress-bar.vue接收一个percent参数,用来显示当前播放的一个进度。

    2.对于进度条用户手动拖动进度的实现。

    <p class="progress-btn" ref="btn"
     @touchstart="touchStart"
     @touchmove="touchMove"
     @touchend="touchEnd">
    </p>

    思路:主要是通过监听ontouchstartontouchmoveontouchend事件来完成。

    // 首先得定义一个`touch`对象
    let touch = {};
    
    // 在监听的方法中
    touchStart(e){
     this.touch.initialized = true;
     // 获取touch的起始位置
     this.touch.startX = e.touches[0].pageX;
     // 获取整个进度条的宽度
     this.touch.barW = xxx;
     // 获取已经播放的进度
     this.touch.offset = xxx; 
    }
    
    touchMove(e){
     // 判断有无初始化
     ...
     // 获取用户滑动的距离
     let deltaX = e.touches[0].pageX - this.touch.startX;
     let barW = xxx; // 进度条的宽度 - 拖动btn的宽度
     let offset = Math.min(Math.max(0, this.touch.offset + detail), barW);
     
     // 最后设置btn的位置和progress的进度就OK
     ...
    }
    
    touchEnd(){
     this.touch.initialized = false;
     // 然后将进度推送出去就好了
     this.$emit('percentChange',percent);
    }

    svg实现圆形进度条

    <template>
     <p class="progress-circle">
     <svg :width="radius" :height="radius" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
     <circle class="progress-background" r="50" cx="50" cy="50" fill="transparent"/>
     <circle class="progress-bar" r="50" cx="50" cy="50" fill="transparent"
     :stroke-dasharray="dashArray"
     :stroke-dashoffset="offset"/>
     </svg>
     <slot></slot>
     </p>
    </template>

    通过svg可以实现各种进度条,有一个问题,怎样去动态的修改它的进度值呢?

    这就不能不提 SVG Stroke 属性

  • stroke 定义一条线,文本或元素轮廓颜色

  • stroke-width 文本或元素轮廓的厚度

  • stroke-dasharray 该属性可用于创建虚线

  • stroke-dashoffset 设置虚线边框的偏移量

  • OK,知道了以上属性,就足以实现一个可设置进度的SVG进度条了。

    思路:stroke-dasharray适用于创建虚线的,如果这个虚线长度为整个轮廓的周长呢。
    stroke-dashoffset可以设置虚线的偏移量,利用这两个属性,我们就可以完成对进度的控制。

    且看一个小栗子:

    所以,通过父组件传入的percent,不断地修改stroke-dashoffset就能达到进度的显示了。

    全屏和退出全屏

    // 全屏显示
    document.documentElement.webkitRequestFullScreen();
    // 退出全屏
    document.webkitExitFullscreen();
    
    // 1.得根据不同的浏览器添加前缀
    // 2.程序主动调用不管用,得用户操作才可以(点击按钮)

    歌词页的显示

    通过网络接口获取的歌词:

    对于歌词的解析,播放是通过一个插件lyric-parser完成的。

    这个插件很简单:
    1.通过正则把时间和对应的歌词切分出来创建成对象。
    2.当调用play方法时,通过定时器完成歌词的播放,并将对应的行号和歌词通过回调函数传递出去。

    当播放的歌词超过5行时,就可以使用封装的scroll组件完成滚动操作。

    if (lineNum > 5) {
     let elements = this.$refs.lyricLine;
     this.$refs.lyricScroll.scrollToElement(elements[lineNum - 5], 1000);
    } else {
     this.$refs.lyricScroll.scrollTo(0, 0, 1000);
    }

    Vue中的mixin

    为什么要使用mixin?

    多个组件公用一样的代码,我们可以将这部分抽离出来作为mixin,只要引入对应的组件中就可以了。

    例如下面的mixin

    import { mapGetters } from 'vuex';
    
    export const playListMixin = {
    
     mounted () {
     this.handlePlayList(this.playList);
     },
     // 当路由对应的页面激活时调用
     activated () {
     this.handlePlayList(this.playList);
     },
     watch: {
     playList (newPlayList) {
     this.handlePlayList(newPlayList);
     }
     },
     computed: {
     ...mapGetters([
     'playList'
     ])
     },
     methods: {
     // 这个方法需要对应的组件自己去实现,直接调用抛出错误
     handlePlayList () {
     throw new Error('Components must implement handlePlayList method.');
     }
     }
    };

    有了mixin我们在组件中就可以这样使用了:

    import { playListMixin } from 'common/js/mixin';
    
    export default{
     mixins: [playListMixin],
     ...
    }

    节流处理

    在搜索页面,我们需要处理用户的输入,然后向服务器发起请求。
    为了不必要的请求、节省流量和提高页面性能,我们都有必要做节流处理。

    在搜索框search-box这个基础组件中:

    // 在created钩子中,我们监听用户输入字符串(query)变化,然后将变化后的字符串
    // 提交给父组件
    
    // 可以看到在回调函数中,又包了一层debounce函数
    
    created () {
     this.$watch('query', debounce(() => {
     this.$emit('queryChange', this.query);
     }, 500));
    }

    所以debounce函数,就是我们的节流函数,这个函数,接收一个函数,返回一个新的函数

    function debounce(func,delay){
     let timer = null;
     return function(...args){
     if(timer){
     clearTimeout(timer);
     }
     timer = setTimeout(()=>{
     func.apply(this,args);
     },delay) 
     }
    }
    
    // 测试
    function show(){
     console.log('hello...');
    }
    
    var func = debounce(show,3000);
    
    // 调用
    func(); 
    
    // 连续调用时,没有超过三秒是不会有任何
    输出的

    animation动画

    语法:

    animation: name duration timing-function delay iteration-count direction fill-mode play-state;
    animation: 动画名称 执行时间 速度曲线 延时时间 执行次数 动画播放顺序 结束时应用的样式 播放的状态(paused|running)

    封装localStorage操作

    const __VERSION__ = '1.0.1';
    const store = {
     version: __VERSION__,
     storage: window.localStorage,
     session: {
     storage: window.sessionStorage
     }
    };
    
    // 操作store的api
    const api = {
     set (key, val) {
     if (this.disabled) {
     return false;
     }
     if (val === undefined) {
     return this.remove(key);
     }
     this.storage.setItem(key, this.serialize(val));
     return val;
     },
     get (key, val) {
     if (this.disabled) {
     return false;
     }
     let result = this.storage.getItem(key);
     if (!result) {
     return val;
     }
     return this.deSerialize(result);
     },
     getAll () {
     if (this.disabled) {
     return false;
     }
     let ret = {};
     for (let key in this.storage) {
     if (this.storage.hasOwnProperty(key)) {
     ret[key] = this.get(key);
     }
     }
     return ret;
     },
     remove (key) {
     if (this.disabled) {
     return false;
     }
     this.storage.removeItem(key);
     },
     removeAll () {
     if (this.disabled) {
     return false;
     }
     this.storage.clear();
     },
     forEach (cb) {
     if (this.disabled) {
     return false;
     }
     for (let key in this.storage) {
     if (this.storage.hasOwnProperty(key)) {
     cb && cb(key, this.get(key));
     }
     }
     },
     has (key) {
     if (this.disabled) {
     return false;
     }
     return key === this.get(key);
     },
     serialize (val) {
     try {
     return JSON.stringify(val) || undefined;
     } catch (e) {
     return undefined;
     }
     },
     deSerialize (val) {
     if (typeof val !== 'string') {
     return undefined;
     }
     try {
     return JSON.parse(val) || undefined;
     } catch (e) {
     return undefined;
     }
     }
    };
    
    // 扩展store对象
    Object.assign(store, api);
    Object.assign(store.session, api);
    
    // 浏览器能力检测
    try {
     let testKey = 'test_key';
     store.set(testKey, testKey);
     if (store.get(testKey) !== testKey) {
     store.disabled = true;
     }
     store.remove(testKey);
    } catch (e) {
     store.disabled = true;
    }
    
    export default store;

    路由懒加载

    为什么需要?

    如果开发的App太大的话,就会导致首屏渲染过慢,为了增强用户体验,加快渲染速度,
    需要用到懒加载功能。让首屏的内容先加载出来,其他路由下的组件按需加载。

    vue官网描述:

    异步组件
    在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。
    为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。
    Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。
    const AsyncComponent = () => ({
     // 需要加载的组件 (应该是一个 `Promise` 对象)
     component: import('./MyComponent.vue'),
     // 异步组件加载时使用的组件
     loading: LoadingComponent,
     // 加载失败时使用的组件
     error: ErrorComponent,
     // 展示加载时组件的延时时间。默认值是 200 (毫秒)
     delay: 200,
     // 如果提供了超时时间且组件加载也超时了,
     // 则使用加载失败时使用的组件。默认值是:`Infinity`
     timeout: 3000
    })

    注意:如果你希望在 Vue Router 的路由组件中使用上述语法的话,你必须使用 Vue Router 2.4.0+ 版本。

    当然为了简单起见:

    router/index.js路由配置文件中这样加载组件:

    // import Recommend from '@/components/recommend/recommend';
    const Recommend = () => ({
     component: import('@/components/recommend/recommend')
    });

    文档

    基于vue的移动端web音乐播放器的实现

    基于vue的移动端web音乐播放器的实现:这篇文章主要介绍了基于vue的移动端web音乐播放器的实现,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下项目初始项目GitHub地址: https://github.com/bjw1234/vu...项目演示地址: http://music.baijiawei.top学习这
    推荐度:
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top