vue-manage-system 後臺管理系統開發總結

来源:https://www.cnblogs.com/linxin/archive/2018/09/13/9638461.html
-Advertisement-
Play Games

前言 vue manage system,一個基於 Vue.js 和 element ui 的後臺管理系統模板,從2016年年底第一個commit,到現在差不多兩年了,GitHub上也有了 5k star,也是這些讓我有了持續更新的動力,其中也踩了很多坑,在這總結一下。 github地址: "vue ...


前言

vue-manage-system,一個基於 Vue.js 和 element-ui 的後臺管理系統模板,從2016年年底第一個commit,到現在差不多兩年了,GitHub上也有了 5k star,也是這些讓我有了持續更新的動力,其中也踩了很多坑,在這總結一下。

github地址:vue-manage-system

線上地址:blog.gdfengshuo.com/example/work/

自定義圖標

element-ui 自帶的字體圖標比較少,而且許多比較常見的都沒有,因此需要自己引入自己想要的字體圖標。最受歡迎的圖標庫 Font Awesome,足足有 675 個圖標,但也因此導致字體文件比較大,而項目中又不需要用到這麼多圖標。那麼這時候,阿裡圖標庫就是一個非常不錯的選擇。

首先在阿裡圖標上創建一個項目,設置圖標首碼,比如 el-icon-lx,設置Font Family,比如 lx-iconfont,添加需要用到的圖標到項目中,我這邊選擇 Font class 生成線上鏈接,因為所有頁面都需要用到圖標,就直接在 index.html 中引入該css鏈接就行了

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>vue-manage-system</title>
    <!-- 這裡引入阿裡圖標樣式 -->
    <link rel="stylesheet" href="//at.alicdn.com/t/font_830376_qzecyukz0s.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

然後需要設置首碼為 el-icon-lx 的圖標類名使用 lx-iconfont 字體。

[class*="el-icon-lx"], [class^=el-icon-lx] {
    font-family: lx-iconfont!important;
}

但是這個樣式要放在哪裡才可以呢?這可不是隨便放就行的。在 main.js 中,引入了 element-ui 的樣式,而樣式中有這樣的一段css:

