前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >业务后台商业组件ViewUI(iView)入门

业务后台商业组件ViewUI(iView)入门

作者头像
用户10175992
发布2022-11-15 13:23:54
1.6K0
发布2022-11-15 13:23:54
举报
文章被收录于专栏:辰远

1 安装View UI组件

1.1 什么是View UI

后台管理信息系统(MIS)是软件开发的一个重要领域,如OA、ERP、商城后台等等都属于MIS系统。业务人员需要在MIS系统中操作大量的表单和数据,传统的服务器(同步)页面伴随着大量刷新,用户体验很差,所以开发界喜欢选择以vue为代表的新一代前后端分离技术以实现流程的操作。

在MIS系统开发中,需要大量的表单、表格、日历、选项卡等复杂组件来完成业务功能,这些组件实现起来都比较复杂,作为普通程序员,一般会选择现成的商业组件。

业界比较成熟的后台商业组件主要有:Element UI、View UI 和 Ant Design,这些组件的功能和使用方式都大同小异,这里介绍View UI给大家使用。

官网:iView - A high quality UI Toolkit based on Vue.js

View UI的前身是iView,至今已经是4.0版,由于最新版引入了商业模式,因此代码更新较快。

1.2 安装View UI

官方的安装教程:https://www.iviewui.com/docs/guide/install

为vue项目安装View UI组件有很多方式,这里使用最简便得方法,就是直接使用vue-cli得ui向导来完成安装。新版得vue-cli不仅可以通过命令行来完成项目创建,还可以通过web可视化方式创建,View UI可以作为vue-cli的插件添加到项目中。

(1)使用vue-cli可视化项目管理器

在命令行中输入以下指令:

代码语言:javascript
复制
vue ui

(2)添加插件:axios 和 view-ui

 完成上述操作后,一个包含view-ui插件库的vue工程就创建好了,正常进入项目目录执行:

代码语言:javascript
复制
npm run serve

2 项目布局:

2.1 栅格系统

类似BootStrap中的12栅格系统,View UI通用把页面分为行(Row)和列(Col),使用24栅格进行布局。

官方的栅格教程:https://www.iviewui.com/components/grid

2.2 设置路由:

(1)分层次创建组件

(2)设置父子级别路由: 

代码语言:javascript
复制
const routes = [
2
    {
3
      path: '/',
4
      name: 'home', 
5
      component: Home,
6
      children:[
7
        {
8
          path:'/',
9
          name:'default',
10
          component:Default,
11
          meta:{
12
            title: '后台首页'
13
          }
14
        },
15
        {
16
          path:'/categories',
17
          name:'categories',
18
          component:Categories,
19
          meta:{
20
            title: '分类管理'
21
          }
22
        },
23
        {
24
          path:'/products',
25
          name:'products',
26
          component:Products,
27
          meta:{
28
            title: '商品管理'
29
          }
30
        },
31
      ]
32
    },
33
    {
34
      path:'/login',
35
      name:'login',
36
      component:Login
37
    }
38
  ]

2.3 布局

业务系统通常由比较严谨的布局,View UI为我们准备好了多种布局风格,这里使用“顶部-侧边布局”作为示例:

​​​​​​https://www.iviewui.com/components/layout#DB-CBBJ

代码语言:javascript
复制
<style scoped>
2
......
3
.layout-logo{
4
    ......
5
    color:#fff;
6
    line-height: 30px;
7
    text-align: center;
8
}
9
......
10
</style>
11
<template>
12
    <div class="layout">
13
        <Layout>
14
            <Header>
15
                <Menu mode="horizontal" theme="dark" active-name="1">
16
                    <div class="layout-logo">
17
                      <router-link to="/"><h3>趣物网 - 后台管理</h3></router-link>  
18
                    </div>
19
                    <div class="layout-nav">
20
                        <MenuItem name="1">
21
                            <Icon type="ios-navigate"></Icon>
22
                            Item 1
23
                        </MenuItem>
24
                        <MenuItem name="2">
25
                            <Icon type="ios-keypad"></Icon>
26
                            Item 2
27
                        </MenuItem>
28
                        <MenuItem name="3">
29
                            <Icon type="ios-analytics"></Icon>
30
                            Item 3
31
                        </MenuItem>
32
                        <MenuItem name="4">
33
                            <Icon type="ios-paper"></Icon>
34
                            Item 4
35
                        </MenuItem>
36
                    </div>
37
                </Menu>
38
            </Header>
39
            <Layout :style="{padding: '0 50px'}">
40
                <Breadcrumb :style="{margin: '16px 0'}">
41
                    <BreadcrumbItem>后台管理</BreadcrumbItem>
42
                    <BreadcrumbItem>{{$route.meta.title}}</BreadcrumbItem>
43
                </Breadcrumb>
44
                <Content :style="{padding: '24px 0', minHeight: '280px', background: '#fff'}">
