Le contenu de cet article concerne le processus de développement (code) du système de gestion d'arrière-plan vue-manage-system. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
vue-manage-system, un modèle de système de gestion backend basé sur Vue.js et element-ui, fait presque deux ans depuis son premier commit fin 2016. Il Il y a aussi 5 000 étoiles sur GitHub, ce qui m'a donné la motivation pour continuer la mise à jour. J'ai également rencontré de nombreux pièges, que je vais résumer ici.
Adresse github : vue-manage-system
element-ui est livré avec relativement peu d'icônes de police, et la plupart des plus courantes ne sont pas disponibles, donc vous avez besoin de présenter vous-même les icônes de police que vous souhaitez. La bibliothèque d'icônes la plus populaire, Font Awesome, contient 675 icônes, mais cela donne également un fichier de polices relativement volumineux et il n'est pas nécessaire d'utiliser autant d'icônes dans le projet. Alors en ce moment, Alibaba Icon Library est un très bon choix.
Créez d'abord un projet sur l'icône Ali, définissez le préfixe de l'icône, tel que el-icon-lx, définissez la famille de polices, telle que lx-iconfont, ajoutez les icônes que vous devez utiliser au projet, je choisis La classe Font here génère des liens en ligne, car toutes les pages doivent utiliser des icônes, introduisez simplement le lien CSS directement dans index.html
<!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>
Ensuite, vous devez définir le nom de la classe d'icônes avec le préfixe el-icon- lx Utilisez la police lx-iconfont.
[class*="el-icon-lx"], [class^=el-icon-lx] { font-family: lx-iconfont!important; }
Mais où dois-je placer ce style ? Ce n’est pas quelque chose que vous pouvez mettre en place avec désinvolture. Dans main.js, le style element-ui est introduit, et il y a un morceau de CSS dans le style :
[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; }
Évidemment, si ce morceau de CSS est exécuté après notre style personnalisé, ce sera le cas. notre style est écrasé, l'icône personnalisée ne sera pas affichée. Lors de la construction du projet, les styles dans APP.vue seront regroupés dans app.css, puis les styles référencés dans main.js seront ajoutés à l'arrière. Ensuite, nous pouvons mettre le style personnalisé dans un fichier CSS, puis l'introduire après l'introduction du CSS element-ui dans main.js, puis la police par défaut peut être écrasée, puis l'icône peut être utilisée dans le projet via <i class="el-icon-lx-people"></i>
.
La personne intelligente a découvert que si le préfixe de mon icône personnalisée ne contient pas el-icon-, il n'y aura pas de problème de ce type. Oui, afin de conserver le même style que la police d'origine, vous devez copier l'intégralité de son 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; }
la documentation d'element-ui sur le menu de navigation est également très détaillée , mais certaines personnes soulèvent encore des problèmes ou ajoutent QQ pour me demander : Comment créer le menu de troisième niveau, etc. De plus, des éléments de menu spécifiques peuvent être des éléments de données spécifiques renvoyés par le serveur en fonction des autorisations, ils ne peuvent donc pas être codés en dur dans le modèle.
Déterminez d'abord le format des données du menu comme suit. Même si le format renvoyé par le serveur n'est pas comme celui-ci, le front-end doit le traiter dans le format suivant :
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页面' }] }] } } }
l'icône est l'icône du menu, vous pouvez l'utiliser. L'icône que nous avons personnalisée ci-dessus est l'adresse de routage est le nom du sous-menu ; Le modèle affiche le menu de deuxième niveau et le menu de troisième niveau en déterminant si le menu contient des sous-menus.
<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>
Ceci complète un menu de navigation dynamique.
Déclencher l'expansion ou la réduction du composant Sidebar via un bouton dans le composant Header implique le transfert de données entre les composants. Ici, la communication entre les composants est gérée via un centre d'événements distinct (Event Bus) de Vue.js.
const bus = new Vue();
Déclenchez l'événement de réduction lorsque vous cliquez sur le bouton dans le composant En-tête :
bus.$emit('collapse', true);
Écoutez l'événement de réduction dans le composant Barre latérale :
bus.$on('collapse', msg => { this.collapse = msg; })
Le plug-in de graphique utilisé dans vue-manage-system est vue-schart, qui encapsule un plug-in de graphique basé sur un canevas schart.js. Pour que le graphique s'adapte à sa largeur et soit restitué à mesure que la taille de la fenêtre ou de l'élément parent change, si cette fonction n'est pas implémentée dans le plug-in de graphique, vous devez l'implémenter manuellement.
vue-schart fournit la méthode renderChart() pour restituer le graphique Dans Vue.js, le composant parent appelle la méthode du composant enfant, qui peut être appelée via $refs.
<schart ref="bar" canvasId="bar" :data="data" type="bar" :options="options"></schart>
Écoutez ensuite l'événement resize de la fenêtre et appelez la méthode renderChart() pour restituer le graphique.
import Schart from 'vue-schart'; export default { components: { Schart }, mounted(){ window.addEventListener('resize', ()=>{ this.$refs.bar.renderChart(); }) } }
Mais pensez à retirer l'écouteur lorsque le composant est détruit ! Le changement de taille de la fenêtre d'écoute est terminé, mais qu'en est-il du changement de taille de l'élément parent ? Étant donné que la largeur de l'élément parent est définie sur un pourcentage, la largeur de l'élément parent change lorsque la barre latérale se réduit. Cependant, p n'a pas d'événement de redimensionnement et ne peut pas surveiller son changement de largeur, mais nous saurons quand le pliage est déclenché. Alors, est-il possible de restituer le graphique en appelant la fonction de rendu lorsque le pli change ? Ensuite, il est préférable de surveiller les modifications de la barre latérale via Event Bus et de la restituer après 300 ms, car il y a un processus d'animation de 300 ms lors du pliage
bus.$on('collapse', msg => { setTimeout(() => { this.$refs.bar.renderChart(); }, 300); });
Page multi-onglets également La fonctionnalité avec le plus de problèmes soulevés.
当在 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后台模板
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!