使用vue重構資訊頁面

目錄

  1. 文件結構設計
  2. eventBus通訊
  3. 其餘特性
  4. 須要改進優化的地方

前言

從我接手到將這個頁面代碼重構前,一直都仍是使用angular1的代碼去作的,需求來了也是用angular去實現;做爲一個憧憬新技術的前端,怎麼忍受得了如今還在使用這麼有歷史感的框架,因此,之前就一直在醞釀着如何將angular重構成vue。javascript

代碼結構設計

這個資訊項目代碼總體都是使用angular.js來去實現的,而這次想重構的資訊詳情頁面只是其中的一個頁面,因此新建了一個文件夾/newApp、做爲之後新技術的文件夾,之後使用vue技術的都放在這個文件夾下,區別於原先文件夾/appphp

在舊的angular1的js文件中,因爲頁面功能豐富,全部的功能代碼全都擠在了同一個js中,這就致使主要的js一共有1500+行的代碼。每次打開看到長長的一摞代碼、還要在裏面找到對應的功能代碼,就不由吐槽其中的不合理。。css

因此此次重構,我按照頁面中的每一個模塊、每一個功能,來將頁面拆分紅不一樣的.vue組件模塊,之後想要去維護、或者新增功能時,能夠直接去對應的模塊文件中修改或者是新增一個vue文件。html

  • components

    存放着vue的組件代碼前端

    • base

      這個文件夾下,存放着一些能夠被複用的組件vue

      • commentInput.vue -- 評論輸入框
      • commentList.vue -- 評論列表
      • replyBar.vue -- 固定懸浮於底部的評論條、提示用戶能夠評論
      • report.vue -- 對評論進行舉報會彈出的舉報信息框
    • photoswipe.vue

      資訊裏面的圖片瀏覽組件、在app內會調用客戶端的瀏覽器組件能力、端外使用第三方組件庫photoSwipe的來實現點擊瀏覽大圖。java

    • adImg.vue -- 廣告展現模塊
    • audioBar.vue -- 語音播放功能模塊
    • bannerTop.vue -- 站外顯示的頂部拉新banner模塊
    • comments.vue -- 評論列表功能模塊
    • fontconfig.vue -- 設置字體大小功能模塊
    • footBar.vue -- 展現點贊人數和瀏覽人數模塊
    • hotRecommend.vue -- 熱點推薦模塊
    • mask.vue -- 頁面蒙版
    • relatedStock.vue -- 相關個股模塊
    • relatedTopic.vue -- 關聯專題模塊
    • shareBar.vue -- 文末快速分享模塊
  • detailBusiness

    在這個文件夾下放着一些資訊的業務jsnode

    • detailSensor.js -- 引入神策統計的sdk
    • drawTimeline.js -- 畫出股票的行情線圖
  • i18n

    語言包web

  • sass

    資訊頁面用到的sass文件、不過因爲node-sass的安裝有點麻煩(在技術選型時未考慮此狀況),後面可能會重構成使用less來作css的預處理器。vuex

  • utils

    一些公用的函數被抽成單獨的文件放在這裏

  • allCommentsMain.js

    評論列表頁面主js

  • commentDetailMain.js

    評論詳情頁面主js

  • eventBus.js --

    使用eventBus來實現頁面的通訊

  • i18n.js

    使用vue-i18n來實現頁面的多語言

  • Main.js

    資訊詳情頁面主js

  • mixin.js

    混入

  • shareInfoSettingMain.js

    將分享的邏輯單獨抽取成一個js。這裏單獨抽成一個js是由於,在安卓的webview加載h5時,會等js文件執行完畢以後才渲染出頁面(即用戶看到東西),因此頁面的主js是進行了延遲加載的,可是分享這一邏輯是但願仍是能提早加載,因此單獨將這一功能抽取成一個js,讓頁面按照順序正常去加載。

組件間通訊

由於將頁面按照功能拆分紅了不少小的模塊,在不一樣的模塊之間的通訊就須要想方法實現,這些模塊之間大可能是一種兄弟組件的關係。

咱們首先能想到的vue中父子組件的通訊功能的實現,可是父子組件的場景不適合如今的多個兄弟組件之間的通訊,或者說實現起來很囉嗦。

因此考慮另外兩種方法實現:eventBus和vuex。考慮到資訊詳情頁只有一個單頁面,引入vuex的話可能會過重了,使代碼體積增長很多,於是使用了EventBus事件總線這一方法來實現。

事件總線

在Vue中可使用 EventBus來做爲溝通橋樑的概念,就像是全部組件共用相同的事件中心,能夠向該中心註冊發送事件或接收事件,全部組件均可以上下平行地通知其餘組件。

