国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

基于vue的移動端web音樂播放器

chemzqm / 1164人閱讀

摘要:代碼實(shí)現(xiàn)得到合適的瀏覽器前綴對外暴露的方法使用案例導(dǎo)入該模塊加了合適前綴的屬性使用該屬性移動端的事件隨著觸屏設(shè)備的普及,為移動端新增了事件。如果用戶的手指從觸屏設(shè)備的邊緣移出了觸屏設(shè)備,也會觸發(fā)事件。

聲明

以下只是學(xué)習(xí)完慕課網(wǎng)huangyi老師實(shí)戰(zhàn)視頻課程的筆記內(nèi)容,僅供個人參考學(xué)習(xí)使用。
如果對Vue2.0實(shí)戰(zhàn)高級-開發(fā)移動端音樂WebApp感興趣的話,請移步這里:
https://coding.imooc.com/clas...
謝謝。

項(xiàng)目GitHub地址: https://github.com/bjw1234/vu...

項(xiàng)目演示地址: http://music.baijiawei.top

項(xiàng)目初始化
// 安裝vue腳手架工具
npm install vue-cli -g

// 初始化webpack應(yīng)用
vue init webpack vue-music
項(xiàng)目中使用到的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

// 擴(kuò)展點(diǎn)擊區(qū)域
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毫秒延時和點(diǎn)透問題

fastclick:處理移動端click事件300毫秒延遲和點(diǎn)透問題。

先執(zhí)行安裝fastclick的命令。

npm install fastclick --save

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

import FastClick from "fastclick";

FastClick.attach(document.body);

注意: 當(dāng)fastclick和其他的模塊點(diǎn)擊沖突,導(dǎo)致點(diǎn)擊事件不可用時,可以給對應(yīng)的dom添加needsclick類來解決。

對jsonp進(jìn)一步封裝

下載原始的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的生命周期函數(shù)

注意: 當(dāng)使用keep-alive組件時,當(dāng)切換到其他路由,會調(diào)用前組件的deactivated鉤子函數(shù),當(dāng)切回來時,會調(diào)用activated函數(shù)。

better-scroll組件的使用

注意:

1.better-scroll只處理容器的第一個子元素的滾動。

2.一定得保證子元素超出父元素,這樣才能正確的滾動。

初始化:

import BScroll from "better-scroll";

let wrapper = document.querySelector(".wrapper");
let scroll = new BScroll(wrapper,{
    // 配置項(xiàng)
});
.wrapper
    position: fixed
    width: 100%
    top: 88px
    bottom: 0
    .scroll
        height: 100%
        overflow: hidden

問題排查(無法滾動原因:)

1.內(nèi)層容器的高度沒有超過外層容器。

2.dom沒有渲染完畢就初始化better-scroll

3.改變了dom的顯隱性,沒有對scroll進(jìn)行重新計算。

針對3:當(dāng)dom顯示出來之后,加20毫秒延時,然后調(diào)用refresh方法。

開發(fā)模式下的請求代理

當(dāng)在開發(fā)模式下,需要使用一些后臺接口,為了防止跨域問題,vue-cli提供了非常強(qiáng)大的http-proxy-middleware包。可以對我們的請求進(jìn)行代理。
進(jìn)入 config/index.js 代碼下如下配置即可:

proxyTable: {
  "/getDescList": {
    target: "http://127.0.0.1:7070/desclist", // 后端接口地址
    changeOrigin: true,
    // secure: false,
    pathRewrite: {
      "^/getDescList": "/"
    }
  }
}
負(fù)外邊距的作用效果

marin-left或者margin-top是負(fù)值:它會將元素在相應(yīng)的方向進(jìn)行移動。left就是左右方向移動,top就是上下方向移動。也就是會使元素在文檔流里的位置發(fā)生變化

margin-right或者margin-bottom是負(fù)值:它不會移動該元素(該元素不變化),但會使該元素后面的元素往前移動。也就是說,如果margin-bottom為負(fù)值,那么該元素下面的元素會往上移動;如果margin-right為負(fù)值,那么該元素右邊的元素會往左移動,從而覆蓋該元素。

配置子路由

