vue實踐過程之技術(shù)實現(xiàn)

實現(xiàn)項目

這個項目和微吉風(fēng)很像惧眠,不過它是小程序,我這里的是webapp,哈哈于个。其實我這這個項目就是玩玩氛魁,為了練習(xí)練習(xí)vue而來,積累一下前端如何前后端分離厅篓,感受一下vue的美麗秀存,擁抱一下Muse-UI。

接口設(shè)計

用flask寫的接口api在做這個前端項目的時候有調(diào)整過羽氮,接口主要有:

實現(xiàn)

1.數(shù)據(jù)來源:模擬登陸:學(xué)校教務(wù)系統(tǒng)官網(wǎng)

2.數(shù)據(jù)簡化:模擬登陸的過程是在服務(wù)器完成的或链,請求的到數(shù)據(jù)通過服務(wù)器進行刷選后簡化數(shù)據(jù),再返回給瀏覽器档押。幾乎所有的請求都是要模擬登陸一次學(xué)校教務(wù)系統(tǒng)澳盐,再請求數(shù)據(jù)的,數(shù)據(jù)都是不會保存到服務(wù)器的令宿。

3.數(shù)據(jù)更新周期:分析返回來的數(shù)據(jù)叼耙,會發(fā)現(xiàn)有些數(shù)據(jù)變動非常小,如果每次打開頁面都向服務(wù)器發(fā)起請求,就太消耗服務(wù)器資源了掀淘。比如課表都幾乎是一學(xué)期才會有變動的旬蟋,頻繁請求就有點多余。但是這里設(shè)計的服務(wù)器是不打算保存任何與用戶相關(guān)的信息的革娄,所以這里用到了WebStorage的儲存方案倾贰,localStorage(目前主流的瀏覽都支持)使用localStorage來緩存這些變化不大的數(shù)據(jù),比如課表數(shù)據(jù)拦惋,周數(shù)匆浙,個人學(xué)年時間等。

拓展:只讀的localStorage 屬性允許你訪問一個Document 源(origin)的對象 Storage厕妖;其存儲的數(shù)據(jù)能在跨瀏覽器會話保留首尼。localStorage 類似 sessionStorage,但其區(qū)別在于:存儲在 localStorage 的數(shù)據(jù)可以長期保留言秸;而當(dāng)頁面會話結(jié)束——也就是說软能,當(dāng)頁面被關(guān)閉時,存儲在 sessionStorage 的數(shù)據(jù)會被清除 举畸。

應(yīng)注意查排,無論數(shù)據(jù)存儲在 localStorage 還是 sessionStorage它們都特定于頁面的協(xié)議抄沮。

另外跋核,localStorage 中的鍵值對總是以字符串的形式存儲。 (需要注意, 和js對象相比, 鍵值對總是以字符串的形式存儲意味著數(shù)值類型會自動轉(zhuǎn)化為字符串類型).

語法:

//設(shè)置值
localStorage.setItem('name', 'Cendeal');
//獲取值
localStorage.getItem('name');
//或者這獲取值
localStorage.name
//刪除值
localStorage.removeItem('name');
//或者也可以這樣刪除值
delete localStorage.name
// 移除所有
localStorage.clear();

下面是計算數(shù)據(jù)存活周期:

/**
 * 計算生存時間
 * @param Date now-當(dāng)前時間
 * @param Number day-天數(shù)
 * @return Number
 */
function calculateExpiration(now,day) {
    let future = new Date()
    future.setHours(0,0,0,0)
    future.setDate(now.getDate()+day)
    return Math.floor(future - now)
}

/**
 * 獲取當(dāng)前周的生存時間
 * @return Number  生存時間-秒
 *
 */
function getCurrentWeekExpiration() {
    let now = new Date()
    return calculateExpiration(now,8-now.getDay())
}

/**
 * 獲取課表的生存周期
 * @param Number totalWeek-總周數(shù)
 * @return Number 生存時間-秒
 */
function getScheduleExpiration(totalWeek=22) {
    let now = new Date()
    return calculateExpiration(now,totalWeek*7)
}

export {getCurrentWeekExpiration,getScheduleExpiration}

4.改造localStorage:了解到localStorage儲存室沒有生命周期的叛买,它依賴瀏覽器的清除規(guī)則砂代,一般都是需要用戶手動清除數(shù)據(jù)的,那么要怎樣才知道課表需要更新數(shù)據(jù)呢率挣,除了用戶自己手動更新外刻伊,還需要設(shè)置一個更新周期,明顯一般都是學(xué)期末據(jù)需要更新數(shù)據(jù)了椒功,那么就可以考慮為其設(shè)置存活時間娃圆。由于localStorage是沒有這函數(shù)的,所以這里重寫了一個蛾茉,為localStorage添加存活時間讼呢。

