闲聊:
今天是六一儿童节哟,小颖祝大家节日快乐哈哈哈。其实这个demo小颖断断续续做了将近两个礼拜了,心塞的,其实这个也没有多难,主要是小颖有点最近事情有点多,所以就把这个一直拖着,今天好不容易做好了嘻嘻。我们一起来看看效果图吧:
相关技术:
1.vue2.0
2.webpack
3.element
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="width:100%;"> <el-button type="primary" style="width: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="width: 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>
借鉴:
使用vuejs2.0和element-ui 搭建的一个后台管理界面
如果这篇文章对你有用请给小颖一点鼓励吧嘻嘻,动动手扫扫下方二维码小颖打赏一丢丢呗,欢迎帅锅美女打赏哦!
bug一个大大的bug
由于小颖的疏忽,小颖,少写了一个方法,所以会出现
这样的问题。原因是由于小颖在home.vue中少写了一个 “showMenu” 方法,嘻嘻,谢谢这位园友,小颖已经把博客更新啦,嘻嘻,小颖也是初学者所以希望大家多多提问题和建议哦。