這篇文章帶給大家的內容是關於vue-manage-system後台管理系統開發的過程(程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
vue-manage-system,一個基於Vue.js 和element-ui 的後台管理系統模板,從2016年年底第一個commit,到現在差不多兩年了, GitHub上也有了5k star,也是這些讓我有了持續更新的動力,其中也踩了很多坑,在這總結一下。
github位址:vue-manage-system
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> <p id="app"></p> </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(); }) } }
不過也要記得元件銷毀時移除監聽喔!監聽視窗大小改變完成了,那父元素大小改變呢?因為父元素寬度設為百分比,當側邊欄折疊的時候,父元素的寬度改變了。但是 p 並沒有 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 一起讨论。
相关推荐:
ASP.NET MVC5+EF6+EasyUI 后台管理系统微信公众平台开发
基于thinkphp的后台管理系统模板快速搭建,thinkphp后台模板
以上是vue-manage-system在後台管理系統開發的過程(程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!