前面我们已经实现了前后两端项目的基础搭建以及前后数据交互,目前的UI页面十分的简陋,所以今天咱们来完善前端项目,让UI更加美观。
如果你的html、js、css的基础很好,那么前端项目研发起来相信不会很困难,不管是传统技术JSTL、JQuery与easyUI、bootstrap等UI框架,还是vue、react、angular与elmentui、layui等新技术,前端底层实现都是大同小异的,无非每项技术的特点各有不同。后期可根据团队人员和项目的基本情况来进行配套组合的技术选型。我们继续以Vue.js和elmentui为例研发本项目。
为了后续不断完善前端项目,需要一些VUE组件来帮助我们更好的实现前端功能。
require和import的区别
vue编程中最重要的思想就是模块化,import和require都是被模块化所使用。
遵循规范
require 是 AMD规范引入方式。
import是ES6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法。
调用时间
require是运行时调用,所以require理论上可以运用在代码的任何地方。
import是编译时调用,所以必须放在文件开头。
原来得样例中页面引入咱们使用 import login from '@/views/login'的方式。
后续如果页面过多,开发环境如果使用懒加载, 页面太多的话会造成webpack热更新太慢。所以生产环境使用懒加载,开发环境不使用懒加载。
添加模块化工具类
router目录下添加工具类根据不同环境采用不同的模块化方式
import-development.js
module.exports = file => require('@/views/' + file + '.vue').default
import-production.js
module.exports = file => () => import('@/views/' + file + '.vue')
嵌套路由又称为子路由,在实际应用中,通常由多层嵌套的组件组合而成。同样地,URL中各段动态路景观也按某种结构对应嵌套的各层组件,例如我们看Vue的官网教程。
当我们点击左边的项目的时候,我们知道,他左边和上面两个导航栏是不会改变的。改变的只是右边那一块区域。将鼠标放在某个标签上面,我们可以看到,他就是一个路由。或者我们应该说,他就是一个子路由。
index.js 添加路由
- const _import = require('./import-' + process.env.NODE_ENV)
-
-
- //全局路由
- const routes = [
- { path: '/login', name:'login',component: _import('login') },
- ]
-
- // 嵌套路由入口
- const mainRoutes = {
- path: '/',
- component: _import('layout/main'),
- name: 'main',
- redirect: { name: 'home' },
- meta: { title: '主入口整体布局' },
- children: [
- { path: '/home', component: _import('demo/list'), name: 'home', meta: { title: '首页' } },
- { path: '/test1', component: _import('demo/test1'), name: 'test1', meta: { title: '选项一', isTab: true } },
- { path: '/test2', component: _import('demo/test2'), name: 'test2', meta: { title: '选项二', isTab: true } },
- { path: '/test', component: _import('demo/add'), name: 'test', meta: { title: '测试功能', isTab: true } },
- { path: '/theme', component: _import('common/theme'), name: 'theme', meta: { title: '主题', isTab: true } },
- ],
- }
-
- export default new Router({
- routes: routes.concat(mainRoutes)
- })
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
vuex 包含有五个基本的对象:
state:存储状态。也就是变量;
getters:派生状态。也就是set、get中的get,有两个可选参数:state、getters分别可以获取state中的变量和其他的getters。外部调用方式:store.getters.personInfo()。就和vue的computed差不多;
mutations:提交状态修改。也就是set、get中的set,这是vuex中唯一修改state的方式,但不支持异步操作。第一个参数默认是state。外部调用方式:store.commit(‘SET_AGE’, 18)。和vue中的methods类似。
actions:和mutations类似。不过actions支持异步操作。第一个参数默认是和store具有相同参数属性的对象。外部调用方式:store.dispatch(‘nameAsyn’)。this.$store.dispatch(‘user/login’, this.loginForm)
modules:store的子模块,内容就相当于是store的一个实例。调用方式和前面介绍的相似,只是要加上当前子模块名,如:store.a.getters.xxx()。
有了Vuex可以实现组件全局状态(数据)的管理,方便的实现组件之间的数据共享。
Sass 是一个 CSS 的扩展,它在 CSS 语法的基础上,允许使用变量 (variables),嵌套规则 (nested rules), 混合 (mixins), 导入 (inline imports) 等功能,令 CSS 更加强大与优雅。使用 Sass 以及 Compass 样式库 有助于更好地组织管理样式文件,以及更高效地开发项目。
- npm install node-sass --save-dev //安装node-sass
- npm install sass-loader --save-dev //安装sass-loader
- npm install style-loader --save-dev //安装style-loader
此处安装后可能会因sass-loader版本过高报错,可手动指定版本
npm install sass-loader@7.3.1 --save-dev //版本不能太高
也可在package.json中更改版本,然后npm install
我们先研后台管理系统,管理系统一般有一下几类UI页面。
1、登录页面
这个不多说了用户密码登录页面。
2、主页面
登录验证成功后跳转到本页面,左侧菜单右侧详情的常规布局。
3、功能列表页
4、功能编辑详情
登录页面前边我们已经实现了简单表单,样子比较丑陋,登录页比较简单,样式大家可以自行找网上提供的布局样式也可,基础较好的同学可以自己调整布局。这里举一个简单的登录样式的样例。
- <template>
- <div class="login">
- <el-form ref="dataForm" :model="dataForm" :rules="loginRules" size="mini" class="login-form" status-icon>
- <h2 class="title">欢迎登录后台管理系统</h2>
- <el-form-item prop="username">
- <el-input
- v-model="dataForm.username"
- type="text"
- auto-complete="off"
- placeholder="账号"
- >
- <i slot="prefix" class="el-input__icon el-icon-s-custom svg-external-icon"></i>
- </el-input>
- </el-form-item>
- <el-form-item prop="password">
- <el-input
- v-model="dataForm.password"
- type="password"
- auto-complete="off"
- placeholder="密码"
- @keyup.enter.native="dataFormSubmit"
- >
- <i slot="prefix" class="el-input__icon el-icon-s-goods svg-external-icon"></i>
- </el-input>
- </el-form-item>
- <!-- <el-form-item prop="captcha" v-if="captchaOnOff">
- <el-input
- v-model="dataForm.captcha"
- auto-complete="off"
- placeholder="验证码"
- style="width: 63%"
- @keyup.enter.native="dataFormSubmit"
- >
- <i slot="prefix" class="el-input__icon el-icon-menu svg-external-icon"></i>
- </el-input>
- <div class="login-code">
- <img :src="captchaPath" @click="getCaptcha()" style="width: 100%" class="login-code-img"/>
- </div>
- </el-form-item>-->
- <!-- <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>-->
- <el-form-item style="width:100%;">
- <el-button
- :loading="loading"
- size="medium"
- type="primary"
- style="width:100%;"
- @click.native.prevent="dataFormSubmit"
- >
- <span v-if="!loading">登 录</span>
- <span v-else>登 录 中...</span>
- </el-button>
- <div style="float: right;" v-if="register">
- <router-link class="link-type" :to="'/register'">立即注册</router-link>
- </div>
- </el-form-item>
- </el-form>
- <!-- 底部 -->
- <div class="el-login-footer">
- <span>Copyright © 2021-2022 All Rights Reserved.</span>
- </div>
- </div>
- </template>
-
- <script>
-
- export default {
- name: "Login",
- data() {
- return {
- codeUrl: "",
- dataForm: {
- username: '',
- password: '',
- uid: '',
- captcha: '',
- client_id:'webApp',
- client_secret:'webApp',
- grant_type:'password'
- },
- loginRules: {
- username: [
- { required: true, trigger: "blur", message: "请输入您的账号" }
- ],
- password: [
- { required: true, trigger: "blur", message: "请输入您的密码" }
- ],
- captcha: [{ required: true, trigger: "change", message: "请输入验证码" }]
- },
- captchaPath: '',
- loading: false,
- // 验证码开关
- captchaOnOff: true,
- // 注册开关
- register: false,
- };
- },
- created() {
- // this.getCaptcha()
- var info=this.$route.params.data
- if(info!=null)
- this.$message({
- showClose: true,
- message: info,
- type: 'error',
- duration:1000
- });
- },
- methods: {
- // 提交表单
- dataFormSubmit () {
- this.$refs['dataForm'].validate((valid) => {
- if (valid) {
- this.loading = true;
- this.$router.replace({ name: 'home'})
-
- }
- })
- },
- // 获取验证码
- getCaptcha () {
- this.dataForm.uid = getUUID()
- this.captchaPath = this.$http.adornUrl(`/api-auth/captcha/captcha.jpg?uid=${this.dataForm.uid}`)
- },
- }
- };
- </script>
-
- <style rel="stylesheet/scss" lang="scss">
- .login {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100%;
- /*background-image: url("../assets/images/login-background.jpg");*/
- background: #3a8ee6;
- background-size: cover;
- }
- .title {
- margin: 0px auto 20px auto;
- text-align: center;
- color: #707070;
- }
-
- .login-form {
- border-radius: 6px;
- background: #ffffff;
- width: 450px;
-
- padding: 25px 25px 5px 25px;
- .el-input {
- height: 38px;
- input {
- height: 38px;
- }
- }
- .input-icon {
- height: 39px;
- width: 14px;
- margin-left: 2px;
- }
- }
- .login-tip {
- font-size: 13px;
- text-align: center;
- color: #bfbfbf;
- }
- .login-code {
- width: 33%;
- height: 36px;
- float: right;
- img {
- cursor: pointer;
- vertical-align: middle;
- }
- }
- .el-login-footer {
- height: 40px;
- line-height: 40px;
- position: fixed;
- bottom: 0;
- width: 100%;
- text-align: center;
- color: #fff;
- font-family: Arial;
- font-size: 12px;
- letter-spacing: 1px;
- }
- .login-code-img {
- height: 38px;
- }
- .svg-external-icon{
- font-size: 12px;
- //margin-right: 18px;
- margin-left: 3px;
- display: flex;
- align-items: center;
- }
- body {
- height: 100%;
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: antialiased;
- text-rendering: optimizeLegibility;
- font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
- }
-
- html {
- height: 100%;
- box-sizing: border-box;
- }
-
- #app {
- height: 100%;
- }
- .h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
- font-family: inherit;
- font-weight: 500;
- line-height: 1.1;
- color: inherit;
- }
- </style>
访问 :http://localhost:9081/#/login 显示如下

