Explorar el Código

左侧菜单栏优化

Johnhong9527 hace 5 años
padre
commit
c3b37d5040

+ 36 - 32
build/webpack.base.conf.js

@@ -1,67 +1,71 @@
-'use strict'
-const path = require('path')
-const utils = require('./utils')
-const config = require('../config')
-const vueLoaderConfig = require('./vue-loader.conf')
+"use strict";
+const path = require("path");
+const utils = require("./utils");
+const config = require("../config");
+const vueLoaderConfig = require("./vue-loader.conf");
 
-function resolve (dir) {
-  return path.join(__dirname, '..', dir)
+function resolve(dir) {
+  return path.join(__dirname, "..", dir);
 }
 
-
-
 module.exports = {
-  context: path.resolve(__dirname, '../'),
+  context: path.resolve(__dirname, "../"),
   entry: {
-    app: './src/main.js'
+    app: "./src/main.js"
   },
   output: {
     path: config.build.assetsRoot,
-    filename: '[name].js',
-    publicPath: process.env.NODE_ENV === 'production'
-      ? config.build.assetsPublicPath
-      : config.dev.assetsPublicPath
+    filename: "[name].js",
+    publicPath:
+      process.env.NODE_ENV === "production"
+        ? config.build.assetsPublicPath
+        : config.dev.assetsPublicPath
   },
   resolve: {
-    extensions: ['.js', '.vue', '.json'],
+    extensions: [".js", ".vue", ".json"],
     alias: {
-      '@': resolve('src'),
+      "@": resolve("src"),
+      vue: "vue/dist/vue.esm.js"
     }
   },
   module: {
     rules: [
       {
         test: /\.vue$/,
-        loader: 'vue-loader',
+        loader: "vue-loader",
         options: vueLoaderConfig
       },
       {
         test: /\.js$/,
-        loader: 'babel-loader',
-        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
+        loader: "babel-loader",
+        include: [
+          resolve("src"),
+          resolve("test"),
+          resolve("node_modules/webpack-dev-server/client")
+        ]
       },
       {
         test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
-        loader: 'url-loader',
+        loader: "url-loader",
         options: {
           limit: 10000,
-          name: utils.assetsPath('img/[name].[hash:7].[ext]')
+          name: utils.assetsPath("img/[name].[hash:7].[ext]")
         }
       },
       {
         test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
-        loader: 'url-loader',
+        loader: "url-loader",
         options: {
           limit: 10000,
-          name: utils.assetsPath('media/[name].[hash:7].[ext]')
+          name: utils.assetsPath("media/[name].[hash:7].[ext]")
         }
       },
       {
         test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
-        loader: 'url-loader',
+        loader: "url-loader",
         options: {
           limit: 10000,
-          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+          name: utils.assetsPath("fonts/[name].[hash:7].[ext]")
         }
       }
     ]
@@ -72,10 +76,10 @@ module.exports = {
     setImmediate: false,
     // prevent webpack from injecting mocks to Node native modules
     // that does not make sense for the client
-    dgram: 'empty',
-    fs: 'empty',
-    net: 'empty',
-    tls: 'empty',
-    child_process: 'empty'
+    dgram: "empty",
+    fs: "empty",
+    net: "empty",
+    tls: "empty",
+    child_process: "empty"
   }
-}
+};

+ 57 - 15
src/App.vue

@@ -1,23 +1,65 @@
 <template>
-  <div id="app">
-    <img src="./assets/logo.png">
-    <router-view/>
-  </div>
-</template>
+  <a-layout id="components-layout-demo-custom-trigger">
+    <a-affix :offset-top="0">
+      <h-layout-sider :collapsed="collapsed" />
+    </a-affix>
+
+    <a-layout class="box">
+      <a-affix :offset-top="0">
+        <a-layout-header style="background: #fff; padding: 0">
+          <a-icon
+            class="trigger"
+            :type="collapsed ? 'menu-unfold' : 'menu-fold'"
+            @click="() => (collapsed = !collapsed)"
+          />
+        </a-layout-header>
+      </a-affix>
 
+      <a-layout-content class="content">
+        <router-view />
+      </a-layout-content>
+    </a-layout>
+  </a-layout>
+</template>
 <script>
 export default {
-  name: 'App'
-}
+  data() {
+    return {
+      collapsed: false
+    };
+  }
+};
 </script>
-
 <style>
-#app {
-  font-family: 'Avenir', Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
-  margin-top: 60px;
+#components-layout-demo-custom-trigger .trigger {
+  font-size: 18px;
+  line-height: 64px;
+  padding: 0 24px;
+  cursor: pointer;
+  transition: color 0.3s;
+}
+
+#components-layout-demo-custom-trigger .trigger:hover {
+  color: #1890ff;
+}
+
+#components-layout-demo-custom-trigger .logo {
+  height: 32px;
+  background: rgba(255, 255, 255, 0.2);
+  margin: 16px;
+}
+.ant-layout-sider {
+  height: 100vh;
+}
+.box {
+  /*padding-top: 64px;*/
+  /*max-height: 100vh;*/
+  /*overflow: scroll;*/
+}
+.box .content {
+  margin: 24px 16px;
+  padding: 24px;
+  background: #fff;
+  min-height: 980px;
 }
 </style>

+ 115 - 0
src/components/layout/h-layout-sider.vue

