• vue2.0+element+node+webpack搭建的一个简单的后台管理界面


    闲聊:

          今天是六一儿童节哟,小颖祝大家节日快乐哈哈哈。其实这个demo小颖断断续续做了将近两个礼拜了,心塞的,其实这个也没有多难,主要是小颖有点最近事情有点多,所以就把这个一直拖着,今天好不容易做好了嘻嘻。我们一起来看看效果图吧:

                                 

    相关技术:

                1.vue2.0

                2.webpack

                3.element

                4.vue-router

    vue2.0环境搭建:

         1.检查本地是否安装node:node -v  

                         

           如果没有安装从node官网上下载相应的node,安装成功即可。

          2.检查本地npm版本:npm -v,如果版本太低可以通过:npm install -g npm进行升级

                        

          3.全局安装webpack:npm install webpack -g

          4.安装vue脚手架:npm install vue-cli -g

          5.新建空文件夹,根据模板创建项目:

                 vue init webpack-simple 工程名字<工程名字不能用中文>

                 或者创建 vue1.0 的项目: vue init webpack-simple#1.0 工程名字<工程名字不能用中文>

                 会有一些初始化的设置,如下输入:

           Target directory exists. Continue? (Y/n)直接回车默认(然后会下载 vue2.0模板,这里可能需要连代理)

           Project name (vue-test)直接回车默认

           Project description (A Vue.js project) 直接回车默认

           Author 写你自己的名字

           Use sass 小颖的这个demo要用sass所以,小颖选的yes,大家可以根据自己的需求选择yes or no

    在你的项目根目录下,运行:npm run dev之后,会自动打开你的默认浏览器:http://localhost:8080/    效果如下:

             

    项目目录:

    ------------------mydemo

    --------------------------src

    ----------------------------------page

    --------------------------------------------------menu1

    ---------------------------------------------------------------------menuTab.vue

    --------------------------------------------------menu2

    ---------------------------------------------------------------------menuTable.vue

    --------------------------------------------------404.vue

    --------------------------------------------------home.vue

    --------------------------------------------------login.vue

    ----------------------------------App.vue

    ----------------------------------main.js

    ----------------------------------router.js

    --------------------------favicon.ico

    --------------------------index.html

    --------------------------package.json

    --------------------------webpack.config.js

    然后我们将自己想要的页面什么的慢慢加进去:

    1.在根目录下添加favicon.ico图标,小颖是直接把:mydemo/src/assets下的logo.png改成favicon.ico。

    2.在webpack.config.js中添加以下代码:

                                    

                                   

    然后我们再执行一次:npm run dev

    然后就报错啦报错啦:

    解决方法:

         执行npm install html-webpack-plugin -save-v

    3.在index.html中引入favicon.ico图标:

    <link rel="shortcut icon"  href="favicon.ico"/>

    4.新增所需vue文件和js文件:

    5.引入所需的npm:element-ui、vue-router、font-awesome、style-loader。

    最后呢我们一起来看看具体哪些重要的vue文件和js文件代码是什么样子的。

    代码来啦:

    webpack.config.js

    var path = require('path')
    var webpack = require('webpack')
    var HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        entry: './src/main.js',
        output: {
            path: path.resolve(__dirname, './dist'),
            publicPath: '/dist/',
            filename: 'build.js'
        },
        module: {
            rules: [{
                    test: /.vue$/,
                    loader: 'vue-loader',
                    options: {
                        loaders: {
                            // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
                            // the "scss" and "sass" values for the lang attribute to the right configs here.
                            // other preprocessors should work out of the box, no loader config like this necessary.
                            'scss': 'vue-style-loader!css-loader!sass-loader',
                            'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
                        }
                        // other vue-loader options go here    小颖在这里http://www.cnblogs.com/yingzi1028/p/6925387.html
    } }, { 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|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' } } ] }, plugins: [ new HtmlWebpackPlugin({ template: 'index.html', favicon: 'favicon.ico', // 在此处添加一行这个,用于webpack生成index.html时,自动把favicon.ico加入HTML中 inject: true // 小颖在这里http://www.cnblogs.com/yingzi1028/p/6925387.html
    }) ], resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' } }, devServer: { historyApiFallback: true, noInfo: true }, performance: { hints: false }, devtool: '#eval-source-map' } if (process.env.NODE_ENV === 'production') { module.exports.devtool = '#source-map' // http://vue-loader.vuejs.org/en/workflow/production.html module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"' } }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } }), new webpack.LoaderOptionsPlugin({ minimize: true }) ]) }

    package.json

    {
      "name": "mydemo",
      "description": "A Vue.js project",
      "version": "1.0.0",
      "author": "xiaoying",
      "private": true,
      "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
        "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
      },
      "dependencies": {
        "element-ui": "^1.3.4",
        "font-awesome": "^4.7.0",
        "vue": "^2.3.3",
        "vue-router": "^2.5.3"
      },
      "devDependencies": {
        "babel-core": "^6.0.0",
        "babel-loader": "^6.0.0",
        "babel-preset-env": "^1.5.1",
        "cross-env": "^3.0.0",
        "css-loader": "^0.25.0",
        "file-loader": "^0.9.0",
        "html-webpack-plugin": "^2.28.0",
        "node-sass": "^4.5.0",
        "sass-loader": "^5.0.1",
        "style-loader": "^0.18.1",
        "vue-loader": "^12.1.0",
        "vue-template-compiler": "^2.3.3",
        "webpack": "^2.6.1",
        "webpack-dev-server": "^2.4.5"
      }
    }

    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>mydemo</title>
        <link rel="shortcut icon"  href="favicon.ico"/>
      </head>
      <body>
        <div id="app"></div>
        <script src="/dist/build.js"></script>
      </body>
    </html>

    router.js

    import Vue from "vue"
    import VueRouter from "vue-router"
    
    // 引入组件
    
    import login from './page/login.vue'
    import home from './page/home.vue'
    import notFound from './page/404.vue'
    import menutab from './page/menu1/menuTab.vue'
    import menutable from './page/menu2/menuTable.vue'
    // 要告诉 vue 使用 vueRouter
    Vue.use(VueRouter);
    
    let routes = [{
            path: '/login',
            component: login,
            name: '',
            hidden: true
        },
        {
            path: '/404',
            component: notFound,
            name: '',
            hidden: true
        },
        {
            path: '/',
            component: home,
            name: '导航一',
            iconCls: 'el-icon-message', //图标样式class
            children: [{
                path: '/menutab',
                component: menutab,
                name: 'Tab'
            }]
        },
        {
            path: '/',
            component: home,
            name: '导航二',
            iconCls: 'fa fa-id-card-o',
            children: [{
                    path: '/menutable',
                    component: menutable,
                    name: 'Table'
                }
            ]
        }
    ];
    var router = new VueRouter({
        routes
    })
    export default router;

    main.js

    import Vue from 'vue';
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-default/index.css';
    import Router from 'vue-router';
    import App from './App.vue';
    import 'font-awesome/css/font-awesome.min.css'
    
    
    Vue.use(ElementUI);
    Vue.use(Router);
    
    router.beforeEach((to, from, next) => {
        if (to.path == '/login') {
            sessionStorage.removeItem('user');
        }
        let user = JSON.parse(sessionStorage.getItem('user'));
        if (!user && to.path != '/login') {
            next({
                path: '/login'
            });
        } else {
            next();
        }
    });
    
    // 引入路由
    import router from "./router.js"
    new Vue({
        el: '#app',
        router, // 注入到根实例中
        render: h => h(App)
    });

    App.vue

    <template>
    <div id="app">
        <router-view></router-view>
    </div>
    </template>
    
    <script>
    export default {}
    </script>
    
    <style lang="scss">
    body {
        margin: 0;
        padding: 0;
        font-size: 14px;
        -webkit-font-smoothing: antialiased;
        overflow: scroll;
        overflow-y: hidden;
    }
    
    #app {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
    }
    
    .el-submenu [class^=fa] {
        vertical-align: baseline;
        margin-right: 10px;
    }
    
    .el-menu-item [class^=fa] {
        vertical-align: baseline;
        margin-right: 10px;
    }
    
    .toolbar {
        background: #f2f2f2;
        padding: 10px;
        margin: 10px 0;
        .el-form-item {
            margin-bottom: 10px;
        }
    }
    
    </style>

    login.vue

    <template>
    <div class="login-page-container">
        <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" label-position="left" label-width="0px" class="demo-ruleForm login-container">
            <h3 class="title">系统登录</h3>
            <el-form-item prop="account">
                <el-input type="text" v-model="ruleForm2.account" auto-complete="off" placeholder="账号"></el-input>
            </el-form-item>
            <el-form-item prop="checkPass">
                <el-input type="password" v-model="ruleForm2.checkPass" auto-complete="off" placeholder="密码"></el-input>
            </el-form-item>
            <el-checkbox v-model="checked" checked class="remember">记住密码</el-checkbox>
            <el-form-item style="100%;">
                <el-button type="primary" style="100%;" @click="handleSubmit2" :loading="logining">登录</el-button>
            </el-form-item>
        </el-form>
    </div>
    </template>
    
    <script>
    export default {
        props: {
        },
        data() {
            return {
                logining: false,
                ruleForm2: {
                    account: 'admin',
                    checkPass: '123456'
                },
                rules2: {
                    account: [{
                            required: true,
                            message: '请输入账号',
                            trigger: 'blur'
                        },
                        //{ validator: validaePass }
                    ],
                    checkPass: [{
                            required: true,
                            message: '请输入密码',
                            trigger: 'blur'
                        },
                        //{ validator: validaePass2 }
                    ]
                },
                checked: true
            };
        },
        methods: {
            handleSubmit2(ev) {
                var _this = this;
                _this.$refs.ruleForm2.validate((valid) => {
                    if (valid) {
                        _this.logining = true;
                        var loginParams = {
                            username: this.ruleForm2.account,
                            password: this.ruleForm2.checkPass
                        };
                        if (loginParams.username == "admin" && loginParams.password == "123456") {
                            _this.logining = false;
                            sessionStorage.setItem('user', JSON.stringify(loginParams));
                            _this.$router.push({ path: '/menutab' });
                        } else {
                            _this.logining = false;
                            _this.$alert('用户名或密码错误!', '提示信息', {
                                confirmButtonText: '确定'
                            });
                        }
                    } else {
                        console.log('error submit!!');
                        return false;
                    }
                });
            }
        }
    }
    </script>
    
    <style scoped>
    .login-container {
        -webkit-border-radius: 5px;
        border-radius: 5px;
        -moz-border-radius: 5px;
        background-clip: padding-box;
        margin: 180px auto;
        width: 350px;
        padding: 35px 35px 15px;
        background: #fff;
        border: 1px solid #eaeaea;
        box-shadow: 0 0 25px #cac6c6;
    }
    
    label.el-checkbox.remember {
        margin: 0px 0px 35px 0px;
    }
    </style>

    home.vue

    <template lang="html">
    <div class="home-container">
      <el-row class="container">
        <el-col :span="24" class="header">
                <el-col :span="10" class="logo" :class="collapsed?'logo-collapse-width':'logo-width'">{{collapsed?'':sysName}}</el-col>
                <el-col :span="10">
            <div class="tools" @click.prevent="collapseFun">
              <i class="fa fa-align-justify"></i>
                    </div>
                </el-col>
                <el-col :span="4" class="userinfo">
                    <el-dropdown trigger="hover">
                        <span class="el-dropdown-link userinfo-inner">{{sysUserName}}</span>
                        <el-dropdown-menu slot="dropdown">
                            <el-dropdown-item>我的消息</el-dropdown-item>
                            <el-dropdown-item>设置</el-dropdown-item>
                            <el-dropdown-item divided @click.native="logoutFun">退出登录</el-dropdown-item>
                        </el-dropdown-menu>
                    </el-dropdown>
                </el-col>
            </el-col>
        <el-col :span="24" class="main">
          <aside :class="collapsed?'menu-collapsed':'menu-expanded'">
            <!--导航菜单-->
           <el-menu :default-active="$route.path" class="el-menu-vertical-demo" unique-opened router v-show="!collapsed">
             <template v-for="(item,index) in $router.options.routes" v-if="!item.hidden">
               <el-submenu :index="index+''" v-if="!item.leaf">
                 <template slot="title"><i :class="item.iconCls"></i>{{item.name}}</template>
                 <el-menu-item v-for="child in item.children" :index="child.path" :key="child.path" v-if="!child.hidden">{{child.name}}</el-menu-item>
               </el-submenu>
               <el-menu-item v-if="item.leaf&&item.children.length>0" :index="item.children[0].path"><i :class="item.iconCls"></i>{{item.children[0].name}}</el-menu-item>
             </template>
           </el-menu>
           <!--导航菜单-折叠后-->
           <ul class="el-menu el-menu-vertical-demo collapsed" v-show="collapsed" ref="menuCollapsed">
             <li v-for="(item,index) in $router.options.routes" v-if="!item.hidden" class="el-submenu item">
               <template v-if="!item.leaf">
                 <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
                   <i :class="item.iconCls"></i>
                 </div>
                 <ul class="el-menu submenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
                   <li v-for="child in item.children" v-if="!child.hidden" :key="child.path" class="el-menu-item" style="padding-left: 40px;height: 56px;line-height: 56px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.path)">{{child.name}}</li>
                 </ul>
               </template>
               <template v-else>
                 <li class="el-submenu">
                   <div class="el-submenu__title el-menu-item" style="padding-left: 20px;height: 56px;line-height: 56px;padding: 0 20px;" :class="$route.path==item.children[0].path?'is-active':''" @click="$router.push(item.children[0].path)"><i :class="item.iconCls"></i></div>
                 </li>
               </template>
             </li>
           </ul>
         </aside>
         <section class="content-container">
           <div class="grid-content bg-purple-light">
             <el-col :span="24" class="breadcrumb-container">
               <strong class="title">{{$route.name}}</strong>
               <el-breadcrumb separator="/" class="breadcrumb-inner">
                 <el-breadcrumb-item v-for="item in $route.matched" :key="item.path">{{ item.name }}</el-breadcrumb-item>
               </el-breadcrumb>
             </el-col>
             <el-col :span="24" class="content-wrapper">
               <transition name="fade" mode="out-in">
                 <router-view></router-view>
               </transition>
             </el-col>
           </div>
         </section>
       </el-col>
     </el-row>
    </div>
    </template>
    
    <script>
    export default {
        components: {},
        data() {
            return {
                sysName: 'VueDemo',
                sysUserName: '',
                collapsed: false
            }
        },
        methods: {
            //折叠导航栏
            collapseFun: function() {
                this.collapsed = !this.collapsed;
            },
            showMenu(i, status){
              this.$refs.menuCollapsed.getElementsByClassName('submenu-hook-' + i)[0].style.display = status ? 'block' : 'none';
            },
            //退出登录
            logoutFun: function() {
                var _this = this;
                this.$confirm('确认退出吗?', '提示', {
                    //type: 'warning'
                }).then(() => {
                    sessionStorage.removeItem('user');
                    _this.$router.push('/login');
                }).catch(() => {
    
                });
    
    
            },
        },
        mounted() {
            var user = sessionStorage.getItem('user');
            if (user) {
                user = JSON.parse(user);
                this.sysUserName = user.username || '';
            }
        }
    }
    </script>
    
    <style scoped lang="scss">
    .container {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
        .header {
            height: 60px;
            line-height: 60px;
            background: #bbdbfb;
            color: #fff;
            .userinfo {
                text-align: right;
                padding-right: 35px;
                float: right;
                .userinfo-inner {
                    cursor: pointer;
                    color: #fff;
                }
            }
            .logo {
                height: 60px;
                font-size: 22px;
                padding-left: 20px;
                padding-right: 20px;
                border-color: rgba(238,241,146,0.3);
                border-right-width: 1px;
                border-right-style: solid;
            }
            .logo-width {
                width: 230px;
            }
            .logo-collapse-width {
                width: 60px;
            }
            .tools {
                padding: 0 23px;
                width: 14px;
                height: 60px;
                line-height: 60px;
                cursor: pointer;
            }
        }
        .main {
            display: flex;
            position: absolute;
            top: 60px;
            bottom: 0;
            overflow: hidden;
            aside {
                flex: 0 0 230px;
                width: 230px;
                .el-menu {
                    height: 100%;
                }
                .collapsed {
                    width: 60px;
                    .item {
                        position: relative;
                    }
                    .submenu {
                        position: absolute;
                        top: 0;
                        left: 60px;
                        z-index: 99999;
                        height: auto;
                        display: none;
                    }
                }
            }
            .menu-collapsed {
                flex: 0 0 60px;
                width: 60px;
            }
            .menu-expanded {
                flex: 0 0 230px;
                width: 230px;
            }
            .content-container {
                flex: 1;
                overflow-y: scroll;
                padding: 20px;
                .breadcrumb-container {
                    .title {
                        width: 200px;
                        float: left;
                        color: #475669;
                    }
                    .breadcrumb-inner {
                        float: right;
                    }
                }
                .content-wrapper {
                    background-color: #fff;
                    box-sizing: border-box;
                }
            }
        }
    }
    </style>

    404.vue

    <template>
        <p class="page-container">404 page not found</p>
    </template>
    
    <style>
        .page-container {
            font-size: 20px;
            text-align: center;
            color: rgb(192, 204, 218);
        }
    </style>

    menuTab.vue

    <template>
    <div class="tab-content">
      <el-tabs v-model="activeName" @tab-click="handleClick">
          <el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane>
          <el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane>
          <el-tab-pane label="角色管理" name="third">角色管理</el-tab-pane>
          <el-tab-pane label="定时任务补偿" name="fourth">定时任务补偿</el-tab-pane>
      </el-tabs>
    </div>
    </template>
    <script>
    export default {
        data() {
            return {
                activeName: 'second'
            };
        },
        methods: {
            handleClick(tab, event) {
                console.log(tab, event);
            }
        }
    };
    </script>
    
    <style lang="css">
    </style>

    menuTable.vue

    <template lang="html">
      <div class="table-content">
        <el-table :data="tableData" style=" 100%">
          <el-table-column prop="date" label="日期" width="180"></el-table-column>
          <el-table-column prop="name" label="姓名" width="180"></el-table-column>
          <el-table-column prop="address" label="地址"></el-table-column>
        </el-table>
      </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                tableData: [{
                    date: '2016-05-02',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1518 弄'
                }, {
                    date: '2016-05-04',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1517 弄'
                }, {
                    date: '2016-05-01',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1519 弄'
                }, {
                    date: '2016-05-03',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1516 弄'
                }]
            }
        }
    }
    </script>
    
    <style lang="css">
    </style>

    借鉴:

    vuejs 和 element 搭建的一个后台管理界面

    使用vuejs2.0和element-ui 搭建的一个后台管理界面

    vue2.0环境搭建

    如果这篇文章对你有用请给小颖一点鼓励吧嘻嘻,动动手扫扫下方二维码小颖打赏一丢丢呗,欢迎帅锅美女打赏哦!

                      

    bug一个大大的bug

    由于小颖的疏忽,小颖,少写了一个方法,所以会出现

                                                       

    这样的问题。原因是由于小颖在home.vue中少写了一个  “showMenu”  方法,嘻嘻,谢谢这位园友,小颖已经把博客更新啦,嘻嘻,小颖也是初学者所以希望大家多多提问题和建议哦。

  • 相关阅读:
    Linq 实例
    VS的无用文件
    我在vs文本编辑中常用的快捷键----常更新
    EF+MVC学习中的不理解的问题
    Lambda表达式
    Linq学习(主要参考linq之路)----2LINQ方法语法
    WPF编译时提示“...不包含适合于入口点的静态‘Main’方法 ...”
    SQL
    SQL Server
    sql 判断表是否存在
  • 原文地址:https://www.cnblogs.com/yingzi1028/p/6925387.html
Copyright © 2020-2023  润新知