Vue實現20+頁面的複雜單頁面應用(仿實驗樓)

前言

初學Vue,搜Vue項目時出現的幾乎都是TODO應用,音樂播放器之類複雜度並不如想象中高的應用,當然慢慢摸索實現出來也會知道Vue的一些功能,v-on,v-bind之類的綁定,v-for,v-if 等邏輯控制。但寫完總感覺意猶未盡... 於是想實現一個稍微複雜些的應用。

項目主要實現的是前端頁面部分,數據來源於實驗樓原站,原站API不支持跨域調用,需要使用一個轉發

效果展示

路徑
課程
課程

技術棧

vue2 + vuex + vue-router + axios + flex

知識點總結

vue-router

懶加載

路由懶加載由官方文檔中說明的作用是打包應用時的按需加載:最終的目的總是要打包發佈,所以懶加載一定要知道。

const __import__ = file => () => import(`@/pages/${file}.vue`)
...
{
    name: 'home',
    component: __import__('home') 
}

路由切換過渡動畫

單頁面應用可以很方便的製作切換不同頁面時使用的動畫效果,像是手機APP中的左滑右滑之類的。這裏實現的過渡動畫效果是透明度由0到1的緩慢漸變浮現效果。使用Vue的過渡動畫組件即可
過渡

<template>
  <div id="app">
    <transition name="tab_router_view">
      <router-view></router-view>
    </transition>
  </div>
</template>
<style>
.tab_router_view-enter-active, .tab_router_view-leave-active {
    transition: opacity .8s;
}

.tab_router_view-enter, .tab_router_view-leave-to {
    opacity: 0;
}

.tab_router_view-enter-to, .tab_router_view-leave {
    opacity: 1;
}
</style>

這樣每次切換路由時都會觸發一個透明度從0到1的0.8秒漸變效果:
漸變

路由導航守衛

路由導航守衛可以在每次路由變化時讓我們做一些功能性的調整,如切換的這個頁面如果需要登錄那麼我們可以這樣:

...
{
    path: '/profile',
    name: 'profile',
    component: Profile,
    meta: {
        login: true
    }
}
router.beforeEach((to, from, next)=>{
    if (to.meta.login) {
        if (!store.state.loginState.isLogin) {
            next({name: 'login'})
        } else {
            next()
        }
    }
})

上面的守衛實現瞭如果當前頁面要求登錄但沒有登錄的話會跳轉到登錄頁面,這樣就不需要每個頁面都設置一遍檢查了,
另外前置導航守衛一定要記得調用next,否則不會有組件加載出來。

每次切換路由頁面後我們很可能還需要一個後置導航守衛來替我們將頁面滾到最上部

router.afterEach((to, from) => {
    window.scrollTo(0, 0)
})

區別於前置守衛,後置守衛沒有next需要調用。

vuex

vuex被用來進行狀態管理,這是一個全局的數據倉庫一類的東西,數據的下載,轉換,保存都放在裏面進行。Vue的組件裏當然也可以進行數據的下載保存,也可以進行不同組件件的傳遞,但隨着業務增多往往會變得相當麻煩。

不用vuex狀態管理的話一般會順着思路這麼寫:

數據由父組件下載並保存下來傳遞到子組件:

<SubComponent :data="dataOne">
</SubComponent>
...
data: function () {
    return {
        dataOne: {}
    }
},
created: async function () {
    let res = await get('http://www.ceshi.com')
    this.dataOne = res.data
}

子組件內有一個觸發填好後發起頁面修改,但子組件是不能直接修改父組件傳遞過來的數據的,所以又需要發送一個信號讓父組件接受後由父組件修改:

子組件

props: {
    data: {
        type: Object,
        require: true
    }
},
methods: {
    change: fucntion (data) {
        this.$emit('change', data)
    }
}

父組件

<SubComponent :data="dataOne"
              @change="change"
>
</SubComponent>
...
methods: {
    change: async function (data) {
        await get(...)
    }
}

多寫了一個change方法不說,還需要不忘記註冊子組件的事件,想想這只是兩個組件間的通信,隨着組件的增多,本來只需要一個方法的事情會需要兩個三個,事件的註冊也越來越多,取決於嵌套了多少子組件,稍微不注意忘了註冊哪個事件就要debug很長時間。