@@ -0,0 +1,115 @@
+<template>
+  <a-layout-sider v-model="collapsed" :trigger="null" collapsible>
+    <div
+      class="logo"
+      style="cursor: pointer;"
+      @click="$router.push({ path: '/' })"
+    />
+    <!-- <a-menu theme="dark" mode="inline" :default-selected-keys="['1']">
+      <a-menu-item key="1">
+        <a-icon type="user" />
+        <span>nav 1</span>
+      </a-menu-item>
+      <a-menu-item key="2">
+        <a-icon type="video-camera" />
+        <span>nav 2</span>
+      </a-menu-item>
+      <a-menu-item key="3">
+        <a-icon type="upload" />
+        <span>nav 3</span>
+      </a-menu-item>
+    </a-menu> -->
+    <a-menu
+      :default-selected-keys="['1']"
+      :default-open-keys="['2']"
+      mode="inline"
+      theme="dark"
+      @click="titleClick"
+    >
+      <template v-for="item in list">
+        <a-menu-item v-if="!item.children" :key="item.key">
+          <a-icon type="carry-out" />
+          <span>{{ item.title }}</span>
+        </a-menu-item>
+        <sub-menu v-else :key="item.key" :menu-info="item" />
+      </template>
+    </a-menu>
+  </a-layout-sider>
+</template>
+<script type="text/javascript">
+import { Menu } from "ant-design-vue";
+const SubMenu = {
+  template: `
+      <a-sub-menu :key="menuInfo.key" v-bind="$props" v-on="$listeners">
+        <span slot="title"><span>{{ menuInfo.title }}</span>
+        </span>
+        <template v-for="item in menuInfo.children">
+          <a-menu-item v-if="!item.children" :key="item.key">
+            <span><a-icon type="carry-out" />{{ item.title }}</span>
+          </a-menu-item>
+          <sub-menu v-else :key="item.key" :menu-info="item" />
+        </template>
+      </a-sub-menu>
+    `,
+  name: "SubMenu",
+  // must add isSubMenu: true
+  isSubMenu: true,
+  props: {
+    ...Menu.SubMenu.props,
+    // Cannot overlap with properties within Menu.SubMenu.props
+    menuInfo: {
+      type: Object,
+      default: () => ({})
+    }
+  }
+};
+export default {
+  name: "h-layout-sider",
+  props: ["collapsed"],
+  data() {
+    return {
+      menu: [],
+      list: [
+        {
+          key: "1",
+          title: "第一章"
+        },
+        {
+          key: "2",
+          title: "第二章",
+          children: [
+            {
+              key: "2.1",
+              title: "2.1"
+            }
+          ]
+        },
+        {
+          key: "3",
+          title: "第三章",
+          children: [
+            {
+              key: "3.1",
+              title: "3.1",
+              children: [{ key: "3.1.1", title: "3.1.1" }]
+            }
+          ]
+        }
+      ]
+    };
+  },
+  components: {
+    "sub-menu": SubMenu
+  },
+  methods: {
+    toggleCollapsed() {
+      this.collapsed = !this.collapsed;
+    },
+    titleClick(e) {
+      console.log("titleClick", e);
+      console.log(`/chapter${e.key}`);
+      this.$router.push({ path: `/chapter${e.key}` });
+    }
+  }
+};
+</script>

+ 5 - 0
src/pages/chapter1/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div>
+    第一章
+  </div>
+</template>

+ 5 - 0
src/pages/chapter2/2.1.vue

@@ -0,0 +1,5 @@
+<template>
+  <div>
+    2.1
+  </div>
+</template>

+ 5 - 0
src/pages/chapter2/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div>
+    第二章
+  </div>
+</template>

+ 5 - 0
src/pages/chapter3/3.1.1.vue

@@ -0,0 +1,5 @@
+<template>
+  <div>
+    第三章 3.1.1
+  </div>
+</template>

+ 5 - 0
src/pages/chapter3/3.1.vue

@@ -0,0 +1,5 @@
+<template>
+  <div>
+    第三章 3.1
+  </div>
+</template>

+ 5 - 0
src/pages/chapter3/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div>
+    第三章
+  </div>
+</template>

+ 37 - 7
src/router/index.js

@@ -1,15 +1,45 @@
-import Vue from 'vue'
-import Router from 'vue-router'
-import HelloWorld from '@/components/HelloWorld'
+import Vue from "vue";
+import Router from "vue-router";
+import HelloWorld from "@/components/HelloWorld";
 
-Vue.use(Router)
+Vue.use(Router);
 
 export default new Router({
   routes: [
     {
-      path: '/',
-      name: 'HelloWorld',
+      path: "/",
+      name: "HelloWorld",
       component: HelloWorld
+    },
+    {
+      path: "/chapter1",
+      name: "chapter1",
+      component: () => import("@/pages/chapter1/index")
+    },
+    {
+      path: "/chapter2",
+      name: "chapter2",
+      component: () => import("@/pages/chapter2/index")
+    },
+    {
+      path: "/chapter2.1",
+      name: "chapter2.1",
+      component: () => import("@/pages/chapter2/2.1")
+    },
+    {
+      path: "/chapter3",
+      name: "chapter3",
+      component: () => import("@/pages/chapter3/index")
+    },
+    {
+      path: "/chapter3.1",
+      name: "chapter3.1",
+      component: () => import("@/pages/chapter3/3.1")
+    },
+    {
+      path: "/chapter3.1.1",
+      name: "chapter3.1.1",
+      component: () => import("@/pages/chapter3/3.1.1")
     }
   ]
-})
+});