需求:在歌手頁面下需要一個歌手詳情頁。

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

當(dāng)監(jiān)聽到用戶點(diǎn)擊之后進(jìn)行路由跳轉(zhuǎn):

this.$router.push({
  path: `singer/${singer.id}`
});

// 別忘了在`Singer`頁面中:
Vuex的使用 Vuex是什么?

簡單來說:Vuex解決項(xiàng)目中多個組件之間的數(shù)據(jù)通信和狀態(tài)管理。

Vuex將狀態(tài)管理多帶帶拎出來,應(yīng)用統(tǒng)一的方式進(jìn)行處理,采用單向數(shù)據(jù)流的方式來管理數(shù)據(jù)。用處負(fù)責(zé)觸發(fā)動作(Action)進(jìn)而改變對應(yīng)狀態(tài)(State),從而反映到視圖(View)上。

Vuex怎么用?

安裝:

npm install vuex --save

引入:

import Vuex from "vuex";
import Vue from "Vue";

Vue.use(Vuex);

Vuex的組成部分

使用Vuex開發(fā)的應(yīng)用結(jié)構(gòu)應(yīng)該是這樣的:

State

State負(fù)責(zé)存儲整個應(yīng)用的狀態(tài)數(shù)據(jù),一般需要在使用的時候在根節(jié)點(diǎn)注入store對象,后期就可以使用this.$store.state直接獲取狀態(tài)。

import store from "./store";
..

new Vue({
    el: "#app",
    store,
    render: h => h(App)
});

那么這個store又是什么?從哪來的呢?

store可以理解為一個容器,包含應(yīng)用中的state。實(shí)例化生成store的過程是:

const mutations = {...};
const actions = {...};
const state = {...};

// 實(shí)例化store對象并導(dǎo)出
export defautl new Vuex.Store({
    state,
    actions,
    mutations
});

Mutations

中文意思是“變化”,利用它可以來更改狀態(tài),本質(zhì)上就是用來處理數(shù)據(jù)的函數(shù)。
store.commit(mutationName)是用來觸發(fā)一個mutation的方法。
需要記住的是,定義的mutation必須是同步函數(shù)。

const mutations = {
    changState(state) {
        // 在這里改變state中的數(shù)據(jù)
    }
};

// 可以在組件中這樣觸發(fā)
this.$store.commit("changeState");

Actions

Actions也可以用于改變狀態(tài),不過是通過觸發(fā)mutation實(shí)現(xiàn)的,重要的是可以包含異步操作。

直接觸發(fā)可以使用this.$store.dispatch(actionName)方法。

簡單的多組件數(shù)據(jù)交互
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

// 狀態(tài)
const state = {
  singer: {}
};

// 跟蹤狀態(tài)的變化
const mutations = {
  setSinger (state, singer) {
    state.singer = singer;
  }
};

// 實(shí)例化store對象
export default new Vuex.Store({
  state,
  mutations
});

// 在singer組件中提交數(shù)據(jù)
this.$store.commit("setSinger",singer);

// 在singer-detail組件中接收數(shù)據(jù)
let singer = this.$store.state.singer;
vuex稍微復(fù)雜點(diǎn)的使用

在上面的小栗子中,我們把satemutations等其他一些內(nèi)容寫在了一起,
但是這種方式不適合大型點(diǎn)的項(xiàng)目。最好能將這些內(nèi)容拎出來,多帶帶作為一個文件來使用。

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

state.js 用于存儲狀態(tài)信息

const sate = {
    singer: {}    
};

export default state;

mutation-types.js 保存一些常量(mutations中函數(shù)的函數(shù)名)

export const SET_SINGER = "SET_SINGER";

mutations.js 用于更改狀態(tài)(state中的數(shù)據(jù))

import * as types from "./mutation-types";

// 通過這個函數(shù)可以傳入payload信息
const mutations = {
    [types.SET_SINGER](state,singer){
        state.singer = singer;
    }
};

export default mutations;

getters.js 對狀態(tài)獲取的封裝

export const singer = state => state.singer;

actions.js 對mutation進(jìn)行封裝,或者執(zhí)行一些異步操作

// 暫時沒有什么異步操作

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);

