Vue 2.0 + Vue Router + Vuex 后台管理系统的骨架

https://github.com/helloyoucan/ba

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

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

项目结构如图所示:

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

package.json:

 
  1. {
  2. "name": "element-starter",
  3. "description": "A Vue.js project",
  4. "author": "caihg",
  5. "private": false,
  6. "scripts": {
  7. "dev": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --open",
  8. "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  9. },
  10. "dependencies": {
  11. "element-ui": "^1.0.0",
  12. "vue": "^2.1.0",
  13. "vue-router": "^2.1.1",
  14. "vue-server-renderer": "^2.1.3",
  15. "vuex": "^2.0.0",
  16. "vuex-router-sync": "^3.0.0"
  17. },
  18. "devDependencies": {
  19. "babel-core": "^6.0.0",
  20. "babel-loader": "^6.0.0",
  21. "babel-preset-es2015": "^6.13.2",
  22. "cross-env": "^1.0.6",
  23. "css-loader": "^0.23.1",
  24. "file-loader": "^0.8.5",
  25. "style-loader": "^0.13.1",
  26. "vue-loader": "^10.0.0",
  27. "vue-template-compiler": "^2.1.0",
  28. "webpack": "^2.1.0-beta.25",
  29. "webpack-dev-server": "^2.1.0-beta.0",
  30. "webpack-dev-middleware": "^1.6.1"
  31. }
  32. }

webpack.config.js:

 
  1. var path = require('path')
  2. var webpack = require('webpack')
  3.  
  4. module.exports = {
  5. entry: './src/main.js',
  6. output: {
  7. path: path.resolve(__dirname, './dist'),
  8. publicPath: '/dist/',
  9. filename: 'build.js'
  10. },
  11. module: {
  12. loaders: [
  13. {
  14. test: /\.vue$/,
  15. loader: 'vue-loader'
  16. },
  17. {
  18. test: /\.js$/,
  19. loader: 'babel-loader',
  20. exclude: /node_modules/
  21. },
  22. {
  23. test: /\.css$/,
  24. loader: 'style-loader!css-loader'
  25. },
  26. {
  27. test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
  28. loader: 'file-loader'
  29. },
  30. {
  31. test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/,
  32. loader: 'file-loader',
  33. query: {
  34. name: '[name].[ext]?[hash]'
  35. }
  36. }
  37. ]
  38. },
  39. devServer: {
  40. historyApiFallback: true,
  41. noInfo: true
  42. },
  43. devtool: '#eval-source-map'
  44. }
  45.  
  46. if (process.env.NODE_ENV === 'production') {
  47. module.exports.devtool = '#source-map'
  48. module.exports.plugins = (module.exports.plugins || []).concat([
  49. new webpack.DefinePlugin({
  50. 'process.env': {
  51. NODE_ENV: '"production"'
  52. }
  53. }),
  54. new webpack.optimize.UglifyJsPlugin({
  55. compress: {
  56. warnings: false
  57. }
  58. })
  59. ])
  60. }

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

 
  1. import Vue from 'vue'
  2. import VueRouter from 'vue-router'
  3. import ElementUI from 'element-ui'
  4. import 'element-ui/lib/theme-default/index.css'
  5.  
  6. Vue.use(VueRouter)
  7. Vue.use(ElementUI)
  8.  
  9. import routes from './routes'
  10. const router = new VueRouter({
  11. mode: 'history',
  12. base: __dirname,
  13. routes: routes
  14. })
  15.  
  16. import Main from './components/main.vue'
  17. new Vue({
  18. el: '#app',
  19. router,
  20. render: h => h(Main)
  21. })

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

routes.js 内容如下:

 
  1. import Login from './components/login/login.vue'
  2. import Container from './components/container/container.vue'
  3. import UserHome from './components/container/userHome.vue'
  4. import Platform from './components/asideContainer/platform.vue'
  5. import UserList from './components/platform/userList.vue'
  6. import UserCreate from './components/platform/userCreate.vue'
  7. import Product from './components/asideContainer/product.vue'
  8. import ProductList from './components/product/list.vue'
  9. import ProductBrand from './components/product/brand.vue'
  10. import NotFound from './components/error/notFound.vue'
  11.  
  12. export default [
  13. {
  14. path: '/login',
  15. component: Login
  16. },
  17. {
  18. path: '/',
  19. redirect: '/login'
  20. },
  21. {
  22. path: '/page',
  23. component: Container,
  24. children: [
  25. {
  26. path: 'userHome',
  27. component: UserHome
  28. },
  29. {
  30. path: 'platform',
  31. redirect: 'platform/userList', // 默认指向用户列表(UserList)
  32. component: Platform,
  33. children: [
  34. {
  35. path: 'userList',
  36. component: UserList
  37. },
  38. {
  39. path: 'userCreate',
  40. component: UserCreate
  41. }
  42. ]
  43. },
  44. {
  45. path: 'product',
  46. redirect: 'product/list', // 默认指向商品列表(ProductList)
  47. component: Product,
  48. children: [
  49. {
  50. path: 'list',
  51. component: ProductList
  52. },
  53. {
  54. path: 'brand',
  55. component: ProductBrand
  56. }
  57. ]
  58. }
  59. ]
  60. },
  61. { // 404页面:必须位于最后,否则其它的路由地址都会使用 NotFound 组件
  62. path: '*',
  63. component: NotFound
  64. }
  65. ]

main.vue 的内容如下:

 
  1. <template>
  2. <router-view></router-view>
  3. </template>

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

 
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3.  
  4. Vue.use(Vuex)
  5.  
  6. export default new Vuex.Store({
  7. state: {
  8. username: ''
  9. }
  10. })

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

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

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

 
  1. <template>
  2. <div class="box">
  3. <el-form :model="loginForm" :rules="loginRules" ref="loginForm" label-width="100px" class="form-box">
  4. <el-form-item label="用户名" prop="username">
  5. <el-input v-model="loginForm.username" placeholder="请输入用户名" auto-complete="off"></el-input>
  6. </el-form-item>
  7. <el-form-item label="密码" prop="password">
  8. <el-input type="password" v-model="loginForm.password" auto-complete="off"></el-input>
  9. </el-form-item>
  10. <el-form-item>
  11. <el-button type="primary" @click="onLogin">登录</el-button>
  12. <el-button @click="handleReset">重置</el-button>
  13. </el-form-item>
  14. </el-form>
  15. </div>
  16. </template>
  17.  
  18. <script>
  19. import store from '../../store/store'
  20. export default {
  21. data() {
  22. var validateUsername = (rule, value, callback) => {
  23. if (value === '') {
  24. callback(new Error('请输入用户名'));
  25. } else {
  26. callback();
  27. }
  28. };
  29. var validatePassword = (rule, value, callback) => {
  30. if (value === '') {
  31. callback(new Error('请输入密码'));
  32. } else {
  33. callback();
  34. }
  35. };
  36.  
  37. return {
  38. loginForm: {
  39. username: '',
  40. password: ''
  41. },
  42. loginRules: {
  43. username: [
  44. { validator: validateUsername, trigger: 'blur' }
  45. ],
  46. password: [
  47. { validator: validatePassword, trigger: 'blur' }
  48. ]
  49. }
  50. };
  51. },
  52. methods: {
  53. onLogin(event) {
  54. this.$refs.loginForm.validate((valid) => {
  55. if (valid) {
  56. store.state.username = this.loginForm.username;
  57. this.$router.push('page/userHome');
  58. } else {
  59. console.log('error submit!!');
  60. return false;
  61. }
  62. });
  63. },
  64. handleReset() {
  65. this.$refs.loginForm.resetFields();
  66. }
  67. }
  68. }
  69. </script>
  70.  
  71. <style>
  72. .form-box {
  73. width: 500px;
  74. margin-top: 100px;
  75. margin-right: auto;
  76. margin-left: auto;
  77. }
  78. </style>

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

store.state.username = this.loginForm.username

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

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

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

container.vue 的内容如下:

 
  1. <template>
  2. <div class="container">
  3. <header-nav></header-nav>
  4. <router-view></router-view>
  5. </div>
  6. </template>
  7.  
  8. <script>
  9. import headerNav from './headerNav.vue'
  10. export default {
  11. components: {
  12. headerNav
  13. }
  14. }
  15. </script>
  16.  
  17. <style>
  18. header > h1 {
  19. display: inline-block;
  20. }
  21. header > a {
  22. margin: 0 10px;
  23. color: #000;
  24. text-decoration: none;
  25. }
  26. </style>

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

 
  1. <template>
  2. <header>
  3. <h1>管理平台</h1>
  4. <router-link to="/page/userHome">主页</router-link>
  5. <router-link to="/page/platform">平台管理</router-link>
  6. <router-link to="/page/product">商品管理</router-link>
  7. <strong>欢迎你,{{ getUsername }}</strong>
  8. </header>
  9. </template>
  10.  
  11. <script>
  12. import store from '../../store/store'
  13. export default {
  14. computed: {
  15. getUsername () {
  16. return store.state.username
  17. }
  18. }
  19. }
  20. </script>
  21.  
  22. <style>
  23. header > .router-link-active {
  24. color: red;
  25. }
  26. header > strong {
  27. padding-left: 50px;
  28. }
  29. </style>

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

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

左侧的导航放在 asideContainer 目录

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

 
  1. <template>
  2. <!-- 平台管理 -->
  3. <div>
  4. <ul class="aside-nav">
  5. <li><router-link to="/page/platform/userList">用户列表</router-link></li>
  6. <li><router-link to="/page/platform/userCreate">用户创建</router-link></li>
  7. </ul>
  8. <router-view class="aside-container"></router-view>
  9. </div>
  10. </template>
  11.  
  12. <style>
  13. .aside-nav {
  14. float: left;
  15. width: 100px;
  16. margin: 0 50px 0 0;
  17. padding-left: 0;
  18. }
  19. .aside-nav a {
  20. display: block;
  21. padding: 4px 0 5px;
  22. color: #555;
  23. text-align: center;
  24. text-decoration: none;
  25. }
  26. .aside-nav .router-link-active {
  27. color: #fff;
  28. background-color: orange;
  29. }
  30. .aside-container {
  31. float: left;
  32. }
  33. </style>
 
  1. <template>
  2. <!-- 商品管理 -->
  3. <div>
  4. <ul class="aside-nav">
  5. <li><router-link to="/page/product/list">商品列表</router-link></li>
  6. <li><router-link to="/page/product/brand">商品品牌</router-link></li>
  7. </ul>
  8. <router-view class="aside-container"></router-view>
  9. </div>
  10. </template>

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

userList.vue 中的内容如下:

 
  1. <template>
  2. <div>
  3. 用户列表的内容
  4. </div>
  5. </template>

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

项目代码在 github 上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值