Vue折腾记

来源:互联网 发布:网络连接电视怎么连接 编辑:程序博客网 时间:2024/05/23 12:33

前言

本来想写个新手系列教程..发现这种东西一搜索一大把;
那就写点实战类的吧;这篇文章你能学点什么?
当然是一些常见内置指令的用法,组件过渡,遍历的思路等等


效果图

这里写图片描述

实现思路

  • 过渡用css -
  • 遍历循环判断(比对路由,点击的项名等)
  • 增加标记位来默认展开刷新页面当前所在项
  • 尽量减少DOM的改动,能用v-show的区域绝不用v-if

- 自定义菜单JSON尽量格式简洁,没有一大坨标记位这些干扰物(越简单越方便后期)

代码

  • 菜单menuList.js
export const MENULIST = [  {    menuName: "客户管理",    menuIcon: "fz-ad-icon-test",    menuSubLink: [      {        menuName: "广告主",        menuUrl: "/customer/adhost"      },      {        menuName: "渠道",        menuUrl: "/customer/channel"      }    ]  },  {    menuName: "广告管理",    menuIcon: "fz-ad-guanggao",    menuSubLink: [      {        menuName: "广告新增",        menuUrl: "/ad/add"      },      {        menuName: "广告审核",        menuUrl: "/ad/check"      }    ]  },  {    menuName: "投放管理",    menuIcon: "fz-ad-toufang",    menuSubLink: [      {        menuName: "广告位",        menuUrl: "/puton/area"      },      {        menuName: "广告规格",        menuUrl: "/puton/regular"      }    ]  },  {    menuName: "数据统计",    menuIcon: "fz-ad-statistics",    menuSubLink: [      {        menuName: "广告主",        menuUrl: "/status/adhost"      },      {        menuName: "渠道",        menuUrl: "/status/channel"      }    ]  },  {    menuName: "管理者",    menuIcon: "fz-ad-guanli",    menuUrl: "/manager"  },  {    menuName: "操作日志",    menuIcon: "fz-ad-rizhi",    menuUrl: "/logger"  }];
  • Sidebar.vue