// 調(diào)試環(huán)境下開啟嚴(yán)格模式
const debug = process.env.NODE_ENV !== "production";

// 創(chuàng)建store對象并導(dǎo)出
export default new Vuex.Store({
  state,
  actions,
  getters,
  mutations,
  strict: debug,
  plugins: debug ? [createLogger()] : []
});

使用:

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

有了以上內(nèi)容,那么我們就可以在業(yè)務(wù)中去使用了:

例如:多組件之間的的數(shù)據(jù)交互。
需求:singer組件中需要將用戶點(diǎn)擊的那個singer對象傳遞給組件singer-detail組件。

singer.vue 組件中:

// 使用這個語法糖
import { mapMutations } from "vuex";

methods:{
    ...mapMutations({
        // 將這個函數(shù)(setSinger)和mutations中用于修改狀態(tài)的函數(shù)關(guān)聯(lián)起來
        setSinger: "SET_SINGER"
    });
}

// 傳參
this.setSinger(singer);

// 語法糖的本質(zhì)
  this.$store.commit("setSinger", singer);

singer-detail.vue 組件中:
我們就可以去使用這個數(shù)據(jù)了,當(dāng)然也是使用我們的語法糖啦。

import { mapGetters } from "vuex";

export default {
    // 使用一個計算屬性
    computed: {
        ...mapGetters([
            "singer"   // 這個就是getters.js中的那個singer
        ]);
    },
    created(){
        console.log(this.singer);
    }    
}

// 語法糖的本質(zhì):
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樣式。

代碼實(shí)現(xiàn):

let elementStyle = document.createElement("div").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;
}

使用案例:

// 導(dǎo)入該模塊
import { prefixStyle } from "common/js/dom";

// 加了合適前綴的CSS屬性
const TRANSFORM = prefixStyle("transform");

// 使用該CSS屬性
this.$refs.image.style[TRANSFORM] = `scale(${scale})`;
移動端的touch事件

隨著觸屏設(shè)備的普及,w3c為移動端web新增了touch事件。

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

touchstart 當(dāng)在屏幕上按下手指時觸發(fā)

當(dāng)用戶手指觸摸到的觸摸屏的時候觸發(fā)。事件對象的 target 就是 touch 發(fā)生位置的那個元素。

touchmove 當(dāng)在屏幕上移動手指時觸發(fā)

即使手指移出了 原來的target元素,但 touchmove 仍然會被一直觸發(fā),而且 target 仍然是原來的 target 元素。

touchend 當(dāng)在屏幕上抬起手指時觸發(fā)

當(dāng)用戶的手指抬起的時候,會觸發(fā) touchend 事件。如果用戶的手指從觸屏設(shè)備的邊緣移出了觸屏設(shè)備,也會觸發(fā) touchend 事件。

touchend 事件的 target 也是與 touchstarttarget 一致,即使已經(jīng)移出了元素。

touchcancel 當(dāng)一些更高級別的事件發(fā)生的時候(如電話接入或者彈出信息)會取消當(dāng)前的touch操作,即觸發(fā)touchcancel。一般會在touchcancel時暫停游戲、存檔等操作。

如果你使用了觸摸事件,可以調(diào)用 event.preventDefault()來阻止鼠標(biāo)事件被觸發(fā)。

與移動端相關(guān)的interface主要有三個:

TouchEvent 表示觸摸狀態(tài)發(fā)生改變時觸發(fā)的event

可以通過檢查觸摸事件的 TouchEvent.type 屬性來確定當(dāng)前事件屬于哪種類型。

dom.addEventListener("touchstart",(e) => {
    // 獲取事件類型
    let type = e.type;
    // toch事件發(fā)生時那個位置的元素對象
    let target = e.target;    
    
});

Touch 表示用戶和觸屏設(shè)備之間接觸時多帶帶的交互點(diǎn)(a single point of contact)

screenXscreenY:觸點(diǎn)相對于屏幕左邊緣或上邊緣的x、y坐標(biāo)。
clientXclientY:觸點(diǎn)相對于瀏覽器viewport左邊緣或上邊緣的x、y坐標(biāo)。(不包含滾動距離)

