zoukankan      html  css  js  c++  java
  • Vue 2.0 + Vue Router + Vuex

    用 Vue.js 2.x 与相配套的 Vue Router、Vuex 搭建了一个最基本的后台管理系统的骨架。

    当然先要安装 node.js(包括了 npm)、vue-cli

    项目结构如图所示:

    assets 中是静态资源,components 中是组件(以 .vue 为后缀名的文件),store 中是使用了 vuex 的 js 文件。

    package.json:

    {
      "name": "element-starter",
      "description": "A Vue.js project",
      "author": "caihg",
      "private": false,
      "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --open",
        "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
      },
      "dependencies": {
        "element-ui": "^1.0.0",
        "vue": "^2.1.0",
        "vue-router": "^2.1.1",
        "vue-server-renderer": "^2.1.3",
        "vuex": "^2.0.0",
        "vuex-router-sync": "^3.0.0"
      },
      "devDependencies": {
        "babel-core": "^6.0.0",
        "babel-loader": "^6.0.0",
        "babel-preset-es2015": "^6.13.2",
        "cross-env": "^1.0.6",
        "css-loader": "^0.23.1",
        "file-loader": "^0.8.5",
        "style-loader": "^0.13.1",
        "vue-loader": "^10.0.0",
        "vue-template-compiler": "^2.1.0",
        "webpack": "^2.1.0-beta.25",
        "webpack-dev-server": "^2.1.0-beta.0",
        "webpack-dev-middleware": "^1.6.1"
      }
    }
    

    webpack.config.js:

    var path = require('path')
    var webpack = require('webpack')
    
    module.exports = {
      entry: './src/main.js',
      output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'build.js'
      },
      module: {
        loaders: [
          {
            test: /.vue$/,
            loader: 'vue-loader'
          },
          {
            test: /.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/
          },
          {
            test: /.css$/,
            loader: 'style-loader!css-loader'
          },
          {
            test: /.(eot|svg|ttf|woff|woff2)(?S*)?$/,
            loader: 'file-loader'
          },
          {
            test: /.(png|jpe?g|gif|svg)(?S*)?$/,
            loader: 'file-loader',
            query: {
              name: '[name].[ext]?[hash]'
            }
          }
        ]
      },
      devServer: {
        historyApiFallback: true,
        noInfo: true
      },
      devtool: '#eval-source-map'
    }
    
    if (process.env.NODE_ENV === 'production') {
      module.exports.devtool = '#source-map'
      module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: '"production"'
          }
        }),
        new webpack.optimize.UglifyJsPlugin({
          compress: {
            warnings: false
          }
        })
      ])
    }
    

    项目的入口 js 文件 main.js:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import ElementUI from 'element-ui'
    import 'element-ui/lib/theme-default/index.css'
    
    Vue.use(VueRouter)
    Vue.use(ElementUI)
    
    import routes from './routes'
    const router = new VueRouter({
      mode: 'history',
      base: __dirname,
      routes: routes
    })
    
    import Main from './components/main.vue'
    new Vue({
      el: '#app',
      router,
      render: h => h(Main)
    })
    

    该文件引用了路由配置文件 routes.js 和主入口的组件 main.vue,其中 main.vue 在 components 目录

    routes.js 内容如下:

    import Login from './components/login/login.vue'
    import Container from './components/container/container.vue'
    import UserHome from './components/container/userHome.vue'
    import Platform from './components/asideContainer/platform.vue'
    import UserList from './components/platform/userList.vue'
    import UserCreate from './components/platform/userCreate.vue'
    import Product from './components/asideContainer/product.vue'
    import ProductList from './components/product/list.vue'
    import ProductBrand from './components/product/brand.vue'
    import NotFound from './components/error/notFound.vue'
    
    export default [
      {
        path: '/login',
        component: Login
      },
      {
        path: '/',
        redirect: '/login'
      },
      {
        path: '/page',
        component: Container,
        children: [
          {
            path: 'userHome',
            component: UserHome
          },
          {
            path: 'platform',
            redirect: 'platform/userList', // 默认指向用户列表(UserList)
            component: Platform,
            children: [
              {
                path: 'userList',
                component: UserList
              },
              {
                path: 'userCreate',
                component: UserCreate
              }
            ]
          },
          {
            path: 'product',
            redirect: 'product/list', // 默认指向商品列表(ProductList)
            component: Product,
            children: [
              {
                path: 'list',
                component: ProductList
              },
              {
                path: 'brand',
                component: ProductBrand
              }
            ]
          }
        ]
      },
      { // 404页面:必须位于最后,否则其它的路由地址都会使用 NotFound 组件
        path: '*',
        component: NotFound
      }
    ]

    main.vue 的内容如下:

    <template>
      <router-view></router-view>
    </template>

     store.js 在 store 目录,内容如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        username: ''
      }
    })
    

    后台都是登录成功后跳转到主页面

    界面的 UI 用的是开源的 element-ui

    login.vue 位于 login 目录,内容如下:

    <template>
      <div class="box">
        <el-form :model="loginForm" :rules="loginRules" ref="loginForm" label-width="100px" class="form-box">
          <el-form-item label="用户名" prop="username">
            <el-input v-model="loginForm.username" placeholder="请输入用户名" auto-complete="off"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input type="password" v-model="loginForm.password" auto-complete="off"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="onLogin">登录</el-button>
            <el-button @click="handleReset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>
    
    <script>
    import store from '../../store/store'
    export default {
      data() {
        var validateUsername = (rule, value, callback) => {
          if (value === '') {
            callback(new Error('请输入用户名'));
          } else {
            callback();
          }
        };
        var validatePassword = (rule, value, callback) => {
          if (value === '') {
            callback(new Error('请输入密码'));
          } else {
            callback();
          }
        };
    
        return {
          loginForm: {
            username: '',
            password: ''
          },
          loginRules: {
            username: [
              { validator: validateUsername, trigger: 'blur' }
            ],
            password: [
              { validator: validatePassword, trigger: 'blur' }
            ]
          }
        };
      },
      methods: {
        onLogin(event) {
          this.$refs.loginForm.validate((valid) => {
            if (valid) {
              store.state.username = this.loginForm.username;
              this.$router.push('page/userHome');
            } else {
              console.log('error submit!!');
              return false;
            }
          });
        },
        handleReset() {
          this.$refs.loginForm.resetFields();
        }
      }
    }
    </script>
    
    <style>
    .form-box {
       500px;
      margin-top: 100px;
      margin-right: auto;
      margin-left: auto;
    }
    </style>
    

    在登录事件中,将用户名传递给 store 中的 state.username,以便在其它组件中获取: 

    store.state.username = this.loginForm.username

    登录后的界面,默认跳转到主页:

     

    通过 vuex 获取到了登录的用户名称(caihg);当然,如果刷新当前页面,用户名称就没了。 

    头部在 container 目录,其中有三个组件

    container.vue 的内容如下:

    <template>
      <div class="container">
        <header-nav></header-nav>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import headerNav from './headerNav.vue'
    export default {
      components: {
        headerNav
      }
    }
    </script>
    
    <style>
    header > h1 {
      display: inline-block;
    }
    header > a {
      margin: 0 10px;
      color: #000;
      text-decoration: none;
    }
    </style>
    

    headerNav.vue 中就是头部导航的各种链接:

    <template>
      <header>
        <h1>管理平台</h1>
        <router-link to="/page/userHome">主页</router-link>
        <router-link to="/page/platform">平台管理</router-link>
        <router-link to="/page/product">商品管理</router-link>
        <strong>欢迎你,{{ getUsername }}</strong>
      </header>
    </template>
    
    <script>
    import store from '../../store/store'
    export default {
      computed: {
        getUsername () {
          return store.state.username
        }
      }
    }
    </script>
    
    <style>
    header > .router-link-active {
      color: red;
    }
    header > strong {
      padding-left: 50px;
    }
    </style>
    

    点击头部的导航,下面的内容相应地切换

     其中左侧部分也是导航,点击也要跟随切换

    左侧的导航放在 asideContainer 目录

     platform.vue 与 product.vue 内容相似;只是前者包括了样式,后者没有(相同的样式写一份就够了,如果多写了,也会重复渲染)

    <template>
      <!-- 平台管理 -->
      <div>
        <ul class="aside-nav">
          <li><router-link to="/page/platform/userList">用户列表</router-link></li>
          <li><router-link to="/page/platform/userCreate">用户创建</router-link></li>
        </ul>
        <router-view class="aside-container"></router-view>
      </div>
    </template>
    
    <style>
    .aside-nav {
      float: left;
       100px;
      margin: 0 50px 0 0;
      padding-left: 0;
    }
    .aside-nav a {
      display: block;
      padding: 4px 0 5px;
      color: #555;
      text-align: center;
      text-decoration: none;
    }
    .aside-nav .router-link-active {
      color: #fff;
      background-color: orange;
    }
    .aside-container {
      float: left;
    }
    </style>
    
    <template>
      <!-- 商品管理 -->
      <div>
        <ul class="aside-nav">
          <li><router-link to="/page/product/list">商品列表</router-link></li>
          <li><router-link to="/page/product/brand">商品品牌</router-link></li>
        </ul>
        <router-view class="aside-container"></router-view>
      </div>
    </template>
    

    左侧导航对应的内容分别在不同的目录(根据功能划分)

    userList.vue 中的内容如下:

    <template>
      <div>
        用户列表的内容
      </div>
    </template>

    至此完成,后台管理系统的大致骨架就是这样了。

    项目代码在 github 上

  • 相关阅读:
    mysql 1449 : The user specified as a definer ('root'@'%') does not exist 解决方法
    java中使用正则表达式
    Timer与ScheduledThreadPoolExecutor的比较
    Java同步块
    java中的浅拷贝与深拷贝
    java的关闭钩子(Shutdown Hook)
    JVM系列三:JVM参数设置、分析
    java虚拟机参数设置
    UTF-8编码规则(转)
    过滤3个字节以上的utf-8字符
  • 原文地址:https://www.cnblogs.com/caihg/p/6150158.html
Copyright © 2011-2022 走看看