[class*=" el-icon-"], [class^=el-icon-]{
    font-family: element-icons!important;
    speak: none;
    font-style: normal;
    font-weight: 400;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    vertical-align: baseline;
    display: inline-block;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

很明顯,如果這段 css 在我們自定義樣式後面才執行,就會覆蓋了我們的樣式,那自定義的圖標就顯示不了。而在 build 項目的時候,會把 APP.vue 中的的樣式打包進 app.css 中,然後再把 main.js 中引用到的樣式追加到後面。那麼我們可以把自定義樣式放到一個css文件中,然後在 main.js 引入 element-ui css 的後面引入,那就可以覆蓋掉預設字體了,然後便可以在項目中通過 <i class="el-icon-lx-people"></i> 使用圖標了。

那機智的人就發現了,我自定義圖標的首碼不要含 el-icon- 就不會有這樣的問題了。是的,那麼為了和原有字體保持一樣的樣式,需要複製它的整段css

/* 假設首碼為 el-lx */
[class*="el-lx-"], [class^=el-lx-]{
    font-family: lx-iconfont!important;
    speak: none;
    font-style: normal;
    font-weight: 400;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    vertical-align: baseline;
    display: inline-block;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

導航菜單

element-ui 關於導航菜單的文檔也是非常詳細了,但是還是有人提 issue 或者加 QQ 問我:三級菜單怎麼弄等等。而且具體的菜單項可能是伺服器端根據許可權而返回特定的數據項,因此不能寫死在模板中。

首先定好菜單數據的格式如下,即使伺服器端返回的格式不是這樣,也需要前端處理成下麵的格式:

export default {
    data() {
        return {
            items: [{
                icon: 'el-icon-lx-home',
                index: 'dashboard',
                title: '系統首頁'
            },{
                icon: 'el-icon-lx-calendar',
                index: '1',
                title: '表單相關',
                subs: [{
                    index: '1-1',
                    title: '三級菜單',
                    subs: [{
                        index: 'editor',
                        title: '富文本編輯器'
                    }]
                }]
            },{
                icon: 'el-icon-lx-warn',
                index: '2',
                title: '錯誤處理',
                subs: [{
                    index: '404',
                    title: '404頁面'
                }]
            }]
        }
    }
}

icon 就是菜單圖標,就可以用到我們上面自定義的圖標了;index 就是路由地址;title 就是菜單名稱;subs 就是子菜單了。而模板則通過判斷菜單中是否包含 subs 從而顯示二級菜單和三級菜單。

<el-menu :default-active="onRoutes" :collapse="collapse" router>
    <template v-for="item in items">
        <template v-if="item.subs">
            <el-submenu :index="item.index" :key="item.index">
                <template slot="title">
                    <i :class="item.icon"></i><span slot="title">{{ item.title }}</span>
                </template>
                <template v-for="subItem in item.subs">
                    <el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
                        <template slot="title">{{ subItem.title }}</template>
                        <!-- 三級菜單 -->
                        <el-menu-item v-for="(threeItem,i) in subItem.subs" :key="i" :index="threeItem.index">
                            {{ threeItem.title }}
                        </el-menu-item>
                    </el-submenu>
                    <el-menu-item v-else :index="subItem.index" :key="subItem.index">
                        {{ subItem.title }}
                    </el-menu-item>
                </template>
            </el-submenu>
        </template>
        <!-- 沒有二級菜單 -->
        <template v-else>
            <el-menu-item :index="item.index" :key="item.index">
                <i :class="item.icon"></i><span slot="title">{{ item.title }}</span>
            </el-menu-item>
        </template>
    </template>
</el-menu>

這樣就完成了一個動態的導航菜單。

通過 Header 組件中的一個按鈕來觸發 Sidebar 組件展開或收起,涉及到了組件之間傳遞數據,這裡通過 Vue.js 單獨的事件中心(Event Bus)管理組件間的通信。

const bus = new Vue();

在 Header 組件中點擊按鈕時觸發 collapse 事件:

bus.$emit('collapse', true);

在 Sidebar 組件中監聽 collapse 事件:

bus.$on('collapse', msg => {
    this.collapse = msg;
})

圖表自適應

vue-manage-system 中用到的圖表插件是 vue-schart,是把一個基於 canvas 的圖表插件 schart.js 進行了封裝。要做到圖表能夠自適應寬度,隨著 window 或者父元素的大小改變而重新渲染,如果圖表插件里沒實現該功能,就需要自己手動實現。

vue-schart 中提供了 renderChart() 的方法可以重新渲染圖表,Vue.js 中父組件調用子組件的方法,可以通過 $refs 進行調用。

<schart ref="bar" canvasId="bar" :data="data" type="bar" :options="options"></schart>

然後監聽 window 的 resize 事件,調用 renderChart() 方法重新渲染圖表。

import Schart from 'vue-schart';
export default {
    components: {
        Schart
    },
    mounted(){
        window.addEventListener('resize', ()=>{
            this.$refs.bar.renderChart();
        })
    }
}

不過也要記得組件銷毀時移除監聽哦!監聽視窗大小改變完成了,那父元素大小改變呢?因為父元素寬度設為百分比,當側邊欄摺疊的時候,父元素的寬度發生了變化。但是 div 並沒有 resize 事件,無法監聽到它的寬度改變,但是觸發摺疊的時候,我們是知道的。那麼是否可以通過監聽到摺疊變化的時候,再調用渲染函數重新渲染圖表呢?那麼還是通過 Event Bus 監聽側邊欄的改變,併在 300ms 後重新渲染,因為摺疊時候有 300ms 的動畫過程

bus.$on('collapse', msg => {
    setTimeout(() => {
        this.$refs.bar.renderChart();
    }, 300);
});

多標簽頁

多標簽頁,也是提 issue 最多的一個功能。

當在 A 標簽頁輸入一些內容之後,打開 B 標簽再返回到 A,要保留離開前的狀態,因此需要使用 keep-alive 進行緩存,而且關閉之後的標簽頁就不再緩存,避免關閉後再打開還是之前的狀態。keep-alive 的屬性 include 的作用就是只有匹配的組件會被緩存。include 匹配的不是路由名,而是組件名,那麼每個組件都需要添加 name 屬性。

在 Tags 組件中,監聽路由變化,將打開的路由添加到標簽頁中:

export default {
    data() {
        return {
            tagsList: []
        }
    },
    methods: {
        setTags(route){
            const isExist = this.tagsList.some(item => {
                return item.path === route.fullPath;
            })
            if(!isExist){
                this.tagsList.push({
                    title: route.meta.title,
                    path: route.fullPath,
                    name: route.matched[1].components.default.name
                })
            }
        }
    },
    watch:{
        $route(newValue, oldValue){
            this.setTags(newValue);
        }
    }
}

在 setTags 方法中,將一個標簽對象存到標簽數組中,包括title(標簽顯示的title),path(標簽的路由地址),name(組件名,用於include匹配的)。路由地址需要用 fullPath 欄位,如果使用 path 欄位,那如果地址後面帶有參數,就都沒保存起來了。

在 Home 組件中,監聽到標簽的變化,緩存需要的組件。

<keep-alive :include="tagsList">
    <router-view></router-view>
</keep-alive>
export default {
    data(){
        return {
            tagsList: []
        }
    },
    created(){
        // 只有在標簽頁列表裡的頁面才使用keep-alive,即關閉標簽之後就不保存到記憶體中了。
        bus.$on('tags', msg => {
            let arr = [];
            for(let i = 0, len = msg.length; i < len; i ++){
                // 提取組件名存到tagsList中,通過include匹配
                msg[i].name && arr.push(msg[i].name);
            }
            this.tagsList = arr;
        })
    }
}

總結

由於該項目中不包含任何業務代碼,所以還是相對比較簡單的,不過從開發中還是積累了一些經驗,在其它項目中可以更加熟練地開發。功能雖然不算多,但是也勉強夠用,如果有什麼好的建議,可以開 issue 一起討論。

更多文章:lin-xin/blog


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MySQL InnoDB的二級索引(Secondary Index)會自動補齊主鍵,將主鍵列追加到二級索引列後面。詳細一點來說,InnoDB的二級索引(Secondary Index)除了存儲索引列key值,還存儲著主鍵的值(而不是指向主鍵的指針)。為什麼這樣做呢?因為InnoDB是以聚集索引方式組... ...
  • 最近遇到的死鎖問題都發生在併發操作單張表上,比較有意思,就模擬了重現了一下。根據非聚集索引為條件,刪除某一個表的數據,類似於這麼一個語句,delete from table where nocluster_index in (x,y,z,m,n……)in裡面的內容不同,併發執行某些情況下,可能會引發 ...
  • to_timestamp('2011-11-11 11:11:11.1','yyyy-mm-dd hh24:mi:ss.ff') ...
  • 聚集索引添加規則 聚集索引按下列方式實現 PRIMARY KEY 和 UNIQUE 約束 在創建 PRIMARY KEY 約束時,如果不存在該表的聚集索引且未指定唯一非聚集索引,則將自動對一列或多列創建唯一聚集索引。 主鍵列不允許空值。 在創建 UNIQUE 約束時,預設情況下將創建唯一非聚集索引, ...
  • 我自己的經歷:剛開始大數據是看書,一頁頁的看書,因為身邊有一個好的資源,有問題可以問我朋友,後來發現看大數據的零基礎書籍很難看下去,很多專業的東西對於一個新手根本就看不懂,沒有什麼效率。(在這裡我個人建議,初學不要看書,我的建議是學完一部分後用書去溫習,這樣很多東西都可以明白,並且可以查缺補漏) 學 ...
  • 在Editext的佈局屬性上加上 android:textCursorDrawable="@drawable/cursor_shape" cursor_shape如下: 事實證明:設置android:height無效,應該用padding的方法。 top設置為-2dp :讓游標頂部下移2dp bot ...
  • 一.Android studio的安裝 我們可以從中文社區http://www.android-studio.org/下載Android studio最新版本,然後點擊安裝即可。 之後我們直接運行android-studio它會先報錯因為缺少SDK,接著我們點擊安裝即可,建議在安裝sdk的時候選擇好 ...
  • 使用場景 在開發中,我們可能會遇到一些對非同步請求數做併發量限制的場景,比如說微信小程式的request併發最多為5個,又或者我們需要做一些批量處理的工作,可是我們又不想同時對伺服器發出太多請求(可能會對伺服器造成比較大的壓力)。這個時候我們就可以對請求併發數進行限制,並且使用排隊機制讓請求有序的發送 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...