pageXpageY:觸點(diǎn)相對于document的左邊緣或上邊緣的x、y坐標(biāo)。與client不同的是,包含左邊滾動的距離。

target:觸摸開始時的element。

// 獲取touchList
let touchList = e.changedTouches;
// 獲取第i個touch對象
let touch = touchList[i];

touch.screenX
touch.clientX
touch.pageX
touch.target
...

TouchList 表示一組touches。當(dāng)發(fā)生多點(diǎn)觸摸的時候才用的到。

如果一個用戶用三根手指接觸屏幕(或者觸控板), 與之相關(guān)的TouchList對于每根手指都會生成一個 Touch 對象, 共計 3 個.
可以通過三種方式獲取這個對象:

dom.addEventListener("touchstart",(e) => {
    // 這個 TouchList對象列出了和這個觸摸事件對應(yīng)的那些發(fā)生了變化的 Touch 對象
    e.changedTouches
    // 這個TouchList列出了那些 touchstart發(fā)生在這個元素,并且還沒有離開 touch surface 的touch point(手指)
    e.targetTouches
    // 這個 TouchList 列出了事件觸發(fā)時: touch suface上所有的 touch point。
    e.touches
});
播放器內(nèi)核開發(fā) audio標(biāo)簽

對于音樂的播放,我們使用了audio標(biāo)簽,監(jiān)聽它的事件和操作DOM,可以達(dá)到對音樂播放、
暫停、進(jìn)度控制等操作。


audio進(jìn)行操作

let audio = this.$refs.audio;
// 暫停和播放
audio.pause();
audio.play();

// Audio對象的屬性(部分)

audio.currentTime // 設(shè)置或返回音頻中的當(dāng)前播放位置(以秒計)。

audio.duration    // 返回音頻的長度(以秒計)。

audio.loop    // 設(shè)置或返回音頻是否應(yīng)在結(jié)束時再次播放。(默認(rèn)false)

audio.volume    // 設(shè)置或返回音頻的音量。[0,1]

// Audio對象多媒體事件(Media Events)

onerror // 加載發(fā)生錯誤時的回調(diào)

ontimeupdate // 當(dāng)播放位置改變時調(diào)用
updateTime(e) {
    if(this.currentSongReady){
        // 獲取當(dāng)前播放的進(jìn)度
        this.currentSongTime=e.traget.currentTime;
    }
}
oncanplay // 能夠播放時調(diào)用

// 通過監(jiān)聽這個事件,設(shè)置標(biāo)志位,這個標(biāo)志位可以幫助我們
// 防止用戶快速切換歌曲引起一些錯誤。
songCanPlay(){
    this.currentSongReady = true;
}


onended // 到達(dá)結(jié)尾時調(diào)用

onplay、onpause...
進(jìn)度條組件

1.progress-bar.vue接收一個percent參數(shù),用來顯示當(dāng)前播放的一個進(jìn)度。

2.對于進(jìn)度條用戶手動拖動進(jìn)度的實(shí)現(xiàn)。

思路:主要是通過監(jiān)聽ontouchstartontouchmoveontouchend事件來完成。

// 首先得定義一個`touch`對象
let touch = {};

// 在監(jiān)聽的方法中
touchStart(e){
    this.touch.initialized = true;
    // 獲取touch的起始位置
    this.touch.startX = e.touches[0].pageX;
    // 獲取整個進(jìn)度條的寬度
    this.touch.barW = xxx;
    // 獲取已經(jīng)播放的進(jìn)度
    this.touch.offset = xxx;    
}

touchMove(e){
    // 判斷有無初始化
    ...
    // 獲取用戶滑動的距離
    let deltaX = e.touches[0].pageX - this.touch.startX;
    let barW = xxx; // 進(jìn)度條的寬度 - 拖動btn的寬度
    let offset = Math.min(Math.max(0, this.touch.offset + detail), barW);
    
    // 最后設(shè)置btn的位置和progress的進(jìn)度就OK
    ...
}

touchEnd(){
    this.touch.initialized = false;
    // 然后將進(jìn)度推送出去就好了
    this.$emit("percentChange",percent);
}
svg實(shí)現(xiàn)圓形進(jìn)度條