<template>  <div class="sidebar" >    <ul class="sidebar-menu ">`      <template v-for="(item ,index) in menulist">        <li :class="currentUrl === item.menuUrl ? 'active':''">          <template v-if="item.menuUrl">            <router-link :to="item.menuUrl" @click.native="toggleName=''">              <i :class="['fzicon',item.menuIcon]"></i>              <span>{{item.menuName}}</span>            </router-link>          </template>          <template v-else-if="item.menuSubLink">            <a href="javascript:;" @click="isToggle(item.menuName,item.defaultActive)">              <i :class="['fzicon',item.menuIcon]"></i>              <span>{{item.menuName}}</span>              <i class="trangle" :class="[config.iconfont, (item.menuName === toggleName) || item.defaultActive? config.icon_expand: config.icon_collapse]">              </i>            </a>            <transition name="sliderToggle" mode="out-in">              <ul class="tree-menu" v-show="item.menuName === toggleName || item.defaultActive">                <li v-for="(subitem,subindex) in item.menuSubLink" :key="subitem" :class="currentUrl === subitem.menuUrl ? 'active':''">                  <router-link :to="subitem.menuUrl">                    <i :class="subitem.menuIcon"></i>                    <span>{{subitem.menuName}}</span>                  </router-link>                </li>              </ul>            </transition>          </template>        </li>      </template>    </ul>  </div></template><script>import { MENULIST } from './menuList'; // 引入的自定义菜单数据export default {  name: 'layout-sidebar',  data: function () {    return {      menulist: MENULIST, // 自定义菜单数据      currentUrl: '', // 当前浏览器的url      toggleName: '',  // 菜单子项目名称      config: {        'iconfont': 'fzicon', // iconfont的字体        'icon_collapse': 'fz-ad-jiantou', // 箭头        'icon_expand': 'fz-ad-jiantou1' // 箭头      }    }  },  props: ['toggle', 'padMode'], // 这里是用来构成布局响应传递的props,单一组件不用管他  watch: {    '$route'() {      this.currentUrl = this.$route.fullPath; // 实时监测当前路由的变化并且赋值    }  },  methods: {    isToggle(name, defaultActive) {      this.clearDefaultActive(); // 清除标记位,是否当前为默认展开      defaultActive ? false : name !== this.toggleName ? this.toggleName = name : this.toggleName = ''; // 判断展开收缩的核心    },    clearDefaultActive() {      this.menulist.forEach(item => {        this.$delete(item, 'defaultActive')      })    }  },  created: function () {    this.currentUrl = this.$route.fullPath;    this.$nextTick(() => {      this.menulist.forEach((item, index) => { // 增加标记位,判断当前url然后自动展开或者激活对应项(刷新默认展开当前url的项)        if (!item.menuSubLink && item.menuUrl) {          this.currentUrl === item.menuUrl ? this.$set(item, 'defaultActive', true) : '';        } else {          if (item.menuSubLink) {            item.menuSubLink.forEach((subitem, index) => {              this.currentUrl === subitem.menuUrl ? this.$set(item, 'defaultActive', true) : '';            })          }        }      })    })  },  mounted: function () {  }}</script><style scoped lang="scss">// 自定义过渡效果.sliderToggle-enter-active,.sliderToggle-leave-active {  transition: all 0.5s linear;  height: 100%;  height: auto;  overflow: hidden;}.sliderToggle-enter,.sliderToggle-leave-to {  overflow: hidden;  padding-top: 0;  padding-bottom: 0;  height: 0;  opacity: 0;}// 侧边栏全局样式.sidebar {  position: absolute;  top: 0;  left: 0;  padding-top: 68px;  min-height: 100%;  z-index: 810;  transition: all 0.3s linear;  background-color: #222d32;  .sidebar-menu {    list-style: none;    margin: 0;    padding: 0;    white-space: nowrap;    span {      cursor: pointer;    }    a {      text-decoration: none;      color: #8aa4af;      &:hover {        color: #fff;      }    }    ul {      list-style: none;      margin: 0;      padding: 0;      white-space: nowrap;      overflow: hidden;    }    >li {      position: relative;      margin: 0;      padding: 0;      text-align: left;      &.active {        color: #fff;      }      >a {        border-left: 3px solid transparent;        position: relative;        padding: 15px 5px 15px 19px;        display: block;        font-size: 14px;        >i {          padding-right: 4px;        }        .trangle {          float: right;          padding-right: 10px;        }      }      &.active {        >a {          border-left: 3px solid #3c8dbc;          color: #fff;        }      }      >.tree-menu {        margin: 0 1px;        background: #2c3b41;        list-style: none;        padding: 0;        margin: 0;        .tree-menu {          padding-left: 20px;        }        >li {          margin: 0;          &.active {            >a {              border-left: 3px solid #3c8dbc;              color: #fff;            }          }          >a {            padding: 15px 10px 15px 40px;            display: block;            font-size: 14px;            border-left: 3px solid transparent;          }        }        &.active {          display: block;        }      }    }  }  &.expand {    width: 230px;  }  &.collapse {    width: 50px;    .sidebar-menu {      >li {        >a {          padding: 15px 5px 15px 15px;          span,          i:last-child {            display: none;          }        }        .tree-menu {          display: none;        }        &:hover {          >a {            display: block;            span {              display: block;              position: absolute;              left: 47px;              width: 153px;              padding: 15px 5px 15px 19px;              background-color: #222d32;              color: #fff;              width: 177px;              top: 0;              border-radius: 0 5px 0 0;            }            i:last-child {              display: inline-block;              position: absolute;              right: -165px;              top: 50%;              transform: translateY(-50%);              color: #fff;            }          }          >.tree-menu {            display: block;            position: absolute;            left: 47px;            width: 180px;            background-color: #222d32;            color: #fff;            top: 46px;            width: 180px;            border-radius: 0 0 5px 5px;          }        }      }    }  }}</style>

总结

实际上这货就是把adminlte的风格用vue实现了…
还有变形金刚版本,,整个响应涉及几个到组件间的通讯;
就不把全部代码丢出来了,一大坨…

效果是这样的

这里写图片描述