方案是這樣的:每次存新鍵值時,先計算這個數(shù)據(jù)可以存儲多久谦炬,然后把時間和鍵值一起存進去悦屏,當(dāng)取值的時候就判斷當(dāng)前時間是否超過了那個鍵值的存活時間,如果超過了就delete它键思,并返回null或undefinded

代碼如下:

class JluzhLocalStorage {

    //獲取值
    getItem(key) {
        let now = new Date()
        let data = JSON.parse(localStorage.getItem(key))
        if (data != null) {
            if (data.expiration != null) {
                let expiration = new Date(data.expiration)
                if (expiration - now <= 0) {
                    delete localStorage['key']
                    return undefined
                }
            }

            return data.val
        } else {
            return null
        }


    }

    //默認無限時間
    setItem(key, val, expiration = null) {
        let time = null
        if (expiration != null) {
            let now = new Date()
            time = now.setSeconds(now.getSeconds() + expiration)
        }
        let data = {val: val, expiration: time}
        localStorage.setItem(key, JSON.stringify(data))
    }

    //清空
    clear() {
        localStorage.clear()
    }

    //獲取長度
    get length() {
        return localStorage.length
    }

    get info() {
        let data = {
            size: 0,
            count: localStorage.length,
            keys: []
        }
        let temp = 0
        for (let i in localStorage) {
            temp += 1

            if (temp > data.count) {
                break
            }
            let blob = new Blob([localStorage[i]])
            data.size += blob.size
            data.keys.push(i)

        }
        return data
    }

}

const jluzhLocalStorage = new JluzhLocalStorage()
export default jluzhLocalStorage

5.主題樣式保存方案:這里主題保存樣式也是利用了localStorage進行保存础爬,服務(wù)器不會同步,清掉緩存就會恢復(fù)默認主題吼鳞。sessionStorage我用來保存課表課程的顏色塊數(shù)據(jù)看蚜,所以每次打開新的會話顏色都變化。

6.主題狀態(tài)統(tǒng)一:這里使用的是vuex赔桌,通過store.js里的state保存主題的樣式供炎,更新使用mutations里面定義的函數(shù)進行更新渴逻。

代碼:

import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex)
// noinspection JSValidateTypes
const store = new Vuex.Store({
    state: {
        app_title: '吉機',
        app_host: 'http://www.cendeal.cn:5001/jlu/api',
        theme: {
            nav_style: {
                backgroundColor: 'rgb(244, 67, 54)',
                color: 'white',
                'z-index': 999
            },
            nav_active_color: 'green',

            head_pic_style: {
                backgroundColor: '#ffca28',
                'position': 'relative',
                'top': '8px'
            },
            head_text_style: {
                'color': '#7cb342'
            },
            float_btn_style: {
                'bg': 'red',
                'text': 'yellow'
            }
        },
        url_paths: {
            u_login: '/login',
            u_schedule: '/querySchedule',
            u_score: '/queryScore',
            u_week: '/getCurrentWeek',
            u_lines: '/getStuTimeLines',
            u_auth: '/auth',
            u_logout: '/logout'
        },
        jluzh_courses: '',
        current_week:1,

    },
    getters: {
        navStyle: state => {
            return state.theme.nav_style
        },
        barColor: state => {
            return state.theme.nav_style.backgroundColor
        },
        urlPaths: state => {
            return state.url_paths
        },
        headPicStyle: state => {
            return state.theme.head_pic_style
        },
        headTextStyle: state => {
            return state.theme.head_text_style
        },
        theme: state => {
            return state.theme
        }
    },
    mutations: {
        updateTheme: function (state, theme) {
            if (theme.hasOwnProperty('float_btn_bg'))
                state.theme.float_btn_style.bg = theme.float_btn_bg

            if (theme.hasOwnProperty('float_btn_text_color'))
                state.theme.float_btn_style.text = theme.float_btn_text_color

            if (theme.hasOwnProperty('nav_active_color'))
                state.theme.nav_active_color = theme.nav_active_color

            if (theme.hasOwnProperty("nav_bg"))
                state.theme.nav_style.backgroundColor = theme.nav_bg

            if (theme.hasOwnProperty('nav_text_color'))
                state.theme.nav_style.color = theme.nav_text_color

            if (theme.hasOwnProperty('head_pic_bg'))
                state.theme.head_pic_style.backgroundColor = theme.head_pic_bg

            if (theme.hasOwnProperty('head_pic_text_color'))
                state.theme.head_text_style.color = theme.head_pic_text_color
        },
        initTheme:function () {
            let theme = localStorage.getItem('jluzh_theme')
            if(theme != null || theme != undefined){
                store.commit('updateTheme',JSON.parse(theme))
            }
        },
        updateWeek:function (state,week) {
            state.current_week = week
        },
        updateCourses:function (state,courses) {
            if(courses==null)
            delete localStorage['jluzh_courses']
            state.jluzh_courses = courses
        }
    },
    actions: {}
})
export default store

