美文网首页前端开发那些事儿
二、vue+ElementUI开发后台管理模板—vuex状态管理

二、vue+ElementUI开发后台管理模板—vuex状态管理

作者: 吃自己家大米 | 来源:发表于2020-05-20 07:28 被阅读0次

    (获取本节完整代码 GitHub/chizijijiadami/vue-elementui-2

    0、写在前面

    关于布局:我们常见的后台管理页面结构一般有下图中显示的三种,如果把Tabs(导航的多标签显示)、Crumbs(面包屑)、Content(页面内容)和Footer(底部)当做中间区域视为一块整体,可以看到主要的区别就是Menu(菜单栏)位置的区别,待会我们就根据这些来设立vuex(vuex官网)的布局状态值,主要考虑以下两点:
    (1)菜单栏的位置;
    (2)设置是否需要该模块,包括Tabs、Crumbs、Foooter。

    关于功能:在后台模板中我们会用到以下几种功能:
    ● Menu菜单自动化
    ● Tabs多标签
    ● Crumbs面包屑导航
    ● vuex 的 modules
    ● svg 图标雪碧图 svg-sprite-loader
    ● 批量导入资源
    ● 自定义全局组件—批量全局注册
    ● 自定义全局方法
    ● 获取接口数据、模拟数据——axios+Mockjs 【关联:axios源码学习到使用】
    ● 精确到按钮级别的权限控制

    行动前准备:接下来我们用 GitHub/chizijijiadami/hand-to-hand 的代码来做准备些工作。可以参见下文章 vue实践1.1 企业官网——prerender-spa-plugin预渲染 ,第2段 css预处理器stylusstylus官网)、第5段vuex状态管理vuex官网 )。
    a、运行后自动打开浏览器src>package.json

    - "serve": "vue-cli-service serve --mode development",
    + "serve": "vue-cli-service serve --mode development --open",
    

    b、安装

    yarn add  vuex  element-ui
    yarn add  stylus stylus-loader -D
    

    c、src>App.vue

    <template>
      <div id="app">
    -    <header>
    -      <nav><router-link to="/index">index</router-link><router-link to="/list">list</router-link></nav>
    -    </header>
        <router-view></router-view>
      </div>
    </template>
    <script>
    export default {
      name: 'App',
    }
    </script>
    

    d、src>main.js

    + import Element from "element-ui";
    + import 'element-ui/lib/theme-chalk/index.css';
    + // 使用Element UI
    + Vue.use(Element, {
    +   size: "small"
    + });
    
    - import './assets/styles/reset.css'
    - import './assets/styles/style.css'
    

    e、src>pages>Index>index.vue

    <template>
      <div>
        <p class="index-p">Index-index</p>
    -    <img src="~@/assets/images/jerry.png" alt="" srcset="">
      </div>
    </template>
    <script>
    export default {
        name:"IndexIndex",
    -    created(){
    -      console.log(process.env.VUE_APP_BASE_API,'输出VUE_APP_BASE_API');
          
    -    }
    }
    </script>
    - <style>
    -  @import '~@/assets/styles/component.css'
    - </style>
    

    f、删除
    src>assets>images>jerry.png
    src>assets>styles>component.css
    src>assets>styles>reset.css
    src>assets>styles>style.css

    准备工作到此结束。

    1、新建布局文件

    src>pages>Layout>components>Header.vue

    <template>
      <div class="app-header">header</div>
    </template>
    

    src>pages>Layout>components>Mune.vue

    <template>
      <div class="app-menu">
        <el-menu router default-active="/index/index" class="el-menu-vertical-demo">
            <el-menu-item index="/index/index">
              <i class="el-icon-location"></i>
              <span>首页</span>
            </el-menu-item>
          <el-submenu index="list">
            <template slot="title">
              <i class="el-icon-s-grid"></i>列表
            </template>
              <el-menu-item index="/list/detail">
                <i class="el-icon-goods"></i>详情
              </el-menu-item>
              <el-menu-item index="/list/feature">
                <i class="el-icon-document"></i>特性
              </el-menu-item>
          </el-submenu>
        </el-menu>
      </div>
    </template>
    

    src>pages>Layout>components>Tabs.vue

    <template>
      <div clss="app-tabs">
        <el-tabs  type="card">
          <el-tab-pane
            label="首页"
          ></el-tab-pane>
        </el-tabs>
      </div>
    </template>
    

    src>pages>Layout>components>Crumbs.vue

    <template>
      <div clss="app-crumbs">
        <el-breadcrumb separator-class="el-icon-arrow-right">
          <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
        </el-breadcrumb>
     </div>
    </template>
    

    src>pages>Layout>components>Content.vue

    <template>
       <div class="app-content"><router-view></router-view></div>
    </template>
    

    src>pages>Layout>components>Footer.vue

    <template>
      <div class="app-footer">大米工厂</div>
    </template>
    

    src>pages>Layout>index.vue

    <template>
      <div class="app-page">
        <Header />
        <Menu />
        <div class="app-container">
          <Tabs />
          <Crumbs />
          <Content />
          <Footer />
        </div>
    </div>
    </template>
    <script>
    import Header from "./components/Header";
    import Tabs from "./components/Tabs";
    import Menu from "./components/Menu";
    import Crumbs from "./components/Crumbs";
    import Content from "./components/Content";
    import Footer from "./components/Footer";
    export default {
      components: {
        Header,
        Menu,
        Tabs,
        Crumbs,
        Content,
        Footer
      }
    };
    </script>
    
    2、修改src>router>index.js

    Vue Router 滚动行为

    export default new Router({
    +    scrollBehavior() {    //页面内容多过一屏时,需设置滚动位置
    +        return { x: 0, y: 0 }
    +    },
        routes: [
          {
                path: '',
    -           redirect: '/index',
    +           redirect: '/index/index'
            },
            {
                  path: '/index',
    -             component: _import('Index/index')
    +             component: _import('Layout/index'),
    +             redirect: '/index/index',
    +             children:[
    +                 {
    +                     path: 'index',
    +                     component: _import('Index/index'), 
    +                 }
    +             ]
             },
              {
                 path: '/list',
    -            component: _import('List/index'),
    +            component: _import('Layout/index'),
                 children: [
                      {
                          path: 'detail',
                          component: _import('List/Detail/index')
                      },
                      {
                        path: 'feature',
                         component: _import('List/Feature/index')
                    }
                 ]
            },
           {
                path: '/404',
                component: _import('ErrorPages/404')
            },
            {
                path: '*',
                redirect: '/404'
            }
        ]
    })
    

    访问检查下个模块都加载出来了,接下来我们先按照布局1来写样式.

    3、布局1样式

    (1)样式文件中
    src>assets>styles>reset.styl

    //  主要是一些原生样式的覆盖,直接看源代码
    

    src>assets>styles>base.styl

    $body-bgcolor=#f5f6f7
    html
       background-color $body-bgcolor
    

    src>assets>styles>layout.styl

    $bg-color = #eee
    $header_height = 60px
    $menu_width = 200px
    .app-header
      background-color white
      position absolute
      top 0
      left 0
      height $header_height
      width 100%
    .app-menu
      background-color white
      position absolute
      top $header_height
      left 0
      width $menu_width
      height calc(100% - 60px) // $header_height
    .app-container
      height 100vh
      padding $header_height  0 0 $menu_width
    .app-tabs
      background-color white
      height 40px
    .app-crumbs
      height 30px
      line-height 30px
    .app-content
      background-color white
      padding 0 10px
      min-height calc(100% - 40px - 30px - 40px) // app-tabs_height、app-crumbs_height、app-footer_height
    .app-footer
      background-color white
      height 40px
      line-height 40px
    

    src>assets>styles>index.styl ,统一导入样式

    @require './reset.styl'
    @require './base.styl'
    @require './layout.styl'
    

    src>main.js中引用

    //样式
    import "@/assets/styles/index.styl";
    
    浏览器中查看一下,有了。

    尽管stylus中有了变量,但是无法跟 calc 友好结合,如果该变量涉及 calc 计算多的话在改版的时候容易漏掉,所以我们把这些搬运到布局文件中进行。
    (2)在布局文件中计算
    src>pages>Layout>index.vue

    <template>
      <div class="app-page">
    +    <Header :style="{height:header.height}" />
    +    <Menu :style="{top:header.height,width:menu.width,height:menuHeight()}" />
    +    <div class="app-container" :style="{padding:containerPadding()}">
    +      <Tabs :style="{height:tabs.height}" />
    +      <Crumbs :style="{height:crumbs.height,padding:'0 '+content.margin}"   :crumbs="crumbs" :content="content"/>
    +      <Content :style="{'min-height':contentMinHeight(),margin:contentMargin()}"/>
    +      <Footer :style="{height:footer.height,'line-height':footer.height}" />
        </div>
      </div>
    </template>
    <script>
    import Header from "./components/Header";
    import Tabs from "./components/Tabs";
    import Menu from "./components/Menu";
    import Crumbs from "./components/Crumbs";
    import Content from "./components/Content";
    import Footer from "./components/Footer";
    export default {
      components: {
        Header,
        Menu,
        Tabs,
        Crumbs,
        Content,
        Footer
      },
    +  data() {
    +    return {
    +      header: {
    +        height: "60px"
    +      },
    +      menu: {
    +        width: "200px"
    +      },
    +      content: {
    +        margin: "10px"
    +      },
    +      tabs: {
    +        height: "40px"
    +      },
    +      crumbs: {
    +        height: "30px"
    +      },
    +      footer: {
    +        height: "40px"
    +      }
    +    };
    +  },
    +  methods: {
    +    menuHeight() {
    +      return "calc(100% - " + this.header.height + ")";
    +    },
    +    containerPadding() {
    +      return (
    +        this.header.height +
    +        " 0 0 " +
    +        this.menu.width
    +      );
    +    },
    +    contentMinHeight() {
    +      return (
    +        "calc(100% - " +
    +        this.tabs.height +
    +        " - " +
    +        this.crumbs.height +
    +        " - " +
    +        this.footer.height +
    +        ")"
    +      );
    +    }
    +  }
    };
    </script>
    

    src>assets>style>layout.styl

    $bg-color = #eee
    - $header_height = 60px
    - $menu_width = 200px
    .app-header
      background-color white
      position absolute
      top 0
      left 0
    -   height $header_height
      width 100%
    .app-menu
        background-color white
        position absolute
    -   top $header_height
        left 0
    -   width $menu_width
    -   height calc(100% - 60px) // $header_height
    .app-container
      height 100vh
    +  .app-tabs,.app-crumbs,.app-content,.app-footer
    +    background-color white   //这后面的都删掉
    -   padding $header_height 0 0 $menu_width
    - .app-tabs
    -   background-color white
    -   height 40px
    - .app-crumbs
    -   height 30px
    -   line-height 30px
    -.app-content
    -   background-color white
    -   padding 0 10px
    -   min-height calc(100% - 40px - 30px - 40px) // app-tabs_height、app-crumbs_height、app-footer_height
    -.app-footer
    -   background-color white
    -   height 40px
    -   line-height 40px
    

    调整结束,看一下浏览器是没有变化的。
    另外左侧菜单栏,往往是可以收缩的,下面我们从这里入手结合vuex进行布局调整。

    4、结合vuex实现多种布局样式

    (1)菜单栏收缩
    新建 src>data>store>index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    const store=new Vuex.Store({
        state: { 
            menu: {
                isCollapse: false  //默认菜单展开
            }
        },
        mutations: {
            SET_MENU_ISCOLLAPSE: state => {
                state.menu.isCollapse = !state.menu.isCollapse
            }
        },
        actions: {
            setMenuIsCollapse({ commit }) {
                commit('SET_MENU_ISCOLLAPSE')
            }
        }
      })
    export default store
    

    引入 src>main.js

    + import store from './data/store'
    
    new Vue({
       router,
    +  store,
       render: h => h(App),
    }).$mount('#app')
    

    菜单页面中取值 src>pages>Layout>components>Menu.vue

    -  <el-menu router default-active="/index/index" class="el-menu-vertical-demo">
    +  <el-menu :collapse="isCollapse" :collapse-transition="false"  router
                                                           default-active="/index/index" class="el-menu-vertical-demo">
    
    + <script>
    + export default {
    +   computed: {
    +     isCollapse() {
    +       return this.$store.state.menu.isCollapse;
    +     }
    +   }
    + };
    + </script>
    

    添加控制事件 src>pages>Layout>components>Hearder.vue

    <template>
    -  <div class="app-header"></div>
    +  <div class="app-header">
    +    <el-button type="primary" plain  :icon="isCollapse?'el-icon-s-fold':'el-icon-s-unfold'"></el-button>
    +  </div>
    </template>
    + <script>
    + export default {
    +   computed: {
    +     isCollapse() {
    +       return this.$store.state.menu.isCollapse;
    +     }
    +   },
    +   methods:{
    +     setMenuIsCollapse(){
    +       this.$store.dispatch('setMenuIsCollapse');
    +     }
    +   }
    + };
    + </script>
    

    点击看看效果,可以收缩,但是外边 div 没有同时进行收缩,布局文件中再改点东西。
    src>pages>Layout>components>Hearder.vue

    -   <Menu :style="{top:header.height,widthmenu.width,height:menuHeight()}" />
    +   <Menu :style="{top:header.height,width:isCollapse?menu.widthCollapse:menu.width,height:menuHeight()}" />
    
    +  computed: {  //script中添加
    +    isCollapse() {
    +      return this.$store.state.menu.isCollapse;
    +    }
    +  },
    

    这么加只是收缩了菜单栏外层,还有 app-container 的 padding 也要调整

        containerPadding() {
          return (
             this.header.height +
             " 0 0 " +
    -         this.menu.width
    +        (this.isCollapse ? this.menu.widthCollapse : this.menu.width)
          );
        },
    

    现在点点看,就正常了。

    (2)菜单栏位置变化
    根据我们前面的布局分类给菜单栏位置设定状态值。
    src>data>store>index.js

            menu: {
                isCollapse: false,
     +           location:"VH"   //V、VH、H三个值,V表示在左侧,VH表示横跨头部,H表示在头部,默认 V
            }
    

    根据这个设定,我们目前的布局是 V,现在我们做 VH 。
    src>pages>Layout>index.vue——在布局页获取

      computed: {
        isCollapse() {
          return this.$store.state.menu.isCollapse;
        },
    +    menuLocation(){
    +        return this.$store.state.menu.location;
    +    }
      },
    

    观察布局图,从V到VH只是菜单栏跟头部的决定定位值不同。那么我们要做的,修改Menu的 top、height 属性加,Header的 left、width属性。
    src>pages>Layout>index.vue

    - <Header :style="{height:header.height}" />
    - <Menu :style="{top:header.height,width:isCollapse?menu.widthCollapse:menu.width,height:menuHeight()}" />
    + <Header :style="{height:header.height,left:headerLeft(),width:headerWidth()}" />
    + <Menu :style="{top:menuTop(),width:this.menuWidth(),height:menuHeight()}" />
    
     methods:{
    +  headerLeft(){  //涉及三目运算多时,最好加上括号方便读码——这里别忘记菜单栏的收缩
    +     return this.menuLocation === "V" ? "0" : ( this.isCollapse ? this.menu.widthCollapse : this.menu.width );
    +  },
    +  headerWidth(){
    +      return this.menuLocation==="V" ? "100%" : "calc(100% - "+this.menuWidth()+")"
    +  },
    +  menuTop() {
    +     return this.menuLocation === "V" ? this.header.height : "0";
    +  },
       menuHeight() {
    -     return "calc(100% - " + this.header.height + ")";
    +     return  this.menuLocation==="V" ? "calc(100% - " + this.header.height + ")" : "100vh";
       },
    +  menuWidth(){    //这个值用到的比较多我们单独写成一个方式使用
    +     return this.isCollapse?this.menu.widthCollapse:this.menu.width;
    +  },
        containerPadding() {
          return (
            this.header.height +
            " 0 0 " +
    -      (this.isCollapse ? this.menu.widthCollapse : this.menu.width)
    +      this.menuWidth()
          );
        },
     ......
     }
    

    src>assets>style>layout.styl

    .app-header
       background-color white
       position absolute
       top 0
    -  left 0
    -  width 100%
    .app-menu
       background-color white
       position absolute
    -  left 0
    .app-container
       height 100vh
       .app-tabs,.app-content,.app-footer
         background-color white
    

    修改完成,浏览器里点点看。
    接下来,我们写 H 布局。
    src>data>store>index.js

            menu: {
                isCollapse: false,
    -           location:"VH"   //V、VH、H三个值,V表示在左侧,VH表示横跨头部,H表示在头部
    +           location:"H"   //V、VH、H三个值,V表示在左侧,VH表示横跨头部,H表示在头部
            }
    

    观察一下,相对其他两个布局,布局文件Menu这块是直接没了的,还要修改app-container的 padding,Herder的 left、width 属性。
    src>pages>Layout>index.vue

    -  <Menu :style="{top:menuTop(),width:this.menuWidth(),height:menuHeight()}" />
    +  <Menu v-if="menuLocation!=='H'" :style="{top:menuTop(),width:this.menuWidth(),height:menuHeight()}" />
    //methods中
        headerLeft(){
    -     return this.menuLocation==="V" ? "0": this.menuWidth();
    +     return this.menuLocation==="V" || this.menuLocation==="H" ? "0": this.menuWidth();
        },
        headerWidth(){
    -        return this.menuLocation==="V" ? "100%" : "calc(100% - "+this.menuWidth()+")"
    +        return this.menuLocation==="V" || this.menuLocation==="H" ? "100%" : "calc(100% - "+this.menuWidth()+")"
        },
    
        menuWidth() {
    -     return this.isCollapse ? this.menu.widthCollapse : this.menu.width;
    +     return this.menuLocation === "H"?"0px":this.isCollapse ? this.menu.widthCollapse : this.menu.width;
        },
    

    到这里还剩下菜单栏没有在Header中显示,我们接着改Header。
    src>pages>Layout>componets>Header.vue

    <template>
      <div class="app-header">
    -    <el-button type="primary"  plain  @click='setMenuIsCollapse' :icon="isCollapse?'el-icon-s-fold':'el-icon-s-unfold'"></el-button>
    +    <Menu  v-if="menuLocation==='H'"/>
    +    <el-button v-if="menuLocation!=='H'" type="primary"  plain  @click='setMenuIsCollapse' :icon="isCollapse?'el-icon-s-fold':'el-icon-s-unfold'"></el-button>
      </div>
    </template>
    <script>
    + import Menu from "./Menu";
    + export default {
    +   components:{
    +     Menu
    +   },
      computed: {
        isCollapse() {
          return this.$store.state.menu.isCollapse;
        },
    +     menuLocation() {
    +       return this.$store.state.menu.location;
    +     }
      },
      methods:{
        setMenuIsCollapse(){
          this.$store.dispatch('setMenuIsCollapse');
        }
      }
    };
    </script>
    

    src>pages>Layout>componets>Menu.vue

        <el-menu
          :collapse="isCollapse"
          :collapse-transition="false"
          router
          default-active="/index/index"
          class="el-menu-vertical-demo"
    +      :mode="menuLocation==='H'?'horizontal':'vertical'"
        >
    
    <script>
    export default {
      computed: {
         isCollapse() {
           return this.$store.state.menu.isCollapse;
         },
    +    menuLocation() {
    +       return this.$store.state.menu.location;
    +    }
      }
    };
    </script>
    

    这就全部改好了,随意切换下布局状态值,完美 :)

    (3)Tabs、Crumbs、Footer状态
    src>data>store>index.js

        state: { 
            menu: {
                isCollapse: false,
                location:"VH"   //V、VH、H三个值,V表示在左侧,VH表示横跨头部,H表示在头部
            },
    +        tabs:{
    +             isShow:true
    +         },
    +         crumbs:{
    +             isShow:true
    +         },
    +         footer:{
    +             isShow:true
    +         }
        },
    

    src>pages>Layout>index.vue

        <div class="app-container" :style="{padding:containerPadding()}">
    -     <Tabs :style="{height:tabs.height}" />
    -     <Crumbs v-if="isShowCrumbs" :style="{height:crumbs.height,padding:'0 '+content.margin}" :crumbs="crumbs" :content="content" />
    +     <Tabs v-if="isShowTabs" :style="{height:tabs.height}" />
    +     <Crumbs v-if="isShowCrumbs" :style="{height:crumbs.height,padding:'0 '+content.margin}" :crumbs="crumbs" :content="content" />
          <Content :style="{'min-height':contentMinHeight(),margin:contentMargin()}" />
    -     <Footer  :style="{height:footer.height,'line-height':footer.height}" />
    +     <Footer v-if="isShowFooter" :style="{height:footer.height,'line-height':footer.height}" />
        </div>
    
      computed: {
        isCollapse() {
          return this.$store.state.menu.isCollapse;
        },
        menuLocation() {
          return this.$store.state.menu.location;
        },
    +    isShowTabs(){
    +      return this.$store.state.tabs.isShow;
    +    },
    +    isShowCrumbs(){
    +      return this.$store.state.crumbs.isShow;
    +    },
    +    isShowFooter(){
    +      return this.$store.state.footer.isShow;
    +    }
      },
    

    现在可以修改相应的状态值,看下页面这些组件的显示情况,内容不够一屏时需要页面撑开,就需要调整Content的 min-height 属性,先穷举组合情况:
    ● Content
    ● Tabs + Content
    ● Crumbs + Content
    ● Tabs + Crumbs + Content
    ● Tabs + Crumbs + Content + Footer
    ● Crumbs + Content + Footer
    ● Tabs + Content + Footer
    ● Content + Footer
    src>pages>Layout>index.vue

        contentMargin() {
    -     return "0 " + this.content.margin;
    +     let marginTop = this.isShowCrumbs ? "0" : this.content.margin;
    +     let marginBottom = this.isShowFooter ? "0" : this.content.margin;
    +     return marginTop + " " + this.content.margin +" "+ marginBottom;
        },
        contentMinHeight() {
    -      return (
    -        "calc(100% - " +
    -        this.tabs.height +
    -        " - " +
    -        this.crumbs.height +
    -        " - " +
    -        this.footer.height +
            ")"
    -      );
    +      let tabsHeight = this.isShowTabs ?  this.tabs.height: "0px" ;
    +      let crumbsHeight = this.isShowCrumbs ? this.crumbs.height : this.content.margin;  //只有content时留有底部空隙
    +      let footerHeight = this.isShowFooter ? this.footer.height : this.content.margin;
    +      return ("calc(100% - " +tabsHeight + " - " +crumbsHeight +" - " +footerHeight +")");
        }
    

    现在任意调整状态值看看。

    (4)Tabs位置调整
    随意在一个页面添加超过一屏的内容,滚动看看,发现忘记将 Tabs 浮动置顶了,现在修改添加一下。
    src>assets>style>layout.styl

      .app-menu
        background-color white
        position fixed
    + .app-tabs
    +   position fixed
    

    src>pages>Layout>index.vue

    -  <Tabs v-if="isShowTabs" :style="{height:tabs.height}" />
    +  <Tabs v-if="isShowTabs" :style="{height:tabs.height,top:header.height,left:tabsLeft(),width:tabsWidth()}" />
    
        containerPadding() {
    +    let tabsHeight=this.isShowTabs ? this.tabs.height : "0px"
    +    let paddingTop=parseInt(this.header.height)+parseInt(tabsHeight)+"px"
          return (
    -       this.header.height +
    +       paddingTop +
            " 0 0 " +
            this.menuWidth()
          );
         },
    +    tabsLeft(){
    +        return this.menuWidth();
    +    },
    +    tabsWidth(){
    +        return "calc(100% - "+this.menuWidth()+" )"
    +    },
    
        contentMinHeight() {
    -      let tabsHeight = this.isShowTabs ?  this.tabs.height: "0px" ;   //tabs的高已经在containerPadding中有计算,此处去掉
           let crumbsHeight = this.isShowCrumbs ? this.crumbs.height : this.content.margin;
           let footerHeight = this.isShowFooter ? this.footer.height : this.content.margin;
    -      return ("calc(100% - " +tabsHeight + " - " +crumbsHeight +" - " +footerHeight +")");
    +      return ("calc(100% - " +crumbsHeight +" - " +footerHeight +")");
        }
    

    到此我们后台模板最基本的布局就写成了,接下来我们需要进行模板块功能的实现:Menu菜单自动化(现在Menu中的导航都是我们手写的,应当根据路由文件router自动生成相应数据为佳)、Tabs多标签、Crumbs路径等将在接下来的文章中实现。

    这里拿到的代码中一些文件的引入路径跟文章里的是有些区别的,小伙伴么可以想到是为什么么,答案下章说哦。

    感谢阅读,喜欢的话点个赞吧:)
    更多内容请关注后续文章。。。

    一、vue入门基础开发—手把手教你用vue开发
    三、vue+ElementUI开发后台管理模板—功能、资源、全局组件
    四、vue+ElementUI开发后台管理模板—方法指令、接口数据
    五、vue+ElementUI开发后台管理模板—精确到按钮的权限控制

    vue3 + vite + ElementPlus开发后台管理模板

    vue实践1.1 企业官网——prerender-spa-plugin预渲染

    相关文章

      网友评论

        本文标题:二、vue+ElementUI开发后台管理模板—vuex状态管理

        本文链接:https://www.haomeiwen.com/subject/zjtightx.html