Vue组件定制——动态查询规则生成组件

1. 动态查询规则

动态查询规则,大致如下图所示。是可以按照用户的自定义进行组织查询语句的一种复杂组件,大致可以实现SQL查询的where条件,下面是摘自mongodb的某一软件。
在这里插入图片描述

2.组件构建思路

按照规则组件的组织形式,可以把其视为一棵树,有树干和树叶,这样看起来就不难了。

2.1 组件html

这里采用ElementUI构建,因此可以方便的组合各类ui控件来进行构建需要的界面。
当然该组件既然被看作树,因此其也是个递归组件,因此还涉及到自己调用自己。

<template>
  <div class="rules-group-container tree box">
    <el-card class="box-card" style="margin-top: 10px">
      <el-main style="padding: 10px">
        <el-row>
          <el-row class="child">
            <el-radio-group v-model="object.rules" size="small">
              <el-radio-button label="and" value="and"></el-radio-button>
              <el-radio-button label="or" value="or"></el-radio-button>
            </el-radio-group>
            <el-button
              size="small"
              style="float: right; margin-left: 10px"
              type="primary"
              icon="el-icon-circle-plus-outline"
              @click="object.list.push({ rules: 'and', type: 'group', list: [{ types: '', site: '', symbol: '', rules: '', type: 'condition' }] })"
              >新增分组</el-button
            >
            <el-button
              size="small"
              style="float: right; margin-left: 10px"
              type="primary"
              icon="el-icon-circle-plus-outline"
              @click="object.list.push({ types: '', site: '', symbol: '', rules: '', type: 'condition' })"
              >新增条件</el-button
            >
          </el-row>

          <template v-for="(item, index) in object.list">
            <el-row :key="'condition' + index" class="child" v-if="item.type == 'condition'">
              <el-select v-model="item.types" size="small" style="width: 120px" placeholder="请选择">
                <el-option label="无" value="无"> </el-option>
                <el-option label="19位编码" value="19位编码"> </el-option>
                <el-option label="内部编码" value="内部编码"> </el-option>
              </el-select>
              <!-- multiple  -->
              <el-select v-model="item.site" size="small" placeholder="请选择位置" style="margin-left: 10px; width: 150px">
                <el-option label="1" value="1"> </el-option>
                <el-option label="2" value="2"> </el-option>
                <el-option label="3" value="3"> </el-option>
                <el-option label="4" value="4"> </el-option>
                <el-option label="5" value="5"> </el-option>
                <el-option label="6" value="6"> </el-option>
                <el-option label="7" value="7"> </el-option>
                <el-option label="8" value="8"> </el-option>
                <el-option label="9" value="9"> </el-option>
              </el-select>
              <el-select v-model="item.symbol" size="small" placeholder="请选择" style="margin-left: 10px; width: 100px">
                <el-option label="等于" value="=="> </el-option>
                <el-option label="大于" value=">"> </el-option>
                <el-option label="小于" value="<"> </el-option>
                <el-option label="不等于" value="!="> </el-option>
                <el-option label="包含" value="包含"> </el-option>
                <el-option label="不包含" value="不包含"> </el-option>
                <el-option label="以...开头" value="以...开头"> </el-option>
                <el-option label="不以...开头" value="不以...开头"> </el-option>
              </el-select>
              <el-input v-model="item.rules" size="small" style="width: 200px; margin-left: 10px" placeholder="请输入规则"></el-input>
              <el-button @click="object.list.splice(index, 1)" size="small">删除</el-button>
            </el-row>
            <el-row v-if="item.type == 'group' && item.list.length > 0" :key="'group' + index" class="child">
              <create-rule :object="item"></create-rule>
            </el-row>
          </template>
        </el-row>
      </el-main>
    </el-card>
  </div>
</template>

2.2 设置连线

<style scoped>
.box {
  width: 100%;
}
/* 只需要左边边框线 */
.child {
  width: 100%;
  position: relative;
  border: 1px solid #d9d9d9;
  border-style: none none none solid;
  padding: 10px 0;
  padding-left: 12px;
}
/* 设置一个伪元素宽2px 高50% 用于遮挡多余的左边框线 */
.child::before {
  display: block;
  content: '';
  position: absolute;
  background-color: white;
  width: 1px;
  height: 50%;
}
/* 设置第一个子元素的伪类定位 */
.box .child:first-child::before {
  left: -1px;
  top: 0;
}
/* 设置第二个子元素的伪类定位 */
.box .child:last-child::before {
  left: -1px;
  bottom: 0;
}
/* 设置子元素的横线,定位在高度的50% */
.box .child::after {
  top: 50%;
  left: 0;
  position: absolute;
  content: '';
  display: block;
  width: 10px;
  height: 1px;
  border: 1px solid #d9d9d9;
  border-style: solid none none none;
}
</style>

2.3 定义组件名

该组件命名为 CreateRule,定义代码很简单了。

export default {
    name: 'CreateRule',
  props: {
    object: {
      type: Object,
      default: {
        rules: 'and',
        list: [{ type: '', site: '', symbol: '', rules: '' }]
      }
    }
  },
  data() {
    return {}
  },
  }

3.使用组件

vue中使用组件只需引用并增加到组件列表中即可。

<template>
  <div class="new-rule-form">
    <CreateRule :object="object"></CreateRule>
  </div>
</template>

<script>
import CreateRule from './index.vue'
export default {
  name: 'NewRuleForm',
  components: {
    CreateRule
  },
  data() {
    return {
      object: {
        rules: 'and',
        list: [{ types: '', site: '', symbol: '', rules: '', type: 'condition' }]
      }
    }
  }
}
</script>

4.效果展示

这是截取的实际效果.

在这里插入图片描述

5.小结

在vue开发应用中,可以多参考下windows软件的某些界面,偶尔能给我们很大的灵感和启发的。
当然,也希望本文能帮助到小伙伴们。

Vue组件实现原理基于Vue的核心概念——虚拟DOM(Virtual DOM)。组件化是指将页面拆分为多个独立、可复用的组件,每个组件都有自己的模板、样式和行为。Vue通过提供组件系统来支持这种开发方式。 在Vue中,我们可以使用Vue.component()方法创建一个全局组件,或者使用components选项在一个父组件中注册子组件。 当组件被创建时,Vue会根据组件的模板生成一个虚拟DOM树。在数据变化时,Vue会对比新旧虚拟DOM树的差异,并通过最小化地修改真实DOM来更新页面。 组件的模板通常使用Vue的模板语法来描述,包括插值表达式、指令、事件绑定等。当组件被渲染时,模板中的表达式会被动态地计算和更新。 组件还可以定义自己的样式和行为。样式可以使用普通的CSS或CSS预处理器编写,并通过scoped属性限定作用域,确保样式只应用于当前组件组件之间可以通过props属性和自定义事件进行通信。props属性用于父组件向子组件传递数据,子组件可以通过props选项声明接收的数据类型和默认值。自定义事件则用于子组件向父组件发送消息,子组件可以通过$emit方法触发事件,并传递数据给父组件。 通过组件化开发,我们可以将页面拆分为多个独立的组件,使代码更加模块化、可复用和易于维护。同时,通过虚拟DOM的高效更新机制,Vue能够在数据变化时高效地更新页面,提升性能和用户体验。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值