7.跨域問題:因為后端和前端部署不是在同一個域下的,后端是通過gunicorn部署在5001端口音诫,前端直接使用的nginx監(jiān)聽的80端口,所以當(dāng)前端發(fā)起數(shù)據(jù)請求時就會出現(xiàn)跨域惨奕,請求會被瀏覽器攔截。為了解決這個問題竭钝。這里使用的是vue-jsonp發(fā)起跨域請求(其原理就是js文件的請求是可以跨域的)【這里處理的不是太好梨撞,還是存在一點問題,其實比較簡單的就是采用代理的方法】

/**
 * created by cendeal 2019/3/7
 * 通過vue-jsonp 進行跨域請求數(shù)據(jù)
 * 所有函數(shù)返回的都是promise對象
 * 要求:全局使用vue-jsonp,vuex
 */

// 登陸
function loginjs(token) {
    return this.$jsonp(this.$store.state.app_host + this.$store.getters.urlPaths.u_auth, {
        token: token,
        callbackName: 'jsonpCallback'
    })

}


// 獲取選項
function getSelection() {
    return this.$jsonp(this.$store.state.app_host + this.$store.getters.urlPaths.u_lines,
        {callbackName: 'jsonpCallback'})
}

// 獲取分數(shù)
function getScore(grade, term) {
    return this.$jsonp(this.$store.state.app_host + this.$store.getters.urlPaths.u_score,
        {
            Grade: grade,
            term: term,
            callbackName: 'jsonpCallback'
        })
}

// 獲取課表
function getScheduleJs(Grade = null, term = null) {
    let data = {Grade: '0', term: '0', callbackName: 'jsonpCallback'}
    if (Grade != null && term != null) {
        data.Grade = Grade
        data.term = term
    }
    return this.$jsonp(this.$store.state.app_host + this.$store.getters.urlPaths.u_schedule, data)
}

// 獲取當(dāng)前周
function getCurrentWeek() {
    let data = {callbackName: 'jsonpCallback'}
    return this.$jsonp(this.$store.state.app_host + this.$store.getters.urlPaths.u_week, data)
}


export {loginjs,getSelection,getScore,getScheduleJs,getCurrentWeek}

8.課表頁面實現(xiàn):這里使用了另外的swiper不是muse-ui的香罐,因為muse-ui的swiper實現(xiàn)不了想要的效果卧波。就在好友的建議下使用了另外的vue-awesome-swiper它是基于swiper4的。比較難受的就是庇茫,我一開始就打算用它的loop屬性港粱,但是添加上去的時候就出錯了,網(wǎng)上也很少相關(guān)的內(nèi)容港令,就先放棄了loop屬性啥容。就選擇直接生成21張的課表的swiper-slide,在朋友的iphone 瀏覽器打開居然卡了,沒辦法就必須優(yōu)化顷霹,然后在嘗試和看swiper4的文檔咪惠,后來發(fā)現(xiàn)可以先不讓swiper進行init,先讓它的params的loop的值初始為true后再調(diào)用init淋淀,結(jié)果成功了遥昧,然后swiper-slide的數(shù)量可以減到3了《浞祝【如果我不執(zhí)著與想要swiper的cude立體轉(zhuǎn)換效果炭臭,根本就不用這么麻煩,1個swiper-slide就可以袍辞,也不用用到loop】

代碼:Schedule.vue

9.最后是學(xué)習(xí)筆記鞋仍。

0_1.png
0_2.png
0_3.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搅吁,隨后出現(xiàn)的幾起案子威创,更是在濱河造成了極大的恐慌,老刑警劉巖谎懦,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肚豺,死亡現(xiàn)場離奇詭異,居然都是意外死亡界拦,警方通過查閱死者的電腦和手機吸申,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人截碴,你說我怎么就攤上這事梳侨。” “怎么了隐岛?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵猫妙,是天一觀的道長瓷翻。 經(jīng)常有香客問我聚凹,道長,這世上最難降的妖魔是什么齐帚? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任妒牙,我火速辦了婚禮,結(jié)果婚禮上对妄,老公的妹妹穿的比我還像新娘湘今。我一直安慰自己,他們只是感情好剪菱,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布摩瞎。 她就那樣靜靜地躺著,像睡著了一般孝常。 火紅的嫁衣襯著肌膚如雪旗们。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天构灸,我揣著相機與錄音上渴,去河邊找鬼。 笑死喜颁,一個胖子當(dāng)著我的面吹牛稠氮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播半开,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼隔披,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寂拆?” 一聲冷哼從身側(cè)響起奢米,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漓库,沒想到半個月后恃慧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡渺蒿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年痢士,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡怠蹂,死狀恐怖善延,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情城侧,我是刑警寧澤易遣,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站嫌佑,受9級特大地震影響豆茫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屋摇,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一揩魂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧炮温,春花似錦火脉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至担巩,卻和暖如春方援,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背兵睛。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工肯骇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人祖很。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓笛丙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親假颇。 傳聞我的和親對象是個殘疾皇子胚鸯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348