通過svg可以實(shí)現(xiàn)各種進(jìn)度條,有一個問題,怎樣去動態(tài)的修改它的進(jìn)度值呢?

這就不能不提 SVG Stroke 屬性

stroke 定義一條線,文本或元素輪廓顏色

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

stroke-dasharray 該屬性可用于創(chuàng)建虛線

stroke-dashoffset 設(shè)置虛線邊框的偏移量

OK,知道了以上屬性,就足以實(shí)現(xiàn)一個可設(shè)置進(jìn)度的SVG進(jìn)度條了。

思路:stroke-dasharray適用于創(chuàng)建虛線的,如果這個虛線長度為整個輪廓的周長呢。
stroke-dashoffset可以設(shè)置虛線的偏移量,利用這兩個屬性,我們就可以完成對進(jìn)度的控制。

且看一個小栗子:

所以,通過父組件傳入的percent,不斷地修改stroke-dashoffset就能達(dá)到進(jìn)度的顯示了。

全屏和退出全屏
// 全屏顯示
document.documentElement.webkitRequestFullScreen();
// 退出全屏
document.webkitExitFullscreen();

// 1.得根據(jù)不同的瀏覽器添加前綴
// 2.程序主動調(diào)用不管用,得用戶操作才可以(點(diǎn)擊按鈕)
歌詞頁的顯示

通過網(wǎng)絡(luò)接口獲取的歌詞:

對于歌詞的解析,播放是通過一個插件lyric-parser完成的。

這個插件很簡單:
1.通過正則把時間和對應(yīng)的歌詞切分出來創(chuàng)建成對象。
2.當(dāng)調(diào)用play方法時,通過定時器完成歌詞的播放,并將對應(yīng)的行號和歌詞通過回調(diào)函數(shù)傳遞出去。

當(dāng)播放的歌詞超過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,只要引入對應(yīng)的組件中就可以了。

例如下面的mixin

import { mapGetters } from "vuex";

export const playListMixin = {

  mounted () {
    this.handlePlayList(this.playList);
  },
  // 當(dāng)路由對應(yīng)的頁面激活時調(diào)用
  activated () {
    this.handlePlayList(this.playList);
  },
  watch: {
    playList (newPlayList) {
      this.handlePlayList(newPlayList);
    }
  },
  computed: {
    ...mapGetters([
      "playList"
    ])
  },
  methods: {
      // 這個方法需要對應(yīng)的組件自己去實(shí)現(xiàn),直接調(diào)用拋出錯誤
    handlePlayList () {
      throw new Error("Components must implement handlePlayList method.");
    }
  }
};

有了mixin我們在組件中就可以這樣使用了:

import { playListMixin } from "common/js/mixin";

export default{
    mixins: [playListMixin],
    ...
}
節(jié)流處理

在搜索頁面,我們需要處理用戶的輸入,然后向服務(wù)器發(fā)起請求。
為了不必要的請求、節(jié)省流量和提高頁面性能,我們都有必要做節(jié)流處理。

在搜索框search-box這個基礎(chǔ)組件中:

// 在created鉤子中,我們監(jiān)聽用戶輸入字符串(query)變化,然后將變化后的字符串
// 提交給父組件

// 可以看到在回調(diào)函數(shù)中,又包了一層debounce函數(shù)

created () {
  this.$watch("query", debounce(() => {
    this.$emit("queryChange", this.query);
  }, 500));
}

所以debounce函數(shù),就是我們的節(jié)流函數(shù),這個函數(shù),接收一個函數(shù),返回一個新的函數(shù)

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);

// 調(diào)用
func(); 

// 連續(xù)調(diào)用時,沒有超過三秒是不會有任何輸出的
animation動畫

語法:

animation: name duration timing-function delay iteration-count direction fill-mode play-state;
animation: 動畫名稱 執(zhí)行時間 速度曲線 延時時間 執(zhí)行次數(shù) 動畫播放順序 結(jié)束時應(yīng)用的樣式 播放的狀態(tài)(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;
    }
  }
};

// 擴(kuò)展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;
路由懶加載