这里先不做后台校验,随便输入用户名、密码后跳转主页面。
主页面是整个后台管理系统的门面,它的重要程度不言而喻。
先实现常规的左侧是菜单、右侧是详情页面,头部有登录人的基础信息提示。更炫酷的要求后面逐步实现。
整体布局我们参考element官网布局容器来实现,我门以这个样例作为参考样例。

新增主页面main.vue
- <template>
- <div class="site-wrapper" :class="classObj">
- <template >
- <main-sidebar />
- <main-navbar />
- <div class="site-content__wrapper" :style="styleObj">
- <main-content />
- </div>
- </template>
- </div>
- </template>
-
- <script>
- import MainNavbar from './main-navbar'
- import MainSidebar from './main-sidebar'
- import MainContent from './main-content'
-
- export default {
- data () {
- return {
- loading: true,
- styleObj: {'min-height': this.documentClientHeight + 'px'}
- }
- },
- components: {
- MainNavbar,
- MainSidebar,
- MainContent
- },
- computed: {
- documentClientHeight: {
- get () { return this.$store.state.common.documentClientHeight },
- set (val) { this.$store.commit('common/updateDocumentClientHeight', val) }
- },
- userId: {
- get () { return this.$store.state.user.id },
- set (val) { this.$store.commit('user/updateId', val) }
- },
- userName: {
- get () {
- return this.$store.state.user.name
- },
- set (val) {
- this.$store.commit('user/updateName', val)
- }
- },
- sidebarFold: {
- get () { return this.$store.state.common.sidebarFold }
- },
- clientType() {
- let type = this.$store.state.common.clientType;
- if (type === 'phone') {
- this.styleObj['margin-left'] = '0px';
- this.styleObj['padding-top'] = '100px';
- } else {
- if (this.styleObj['margin-left']) this.$delete(this.styleObj, 'margin-left');
- if (this.styleObj['padding-top']) this.$delete(this.styleObj, 'padding-top');
- }
- return type
- },
- showScreen() {
- if (this.clientType == 'phone' && !this.sidebarFold) return true;
- return false;
- },
- classObj() {
- return {
- 'site-sidebar--hide': this.sidebarFold && this.clientType == 'phone',
- 'site-sidebar--fold': this.sidebarFold && this.clientType != 'phone',
- 'tab-phone-top': this.clientType == 'phone'
- };
- }
- },
- created () {
-
- },
- mounted () {
- this.resetDocumentClientHeight()
- },
- methods: {
-
- }
- }
- }
- </script>
封装Aside、Header、Main-content三个组件,在Main.vue主页面中使用。
Aside组件存放菜单
参照element官网 导航菜单组件
main-sidebar.vue
- <template>
- <aside class="site-sidebar" :class="'site-sidebar--' + sidebarLayoutSkin">
- <div class="site-sidebar__inner">
- <el-menu
- :collapse="sidebarFold"
- default-active="home"
- :collapseTransition="false"
- class="site-sidebar__menu"
- >
- <el-menu-item index="home" @click="$router.push({ name: 'home' })" v-show="showSidebar">
- <i class="el-icon-s-home"></i>
- <span slot="title">首页</span>
- </el-menu-item>
- <el-submenu index="1">
- <template slot="title">
- <i class="el-icon-location"></i>
- <span>导航一</span>
- </template>
- <el-menu-item-group>
- <template slot="title">分组一</template>
- <el-menu-item index="1-1" @click="$router.push({ name: 'test1' })">选项1</el-menu-item>
- <el-menu-item index="1-2" @click="$router.push({ name: 'test2' })">选项2</el-menu-item>
- </el-menu-item-group>
- <el-menu-item-group title="分组2">
- <el-menu-item index="1-3">选项3</el-menu-item>
- </el-menu-item-group>
- <el-submenu index="1-4">
- <template slot="title">选项4</template>
- <el-menu-item index="1-4-1">选项1</el-menu-item>
- </el-submenu>
- </el-submenu>
- <el-menu-item index="2">
- <i class="el-icon-menu"></i>
- <span slot="title">导航二</span>
- </el-menu-item>
- <el-menu-item index="3" disabled>
- <i class="el-icon-document"></i>
- <span slot="title">导航三</span>
- </el-menu-item>
- <el-menu-item index="4">
- <i class="el-icon-setting"></i>
- <span slot="title">导航四</span>
- </el-menu-item>
- </el-menu>
- </div>
- </aside>
- </template>
-
- <script>
- import { isURL } from '@/utils/validate'
- export default {
- data () {
- return {
- dynamicMenuRoutes: [],
- menuValue: '',
- leafMenu: []
- }
- },
- components: {
-
- },
- computed: {
- sidebarLayoutSkin: {
- get () { return this.$store.state.common.sidebarLayoutSkin }
- },
- sidebarFold: {
- get () { return this.$store.state.common.sidebarFold }
- },
- menuList: {
- get () { return this.$store.state.common.menuList },
- set (val) { this.$store.commit('common/updateMenuList', val) }
- },
- menuActiveName: {
- get () { return this.$store.state.common.menuActiveName },
- set (val) { this.$store.commit('common/updateMenuActiveName', val) }
- },
- mainTabs: {
- get () { return this.$store.state.common.mainTabs },
- set (val) { this.$store.commit('common/updateMainTabs', val) }
- },
- mainTabsActiveName: {
- get () { return this.$store.state.common.mainTabsActiveName },
- set (val) { this.$store.commit('common/updateMainTabsActiveName', val) }
- },
- showSidebar() {//在phone模式并且关闭菜单状态下不展示菜单
- if (this.$store.state.common.clientType == 'phone' && this.sidebarFold) return false;
- return true;
- }
- },
- watch: {
- $route: 'routeHandle'
- },
- created () {
- this.menuList = JSON.parse(sessionStorage.getItem('menuList') || '[]')
- this.dynamicMenuRoutes = JSON.parse(sessionStorage.getItem('dynamicMenuRoutes') || '[]')
- this.routeHandle(this.$route)
- this.getLeafMenu(this.menuList);
- },
- methods: {
- getLeafMenu(menuList) {
- menuList.forEach((item)=>{
- if (item.list) {
- this.getLeafMenu(item.list)
- } else {
- this.leafMenu.push(item)
- }
- })
- },
- chose() {
- let route = this.dynamicMenuRoutes.filter(item => item.meta.menuId === this.menuValue)
- if (route.length >= 1) {
- this.$router.push({name: route[0].name})
- }
- this.menuValue = ''
- },
- // 路由操作
- routeHandle (route) {
- if (route.meta.isTab&&this.$store.state.common.navbarTab) {
- // tab选中, 不存在先添加
- var tab = this.mainTabs.filter(item => item.name === route.name)[0]
- if (!tab) {
- if (route.meta.isDynamic) {
- var globalRoutes=this.$router.options.routes
- var mainRoutes
- for (var i = 0; i < globalRoutes.length; i++) {
- if (globalRoutes[i].children && globalRoutes[i].children.length >= 1 && globalRoutes[i].name == 'main-dynamic') {
- mainRoutes = globalRoutes[i].children
- }
- }
- route = mainRoutes.filter(item => item.name === route.name)[0]
- if (!route) {
- return console.error('未能找到可用标签页!')
- }
- }
- tab = {
- menuId: route.meta.menuId || route.name,
- name: route.name,
- title: route.meta.title,
- type: isURL(route.meta.iframeUrl) ? 'iframe' : 'module',
- iframeUrl: route.meta.iframeUrl || ''
- }
- this.mainTabs = this.mainTabs.concat(tab)
- }
- this.menuActiveName = tab.menuId + ''
- this.mainTabsActiveName = tab.name
- }
- }
- }
- }
- </script>
Header
- <template>
- <nav class="site-navbar" :class="'site-navbar--' + navbarLayoutType">
- <div class="site-navbar__header" :style="brandStyle">
- <h1 class="site-navbar__brand" :style="brandStyle" @click="$router.push({ name: 'home' })">
- <a class="site-navbar__brand-lg" href="javascript:;">后台管理系统</a>
- <a class="site-navbar__brand-mini" href="javascript:;"></a>
- </h1>
- </div>
- <div class="site-navbar__body clearfix">
- <el-menu
- class="site-navbar__menu"
- mode="horizontal">
- <el-menu-item class="site-navbar__switch" index="0" @click="sidebarFold = !sidebarFold">
- <i class="el-icon-s-fold"></i>
- </el-menu-item>
- </el-menu>
- <el-menu
- class="site-navbar__menu site-navbar__menu--right"
- mode="horizontal">
- <el-menu-item class="site-navbar__avatar" index="3">
- <el-dropdown :show-timeout="0" placement="bottom">
-
- <span class="el-dropdown-link">
- 欢迎,登录!
- </span>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item @click.native="updatePasswordHandle()">修改密码</el-dropdown-item>
- <el-dropdown-item @click.native="logoutHandle()">退出</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </el-menu-item>
- </el-menu>
- </div>
- </nav>
- </template>
-
- <script>
- export default {
- name: 'screenfull',
- data () {
- return {
- updatePassowrdVisible: false,
- isFullscreen: false,
- }
- },
- components: {
-
- },
- computed: {
- navbarLayoutType: {
- get () { return this.$store.state.common.navbarLayoutType }
- },
- sidebarFold: {
- get () { return this.$store.state.common.sidebarFold },
- set (val) { this.$store.commit('common/updateSidebarFold', val) }
- },
- mainTabs: {
- get () { return this.$store.state.common.mainTabs },
- set (val) { this.$store.commit('common/updateMainTabs', val) }
- },
- userName: {
- get () { return this.$store.state.user.name }
- },
- brandStyle: {
- get() {
- let type = this.$store.state.common.clientType;
- if (type === 'phone') {
- return this.brandStyle = {
- float: 'none',
- width: '100%'
- }
- } else {
- return this.brandStyle = {}
- }
- },
- set() {}
- }
- },
- methods: {
- // 修改密码
- updatePasswordHandle () {
- this.updatePassowrdVisible = true
- this.$nextTick(() => {
- this.$refs.updatePassowrd.init()
- })
- },
- // 退出
- logoutHandle () {
- this.$router.push({ name: 'login' })
- }
- }
- }
- </script>
右侧主页面
主页面多个tabs标签页组成,
参考官网
main-content.vue
- <template>
- <main class="site-content" :class="{ 'site-content--tabs': $route.meta.isTab && this.$store.state.common.navbarTab}">
- <!-- 主入口标签页 s -->
- <el-tabs
- v-if="$route.meta.isTab && this.$store.state.common.navbarTab"
- v-model="mainTabsActiveName"
- :closable="true"
- @tab-click="selectedTabHandle"
- @tab-remove="removeTabHandle">
- <el-dropdown class="site-tabs__tools" :show-timeout="0">
- <i class="el-icon-arrow-down el-icon--right"></i>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item @click.native="tabsCloseCurrentHandle">关闭当前标签页</el-dropdown-item>
- <el-dropdown-item @click.native="tabsCloseOtherHandle">关闭其它标签页</el-dropdown-item>
- <el-dropdown-item @click.native="tabsCloseAllHandle">关闭全部标签页</el-dropdown-item>
- <el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新当前标签页</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- <el-tab-pane
- v-for="item in mainTabs"
- :key="item.name"
- :label="item.title"
- :name="item.name">
- <el-card :body-style="siteContentViewHeight">
- <iframe
- v-if="item.type === 'iframe'"
- :src="item.iframeUrl"
- width="100%" height="100%" frameborder="0" scrolling="yes">
- </iframe>
- <keep-alive v-else>
- <router-view v-if="item.name === mainTabsActiveName" />
- </keep-alive>
- </el-card>
- </el-tab-pane>
- </el-tabs>
- <!-- 主入口标签页 e -->
- <el-card v-else :body-style="siteContentViewHeight">
- <keep-alive>
- <router-view />
- </keep-alive>
- </el-card>
- </main>
- </template>
-
- <script>
- import { isURL } from '@/utils/validate'
- export default {
- data () {
- return {
- }
- },
- computed: {
- documentClientHeight: {
- get () { return this.$store.state.common.documentClientHeight }
- },
- menuActiveName: {
- get () { return this.$store.state.common.menuActiveName },
- set (val) { this.$store.commit('common/updateMenuActiveName', val) }
- },
- mainTabs: {
- get () { return this.$store.state.common.mainTabs },
- set (val) { this.$store.commit('common/updateMainTabs', val) }
- },
- mainTabsActiveName: {
- get () { return this.$store.state.common.mainTabsActiveName },
- set (val) { this.$store.commit('common/updateMainTabsActiveName', val) }
- },
- siteContentViewHeight () {
- var height = this.documentClientHeight - 50 - 30 - 2
- if (this.$route.meta.isTab && this.$store.state.common.navbarTab) {
- height -= 40
- return isURL(this.$route.meta.iframeUrl) ? { height: height + 'px' } : { minHeight: height + 'px' }
- }
- return { minHeight: height + 'px' }
- }
- },
- methods: {
- // tabs, 选中tab
- selectedTabHandle (tab) {
- tab = this.mainTabs.filter(item => item.name === tab.name)
- if (tab.length >= 1) {
- this.$router.push({ name: tab[0].name })
- }
- },
- // tabs, 删除tab
- removeTabHandle (tabName) {
- this.mainTabs = this.mainTabs.filter(item => item.name !== tabName)
- if (this.mainTabs.length >= 1) {
- // 当前选中tab被删除
- if (tabName === this.mainTabsActiveName) {
- this.$router.push({ name: this.mainTabs[this.mainTabs.length - 1].name }, () => {
- this.mainTabsActiveName = this.$route.name
- })
- }
- } else {
- this.menuActiveName = ''
- this.$router.push({ name: 'home' })
- }
- },
- // tabs, 关闭当前
- tabsCloseCurrentHandle () {
- this.removeTabHandle(this.mainTabsActiveName)
- },
- // tabs, 关闭其它
- tabsCloseOtherHandle () {
- this.mainTabs = this.mainTabs.filter(item => item.name === this.mainTabsActiveName)
- },
- // tabs, 关闭全部
- tabsCloseAllHandle () {
- this.mainTabs = []
- this.menuActiveName = ''
- this.$router.push({ name: 'home' })
- },
- // tabs, 刷新当前
- tabsRefreshCurrentHandle () {
- var tempTabName = this.mainTabsActiveName
- this.removeTabHandle(tempTabName)
- this.$nextTick(() => {
- this.$router.push({ name: tempTabName })
- })
- }
- }
- }
- </script>
-
访问测试
list.vue
- <template>
- <div>
- <el-form :model="dataForm" ref="dataForm">
- <el-row :gutter="20" >
- <el-col :xs="24" :sm="6" >
- <el-form-item prop="classCode">
- <el-input v-model="dataForm.name" placeholder="姓名" maxlength="20" clearable></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="6" >
- <el-form-item prop="className">
- <el-input v-model="dataForm.province" placeholder="省份" maxlength="20" clearable></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="{span:24,offset:0}" :sm="{span:6,offset:6}">
- <el-form-item style="float: right">
- <el-button type="primary" icon="el-icon-search">查询</el-button>
- <el-button type="default" plain icon="el-icon-refresh-left">重置</el-button>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <el-divider></el-divider>
- <el-row style="padding-bottom: 10px;" align="left">
- <el-button type="primary" icon="el-icon-plus" @click="addPage()">新增</el-button>
- <el-button type="success" icon="el-icon-mouse" @click="add()">测试</el-button>
- <el-button type="info" @click="addPage()">弹框按钮</el-button>
- </el-row>
- <el-table
- :data="tableData"
- border
- style="width: 100%">
- <el-table-column
- fixed
- prop="date"
- label="日期"
- >
- </el-table-column>
- <el-table-column
- prop="name"
- label="姓名"
- >
- </el-table-column>
- <el-table-column
- prop="province"
- label="省份"
- width="120">
- </el-table-column>
- <el-table-column
- prop="city"
- label="市区"
- width="120">
- </el-table-column>
- <el-table-column
- prop="address"
- label="地址"
- width="300">
- </el-table-column>
- <el-table-column
- prop="zip"
- label="邮编"
- width="120">
- </el-table-column>
- <el-table-column
- fixed="right"
- label="操作"
- width="100">
- <template slot-scope="scope">
- <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
- <el-button type="text" size="small">编辑</el-button>
- </template>
- </el-table-column>
- </el-table>
- <add-page ref="addPage" @refreshDataList="test"></add-page>
- </div>
- </template>
-
- <script>
- import axios from 'axios'
- import AddPage from './addPage'
- export default {
- components: {
- AddPage
- },
- methods: {
- handleClick(row) {
- console.log(row);
- },
- test(){
- axios
- .get('http://127.0.0.1:8888/test', {
- params: {
- id: 12345
- }
- })
- .then(response => (
- // this.info = response
- alert(response.data)
- // this.info = response
- ))
- .catch(function (error) { // 请求失败处理
- console.log(error);
- });
- },
- add(){
- this.$router.push({ path:'/add'})
- },
- addPage(id){
- this.$nextTick(() => {
- this.$refs.addPage.init(id);
- })
- }
- },
- mounted () {
-
- },
- data() {
- return {
- dataForm: {
- name: '',
- province: ''
- },
- addPageVisible: false,
- tableData: [{
- date: '2016-05-02',
- name: '王小虎',
- province: '上海',
- city: '普陀区',
- address: '上海市普陀区金沙江路 1518 弄',
- zip: 200333
- }, {
- date: '2016-05-04',
- name: '王小虎',
- province: '上海',
- city: '普陀区',
- address: '上海市普陀区金沙江路 1517 弄',
- zip: 200333
- }, {
- date: '2016-05-01',
- name: '王小虎',
- province: '上海',
- city: '普陀区',
- address: '上海市普陀区金沙江路 1519 弄',
- zip: 200333
- }, {
- date: '2016-05-03',
- name: '王小虎',
- province: '上海',
- city: '普陀区',
- address: '上海市普陀区金沙江路 1516 弄',
- zip: 200333
- }]
- }
- }
- }
- </script>
-
- <style scoped>
- .el-divider--horizontal {
- display: block;
- height: 1px;
- width: 100%;
- margin: 12px 0;
- }
- </style>
演示截图
addPage.vue
- <template>
- <el-dialog
- class="custom_dialog"
- :fullscreen=false
- :show-close=false
- :close-on-click-modal=false
- :visible.sync="visible">
- <div slot="title" class="dialog-title">
- <i class="el-icon-edit-outline"></i>
- <span class="title-text">数据详情</span>
- </div>
-
- <el-form :model="dataForm" :rules="dataRule" ref="dataForm"
- label-width="100px">
- <el-row :gutter="40">
- <el-col :xs="24" :lg="24">
- <el-form-item label="姓名:" prop="classCode">
- <el-input v-model="dataForm.classCode" maxlength="20" placeholder="类型编码"></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :lg="24">
- <el-form-item label="省份:" prop="className">
- <el-input v-model="dataForm.className" maxlength="20" placeholder="类型名称"></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :lg="24">
- <el-form-item label="邮编:" prop="dataName">
- <el-input v-model="dataForm.dataName" maxlength="20" placeholder="名称"></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :lg="24">
- <el-form-item label="邮编:" prop="dataName">
- <el-input v-model="dataForm.dataName" maxlength="20" placeholder="名称"></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :lg="24">
- <el-form-item label="市区:" prop="dataCode">
- <el-input v-model="dataForm.dataCode" maxlength="20" placeholder="键值"></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :lg="24">
- <el-form-item label="邮编:" prop="dataName">
- <el-input v-model="dataForm.dataName" maxlength="20" placeholder="名称"></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :lg="24">
- <el-form-item label="地址:" prop="dataOrder">
- <el-input v-model="dataForm.dataOrder" maxlength="10" placeholder="排序"></el-input>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <span slot="footer" class="dialog-footer">
- <el-button icon="el-icon-close" @click="visible = false">取消</el-button>
- <el-button icon="el-icon-check" type="primary">提交</el-button>
- </span>
- </el-dialog>
- </template>
-
- <script>
- export default {
- data() {
- return {
- visible: false,
- dataForm: {
- id: '',
- classCode: '',
- className: '',
- dataCode: '',
- dataName: '',
- dataOrder: '',
- status: ''
- },
- dataRule: {
- classCode: [
- {required: true, message: '类型编码不能为空', trigger: 'blur'}
- ],
- className: [
- {required: true, message: '类型名称不能为空', trigger: 'blur'}
- ],
- dataCode: [
- {required: true, message: '键值不能为空', trigger: 'blur'}
- ],
- dataName: [
- {required: true, message: '名称不能为空', trigger: 'blur'}
- ],
- dataOrder: [
- {required: true, message: '排序不能为空', trigger: 'blur'}
- ],
- status: [
- {required: true, message: '状态不能为空', trigger: 'blur'}
- ]
- }
- }
- },
- methods: {
- submitForm(formName) {
- this.$refs[formName].validate((valid) => {
- if (valid) {
- alert('submit!');
- } else {
- console.log('error submit!!');
- return false;
- }
- });
- },
- resetForm(formName) {
- this.$refs[formName].resetFields();
- },
- init (id) {
- // this.dataForm.id = id
- this.visible = true
- }
- }
- }
- </script>
-
- <style scoped>
-
- </style>
演示样例
以上就是前端系统主要页面及常用组件,有新的组件可通过elementUI官网,查询具体用法,另外样式的底层逻辑是相同的。