45
                    <Layout>
46
                        <Sider hide-trigger :style="{background: '#fff'}">
47
                            <Menu active-name="1-2" theme="light" width="auto" :open-names="['1']">
48
                                <Submenu name="1">
49
                                    <template slot="title">
50
                                        <Icon type="ios-navigate"></Icon>
51
                                        商品信息管理
52
                                    </template>
53
                                    <MenuItem name="1-1">
54
                                      <router-link to="/categories">分类管理</router-link>
55
                                    </MenuItem>
56
                                    <MenuItem name="1-2">
57
                                      <router-link to="/products">商品管理</router-link>
58
                                    </MenuItem>
59
                                </Submenu>
60
                                <Submenu name="2">
61
                                    <template slot="title">
62
                                        <Icon type="ios-analytics"></Icon>
63
                                        客户订单管理
64
                                    </template>
65
                                </Submenu>
66
                            </Menu>
67
                        </Sider>
68
                        <Content :style="{padding: '24px', minHeight: '280px', background: '#fff'}">
69
                          <router-view></router-view>
70
                        </Content>
71
                    </Layout>
72
                </Content>
73
            </Layout>
74
            <Footer class="layout-footer-center">2011-2016 &copy; TalkingData</Footer>
75
        </Layout>
76
    </div>
77
</template>
78
<script>
79
  export default {}
80
</script>

3 常见组件的使用:

3.1 Table - 数据表格

表格组件通过columns属性绑定列,通过data属性绑定行数据。以分类管理组件(Categories.vue)为例:

代码语言:javascript
复制
 <Table border :columns="columns" :data="categories"> 
2
      <template slot="operation" slot-scope="{row}">
3
        <Button type="primary" @click="showEdit(row)">修改</Button>&nbsp;
4
        <Button type="error" @click="deleteCategory(row)">删除</Button>
5
      </template>
6
    </Table>

背后绑定的数据:

代码语言:javascript
复制
export default {
2
  name:'categories',
3
  data(){
4
    return {
5
      columns:[
6
        {title:'分类ID', key:'id'},
7
        {title:'分类名称', key:'name'},
8
        {title:'操作', slot:'operation', align: 'center'}
9
      ],
10
      categories:[]
11
    }
12
  },

其中 coloumns中每一个对象代表一个列,title是列标题,key是该列绑定的对象属性名。

如果列中由其它组件组成,则可以定义为插槽(slot),让后再通过Table组件中的模板(template)去定制slot中的结构。

template中的slot属性需要和columns中对用列的slot属性向对应,template中的slot-scope则用于定义Table向slot中传入的上下文数据。

3.2  Form - 表单组件

表单组件可以绑定数据和数据校验。以登录组件(Login.vue)为例:

代码语言:javascript
复制
<template>
2
<div>
3
  <h1 class="title">趣物网-登录</h1>
4
  <Row>
5
    <Col span="8" offset="8">
6
      <Card>
7
        <p slot="title">
8
            <Icon type="ios-film-outline"></Icon>用户登录
9
        </p>
10
        <Form ref="loginForm" :model="user" :rules="ruleValidate" :label-width="80">
11
          <FormItem label="用户名" prop="username">
12
              <Input v-model="user.username" placeholder="用户名..." />
13
          </FormItem>
14
          <FormItem label="密码" prop="password">
15
              <Input type="password" v-model="user.password" placeholder="密码..." />
16
          </FormItem>
17
          <FormItem>
18
              <Button @click="login" type="primary">登录</Button>
19
          </FormItem>
20
        </Form>
21
      </Card>
22
    </Col>
23
  </Row>
24
</div>
25
</template>

(1)Form的 :model="user" 用于设置绑定对象,:rules="ruleValidate" 用于设置绑定验证;

(2)其中FormItem的 prop="username" 用于指定当前项需要验证的属性名,即ruleValidate中的属性名;

(3)为了方便调用验证,我们使用 ref="loginForm" 为表单对象设置了引用名,于是下面的代码可以通过 “this.$refs['loginForm'].validate( (valid)=>{...} )” 来显式调用表单验证。

代码语言:javascript
复制
<script>
2
import UserInfo from '@/js/UserInfo.js'
3
const userInfo = new UserInfo();
4
5
export default {
6
  name:'login',
7
  data(){
8
    return{
9
      user:{
10
        username:'',
11
        password:''
12
      },
13
      ruleValidate:{
14
          username:[{required:true, message:'请填写用户名', trigger:'blur'}],
15
          password:[{required:true, message:'请填写密码', trigger:'blur'}],
16
      }
17
    }
18
  },
19
  methods:{
20
    login(){
21
      this.$refs['loginForm'].validate((valid)=>{
22
        if(valid){
23
          this.axios.post('/api/auth/login', this.user).then(res=>{
24
            if(res.data.roleName!='管理员'){
25
              alert('您不是管理员,无法进入后台');
26
            }else{
27
              userInfo.saveLoginUser(res.data);
28
              let redirect ='/'
29
              if(this.$route.query.redirect){
30
                redirect = this.$route.query.redirect;
31
              }
32
              this.$router.push({path: redirect});
33
            }
34
            
35
          }).catch(()=>alert('用户名或密码有误'));
36
        }
37
      });
38
    }
39
  }
40
}
41
</script>

3.3 Modal - 模态框

模态框可以通过简单的布尔属性绑定实现显示和隐藏。继续实现分类管理(Categories.vue)中的分类信息编辑功能:

代码语言:javascript
复制
<Modal
2
      v-model="showModal"
3
      title="商品分类编辑">
4
      <Form ref="categoryForm" :model="editCategory" :rules="editValidate" :label-width="100">
5
          <input type="hidden" v-model="editCategory.id" />
6
          <FormItem label="分类名称" prop="name">
7
              <Input v-model="editCategory.name" placeholder="分类名称..." />
8
          </FormItem>
9
      </Form>
10
      <div slot="footer">
11
          <Button @click="showModal=false">取消</Button>
12
          <Button type="primary" @click="saveCategory">保存</Button>
13
      </div>
14
    </Modal> 

以下是分类编辑的代码,值得注意的是:

vue是支持双向绑定的,如果编辑对象是既显示在Table中,又可以被Form元素修改,则会产生联动问题,即使最终放弃了Form中的变更,也会导致Table中的数据发生变化,因此需要克隆一份数据副本进行修改。

代码语言:javascript
复制
export default {
2
  name:'categories',
3
  data(){
4
    return {
5
      ......
6
      showModal: false,
7
      editCategory:{},
8
      editValidate:{
9
        name:[{required:true, message:'请填写分类名称', trigger:'blur'}],
10
      }
11
    }
12
  },
13
  methods:{
14
    ......
15
    saveCategory(){     //保存编辑信息
16
      this.$refs['categoryForm'].validate( valid=>{
17
        if(valid){
18
          this.axios.post('/api/admin/categories', this.editCategory).then(()=>{
19
            this.editCategory = {};
20
            this.showModal = false;
21
            this.loadCategories();
22
          });
23
        }
24
      });
25
    },
26
    showEdit(item){ //弹出编辑框并传入编辑数据
27
      if(item){
28
        this.editCategory = JSON.parse(JSON.stringify(item)); //克隆副本再做绑定
29
      }else{
30
        this.editCategory = {};
31
      }
32
      this.showModal = true;
33
    }
34
  }
35
}

4 客户端权限:为路由设置拦截器

为了避免未登陆用户能访问后台页面,我们需要为后台路由设置守卫(拦截器)。利用router中的beforeEach事件钩子,我们可以添加守卫。

(1)在程序入口router/index.js中添加路由钩子

代码语言:javascript
复制
import UserInfo from '@/js/UserInfo.js'
2
const userInfo = new UserInfo()
3
......
4
//设置路由拦截
5
router.beforeEach((to, from, next) => {
6
  if (to.meta.anonymous) {  // 判断该路由是否允许匿名访问
7
    next();
8
  }
9
  else {
10
    if (userInfo.isLogin()) {  // 检查是否已登录,已登录继续
11
      next();
12
    }
13
    else {
14
      next({
15
          path: '/login',
16
          query: {redirect: to.fullPath}  // 将跳转的路由path作为参数,保留被拦截路径URL
17
      })
18
    }      
19
  }
20
});

(2)在路由设置router.js中,允许匿名访问的路由项(比如 "/login"),添加meta自定义属性标识(比如"anonymous:true")

代码语言:javascript
复制
 const routes = [
2
    ......
3
    {
4
      path:'/login',
5
      name:'login',
6
      component:Login,
7
      meta:{
8
        anonymous:true      //添加标识符,允许匿名
9
      }
10
    }
11
  ]

附:解决eslint语法报错“Parsing error: x-invalid-end-tag”问题。

问题原因:vue将标签渲染为原生html标签时,由于这些标签是自闭合的,所以有end标签会报错。

解决办法:在“.eslintrc.js” 配置文件的rules配置节中添加“'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }]”

代码语言:javascript
复制
module.exports = {
2
  ......
3
  rules: {
4
    ......
5
    'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }] 
6
  },
7
}
8
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
项目管理
CODING 项目管理(CODING Project Management,CODING-PM)工具包含迭代管理、需求管理、任务管理、缺陷管理、文件/wiki 等功能,适用于研发团队进行项目管理或敏捷开发实践。结合敏捷研发理念,帮助您对产品进行迭代规划,让每个迭代中的需求、任务、缺陷无障碍沟通流转, 让项目开发过程风险可控,达到可持续性快速迭代。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档