為什么需要?

如果開發(fā)的App太大的話,就會導(dǎo)致首屏渲染過慢,為了增強(qiáng)用戶體驗(yàn),加快渲染速度,
需要用到懶加載功能。讓首屏的內(nèi)容先加載出來,其他路由下的組件按需加載。

vue官網(wǎng)描述:

異步組件
在大型應(yīng)用中,我們可能需要將應(yīng)用分割成小一些的代碼塊,并且只在需要的時候才從服務(wù)器加載一個模塊。
為了簡化,Vue 允許你以一個工廠函數(shù)的方式定義你的組件,這個工廠函數(shù)會異步解析你的組件定義。
Vue 只有在這個組件需要被渲染的時候才會觸發(fā)該工廠函數(shù),且會把結(jié)果緩存起來供未來重渲染。
const AsyncComponent = () => ({
  // 需要加載的組件 (應(yīng)該是一個 `Promise` 對象)
  component: import("./MyComponent.vue"),
  // 異步組件加載時使用的組件
  loading: LoadingComponent,
  // 加載失敗時使用的組件
  error: ErrorComponent,
  // 展示加載時組件的延時時間。默認(rèn)值是 200 (毫秒)
  delay: 200,
  // 如果提供了超時時間且組件加載也超時了,
  // 則使用加載失敗時使用的組件。默認(rèn)值是:`Infinity`
  timeout: 3000
})

注意:如果你希望在 Vue Router 的路由組件中使用上述語法的話,你必須使用 Vue Router 2.4.0+ 版本。

當(dāng)然為了簡單起見:

router/index.js路由配置文件中這樣加載組件:

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

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/52621.html

相關(guān)文章

  • 如何用vue打造一個移動音樂放器

    摘要:寫在前面沒錯,這就是慕課網(wǎng)上的那個音樂播放器,后臺是某音樂播放器的線上接口扒取,雖然這類項(xiàng)目寫的人很多,但不得不說這還是個少有的適合提升的好項(xiàng)目,做這個項(xiàng)目除了想寫一個比較大并且功能復(fù)雜的項(xiàng)目,主要原因是要拿它來應(yīng)對面試,也確實(shí)對我的業(yè)務(wù)能 寫在前面 沒錯,這就是慕課網(wǎng)上的那個vue音樂播放器,后臺是某音樂播放器的線上接口扒取,雖然這類項(xiàng)目寫的人很多,但不得不說這還是個少有的適合vu...

    lanffy 評論0 收藏0
  • 基于vue移動web音樂放器

    摘要:代碼實(shí)現(xiàn)得到合適的瀏覽器前綴對外暴露的方法使用案例導(dǎo)入該模塊加了合適前綴的屬性使用該屬性移動端的事件隨著觸屏設(shè)備的普及,為移動端新增了事件。如果用戶的手指從觸屏設(shè)備的邊緣移出了觸屏設(shè)備,也會觸發(fā)事件。 聲明 以下只是學(xué)習(xí)完慕課網(wǎng)huangyi老師實(shí)戰(zhàn)視頻課程的筆記內(nèi)容,僅供個人參考學(xué)習(xí)使用。如果對Vue2.0實(shí)戰(zhàn)高級-開發(fā)移動端音樂WebApp感興趣的話,請移步這里:https://c...

    tracy 評論0 收藏0
  • Vue 實(shí)現(xiàn)網(wǎng)易云音樂 WebApp

    摘要:基于等開發(fā)一款移動端音樂,界面參考了安卓版的網(wǎng)易云音樂布局適配常見移動端。圖標(biāo)使用阿里巴巴圖標(biāo)庫,中間的唱片旋轉(zhuǎn)動畫使用了實(shí)現(xiàn)。搜索功能實(shí)現(xiàn)功能搜索歌手歌單歌曲熱門搜索數(shù)據(jù)節(jié)流上拉刷新保存搜索記錄。 基于 Vue(2.5) + vuex + vue-router + vue-axios +better-scroll + Scss + ES6 等開發(fā)一款移動端音樂 WebApp,UI ...

    Karuru 評論0 收藏0

發(fā)表評論

0條評論

chemzqm

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<