如果用了vuex就會簡單很多,因爲它是一個全局的狀態管理。

父組件只需要負責把觸發數據下載。

<SubComponent></SubComponent>
...
created: async function () {
    await this.$store.dispatch('dataStore/getData')
}

子組件內的數據就會跟隨更改,修改數據也不用再通知父組件

computed: {
    dataOne: function () {
        return this.$store.state.dataStore.dataOne
    }
},
methods: {
    change: async function (data) {
        await this.$store.dispatch('dataStore/getData', data)
    }
}

這樣的全局狀態管理不會因爲嵌套的子組件而增加複雜度,而且具有良好的可讀性,如何操作數據在store裏進行修改,組件裏只需要觸發即可。

API跨域配置

實驗樓原站也是使用Vue編寫,前後端分離,使用API通訊,我們可以把API抓取下來使用,當然我已經抓好了,實驗樓API後端,實驗樓的API與展示在同一個域名下,所以不存在跨域問題,但我們開發的話就不是在同一個域名下,要使用的話繞不開的一環就是跨域了。由於服務器端不支持跨域,要使用只能做一個轉發,先來了解一下跨域吧。

同源策略

同源策略限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制。也就是說
http://www.baidu.com的Js,如果沒有跨域配置是無法與http://juejin.im進行通訊的。

服務器端跨域配置

不管後端使用何種語言,要解決跨域就是要讓服務器的回覆中添加以下頭:

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods:POST
Access-Control-Allow-Headers:x-requested-with,content-type

Access-Control-Allow-Origin 表示可以請求的源,*表示任意一個都可以。

Access-COntrol-Allow-Methods 表示請求時的方法,POST表示只有POST請求纔可以進行跨域請求,GEt,PUT,DELETE之類的如果沒有標明統統不可以。

Access-Control-Allow-Headers表示跨域允許的首部。

Vue中的配置

本地開發的話可以在Vue的配置文件中進行配置config/index.js,下面是配置的開發環境的跨域請求:

dev: {
    proxyTable: {
          '/api': {  
            target: 'http://localhost:8000/api',// 設置你調用的接口域名
            changeOrigin: true,  
            pathRewrite: {  
              '^/api/': '' // 這裏替換的是 target 中的內容,使用的時候 '/api/demo' 就相當於'http://localhost:8000/api/demo'。
            }  
          }
    }
}

生產環境下的跨域:

生產環境下如果跨域不需要攜帶cookies認證那服務器配置了上面說的幾個響應頭即可,否則的話還需要

Access-Control-Allow-Credentials:true

以及

Access-Control-Allow-Origin

不可以爲**與credentials是衝突的。

最後使用 axios 請求時需要配置withCredentials = true

CSS佈局

項目中使用了flex佈局,flex佈局使用起來比較流暢,寫起來也很簡單,任意元素加上

.box {
    display: flex
}

這樣這個元素的內容就會按照默認的flex進行佈局
佈局
默認水平走向,不會換行,從容器的最左端開始排列。
容器裏元素的如何排列我們可以通過這些屬性來設置:

flex-direction  排列方向 row | column
flex-wrap wrap | nowrap
flex-flow 上面兩個的簡寫 row nowrap
justify-content 指定元素主軸(main axis)對其方式 flex-start | flex-end | center | space-between | space-around
align-items 指定元素交叉軸(corss axis)對其方式 flex-start | flex-end | center | baseline | stretch

瞭解上面這一點就可以把常規的佈局方式熟悉一下,只用上面這些就可以搭建出首頁。

這裏是關於flex更詳細的資料

最後

完整的項目請看GitHub

克隆後直接啓動即可:

git clone [email protected]:HuberTRoy/vue-shiyanlou.git

cd vue-shiyanlou

npm install

npm run dev
如果對您有幫助,希望可以得到一枚您的Star~。(〃'▽'〃)
有任何可以改進的地方希望您可以花費一些時間開啓一個Issue或者直接PR~。φ(>ω<*)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章