具體作法是在eventBus.js這個文件中建立一個vue對象,而且將其export出去。其實就是建立一個vue對象做爲eventBus,使用它的$on$emit來實現。這種設計模式是發佈/訂閱模式,即pub/sub

//eventBus.js

import vue from 'Vue';

export default new Vue();
複製代碼

在想要通訊的組件中使用$on$emit方法。

例如,資訊詳情頁面有一個接口是去請求幾個數據:廣告、相關個股等。這個接口其實在頁面中只須要在初始化時去請求一次,而後將數據保存下來就好。

因此在Main.js中負責去請求這個接口,而後請求回來了,發佈一個dataReady的事件,將數據也帶出去。而在其餘的、須要用到這個初始化數據的組件就去訂閱這個事件,拿到初始化的數據後,就將其render到頁面中。

// Main.js

_initData() {
    // ****
    
    //使用eventBus廣播這個事件,多個子組件中用到了初始化數據
    EventBus.$emit('dataReady', data);
}

//adImg.vue 廣告模塊
mounted() {
    EventBus.$on('dataReady', data => {
        // *****
    })
}

//relatedStock.vue 相關個股模塊
mounted() {
    Event.$on('dataReady', data => {
        // ****
    })
}
複製代碼

在這裏其實有個小優化,能夠將直接在Vue的原型上添加一個vue對象實例做爲全局的消息總線,就不用每次都去import 一次eventBus.js。

//Main.js

Vue.prototype.$bus = new Vue();

//使用時:
this.$bus.$on('', () => {});
複製代碼

在使用eventbus完成項目以後發現,事件總線這一個機制確實很方便,不一樣的組件之間能夠隨意通訊,可是由此很容易形成難以管理的災難。好比,在某個模塊中訂閱了某個事件,這個事件是從哪裏發佈的、何時發佈的,在代碼中彷佛有點難以搜索發佈的時機。

其餘特性

資訊詳情頁面中實現了其餘的一些功能,好比多皮膚、多語言這些特性。

多皮膚

多皮膚,使用了css的預處理器sass來實現,用到了sass的變量、混入指令等特性。

首先讓視覺給一個不一樣皮膚下的色彩對照表,而後將其寫入sass文件中,用變量來保存對應的顏色值。根據外部的class來使用對應的顏色變量。

多膚色彩對照表

外面的class則是由後端在渲染html時,將對應的皮膚class添加在最外層的div中,在.vue組件中加入對應的class樣式,就能作到隨膚、且不閃屏。

不過我一開始在重構時的想法並非經過三組對皮膚的變量來實現,我一開始的想法是在sass裏面,就能拿到對應的皮膚的值,從而在使用時都是隻須要知道是要哪一個層級的顏色值就能夠,而不須要在外部的sass代碼裏分別寫三種。

可是問題在於,沒法將js能拿到的皮膚信息傳入sass中,這個想了好久也沒想到解決方案。若是能在sass中就能夠拿到皮膚信息,從而直接賦予元素對應的皮膚值,這樣就很方便了。因此這裏對sass、less這些語言的侷限性也深有感觸,它們終究只是一個「預處理器」而已。

多語言

多語言特性,使用了vue-i18n這個插件來實現。

可改進的地方

整合資訊詳情頁面

其實如今包括資訊詳情說是隻有一個頁面,但因爲它具備的評論功能,是能夠聚合成一個spa的,包括資訊詳情頁面(Main.js)、資訊評論列表頁面(commentDetailMain.js)、評論詳情頁面(allCommentsMain.js)。這三個頁面用到的技術棧在重構以後很是類似,甚至將公共的組件都已經抽取出來了。可是我在重構時仍是把它們三個當成不一樣的頁面拆開了,這一點有待改進。

目前是經過mixin這一特性,將三個頁面公共的一些東西抽取在其中,分別在三個頁面的js中引入這個mixin,能夠避免一些重複的東西。

//mixin.js
// 資訊詳情頁、資訊評論列表頁、資訊評論詳情頁公用的一些東西

import i18n from './i18n';
import ReplyBar from '**/replyBar.vue';
import BannerTop from '**/bannerTop.vue';
import CommentInput from '**/commentInput.vue';

let mixin = {
    i18n,
    components: {
        ReplyBar,   //底部懸浮框
        BannerTop,  //頂部的banner條
        CommentInput //評論輸入框
    }
}

export default mixin;
複製代碼

---- 後來又想了下,因爲當前模式仍是使用php渲染html的方式,因此無法作成SPA這樣子,只能等待加上了node的ssr以後才能實現= =。

使用less代替sass

因爲node-sass的安裝有時會出現一些問題,因此仍是使用less做爲替代比較穩妥..

抽取css樣式

在打包時將vue中的樣式文件也打進js中了,須要在打包時將其抽取出來

進行ing...

相關文章
相關標籤/搜索