Vue+ElementUi 基于Tree实现动态节点添加,节点自定义为输入框列
Vue+ElementUi 基于Tree实现动态节点手动添加,节点自定义为输入框列
代码
<el-steps :active="active" finish-status="success" align-center><el-step title="test1"/><el-step title="test2"/><el-step title="test3"/>
</el-steps>
<el-row style="margin-top:15px"><el-row v-if="active == 0">.....</el-row><el-row v-if="active == 1"><el-treev-if="reloadStatus"ref="tree":data="chargebackData":render-content="renderContent":render-after-expand=true:expand-on-click-node=false:default-expand-all=trueicon-class="el-icon-circle-plus-outline"class="tree-line"node-key="id"></el-tree></el-row><el-row v-if="active == 2">....</el-row>
</el-row>
<el-row style="text-align: right;"><el-button style="margin-top: 12px;" @click="next">{{this.active == 2 ? '确认' : '下一步'}}</el-button>
</el-row>
</el-row>
数据以及树节点自定义内容
<script>export default {data(){return {//步骤条 当前选择的下标(从0开始)active: 0,//步骤条第一步所需的数据stepsOneData: {},//步骤条第二步所需的数据stepsTwoData: [],//tree数据 重新加载使用reloadStatus: true,//tree数据chargebackData:[{createItemCount:0,//只针对一级节点chargebackItemId:undefined,amount: undefined,children:[]}],//步骤条的下一步是否可以通过isNext: true,}},methods:{/*步骤条点击 下一步 按钮 触发*/next() {this.dialogContentLoading = trueif(this.active == 0){//这里可以查询后端结果返回丰富this.stepsTwoData = [...]}else if(this.active == 1){//2.清除无效数据let handleData = JSON.parse(JSON.stringify(this.chargebackData))//2.1请求一级节点的数据let arr = handleData.filter(item => item.itemName != undefined || item.itemName != null || item.itemName == '')//2.2处理二级节点的数据for(let i=0; i< arr.length ; i++){arr[i].children = arr[i].children.filter(item => item.key != undefined || item.key != null || item.key == '')}this.showChargebackData = arr}else if(this.active = 2){//确认按钮触发let list = JSON.parse(JSON.stringify(this.showChargebackData))let arr = this.showChargebackDatalet data = []for(let i = 0; i < arr.length; i++){let obj = {}obj.orderId = this.form.idobj.userId = this.form.userIdobj.chargebackItemId = arr[i].chargebackItemIdobj.amount = arr[i].amountif(arr[i].children.length > 0){obj.detail = JSON.parse(JSON.stringify(arr[i].children))}data.push(obj)}console.log("data",data)this.active = 0this.stepsOneData = {}this.stepsTwoData = []this.chargebackData = [{createItemCount:0,//只针对一级节点chargebackItemId:undefined,amount: undefined,children:[]}]this.dialogContentLoading = falsethis.open = falsereturn}if (this.active++ > 1) this.active = 0;},/*tree 树节点处理@param node 当前节点对象@param data 当前节点数据对象*/renderContent(h, { node, data, store }){return (<el-row style="width:100%">{node.level == 1 ? (<el-row class="row-col-title"><el-col span={2} class="col-title"><span>扣款项:</span> </el-col><el-col span={6}><el-select placeholder="请求选择扣款项" v-model={data.itemName} onChange={(val) => this.selectChangeHandle(val,node,data)} clearable>{this.stepsTwoData.map((item,index) => {return (<el-option key={index} value={item.itemName}>{item.itemName}</el-option>)})}</el-select> </el-col><el-col span={3} class="col-title"><span>退款项总金额:</span></el-col><el-col span={6}><el-input placeholder="请输入退款项总金额" v-model={data.amount}><template slot="append">元</template> </el-input></el-col><el-col span={5} style="margin-left:20px"><el-button type="primary" onClick={() => this.addChangeHandle(node, data, true)}><i class="el-icon-circle-plus-outline"></i></el-button><el-button type="primary" onClick={() => this.reduceChangeHandle(node, data, true)}><i class="el-icon-remove-outline"></i></el-button></el-col></el-row>) : ''}{node.level != 1 ? (<el-row gutter={20}><el-col span={10}><el-input placeholder="退款项明细" v-model={data.key}/></el-col><el-col span={10}><el-input placeholder="退款项明细金额" v-model={data.value} onInput={(value) => this.computeItem(value,node)}/></el-col><el-col span={4}><el-button type="primary" onClick={() => this.addChangeHandle(node, data, false)}><i class="el-icon-circle-plus-outline"></i></el-button><el-button type="primary" onClick={() => this.reduceChangeHandle(node, data, false)}><i class="el-icon-remove-outline"></i></el-button></el-col></el-row>) : ''}</el-row>)},/*步骤条-扣除项-扣除项下拉列表选择option时触发@param val 当前选中的option key值@param node 当前节点对象@param data 当前节点数据对象*/selectChangeHandle(val,node,data){if(val){//选中时if(node.level == 1){//扣除项let target = this.stepsTwoData.filter(item => item.itemName == val)[0]//以下参数不会导致tree自动重新渲染tree组件,但数据是存在的,如果需要重新渲染,手动调用 treeRefresh()data.itemName = target.itemNamedata.chargebackItemId = target.id//添加一个子节点(一个一级节点一次添加)if(data.createItemCount == 0){let children = {key:undefined,value: undefined}data.createItemCount += 1data.children.push(children)this.treeRefresh()}}}else{//清除选择时//清空扣款项的扣款明细列表data.createItemCount = 0data.amount = undefineddata.children = []this.treeRefresh()}},/*点击添加按钮触发@param node 当前节点对象@param data 当前节点数据对象@param isOneLevel 当前节点是否为一级节点*/addChangeHandle(node, data, isOneLevel){if(isOneLevel){//一级节点的添加let obj = {createItemCount:0,//只针对一级节点chargebackItemId:undefined,amount: undefined,children:[]}this.chargebackData.push(obj)this.treeRefresh()}else{//非一级节点(二级)的添加let children = {key:undefined,value: undefined}node.parent.data.children.push(children)this.treeRefresh()}},/*点击减号按钮触发@param node 当前节点对象@param data 当前节点数据对象@param isOneLevel 当前节点是否为一级节点*/reduceChangeHandle(node, data, isOneLevel){if(isOneLevel){//一级节点if(this.chargebackData.length == 1){this.$modal.msgError("扣款项已达最低条数限制,无法删除");return}let delIndex = this.chargebackData.indexOf(data)if(delIndex > -1){this.chargebackData.splice(delIndex, 1)this.treeRefresh()}}else{//非一级(二级)节点let arr = node.parent.data.childrenif(arr.length == 1){this.$modal.msgError("当前扣款项明细已达最低条数限制,无法删除");return}let delIndex = arr.indexOf(data)if(delIndex > -1){arr.splice(delIndex, 1)this.treeRefresh()}}},//输入扣款项明细时计算金额并自动填充扣款项总金额中computeItem(value,node){let val = Number(value)if(isNaN(val)){this.isNext = falsethis.$modal.msgError("金额格式错误");return}this.isNext = true//计算价格let parentData = node.parent.datalet sonData = JSON.parse(JSON.stringify(parentData.children))let sum = 0for(let i = 0; i < sonData.length; i++){//排除值为空的情况if(sonData[i].value){sum += Number(sonData[i].value)}}parentData.amount = sum + ''},/*扣除项树节点手动刷新*/treeRefresh(){this.reloadStatus = false;this.$nextTick(() => {this.reloadStatus = true;})}}}
</script>
相关样式:
<style lang="scss">.tree-line{.el-tree-node__content {display: -webkit-box;display: -ms-flexbox;display: flex;-webkit-box-align: center;-ms-flex-align: center;align-items: center;height: 50px;cursor: default;}.row-col-title{display: flex;}.row-col-title > .el-col {margin: auto 0;}.col-title{text-align: right;}/* 以下全是分支相关样式 start */.el-tree-node {position: relative;padding-left: 16px; /*缩进量*/}.el-tree-node__children {padding-left: 16px; /*缩进量*/}/* 竖线 */.el-tree-node::before {content: "";height: 100%;width: 1px;position: absolute;left: -3px;top: -12px;border-width: 1px;border-left: 1px solid #52627C;}/* 当前层最后一个节点的竖线高度固定 */.el-tree-node:last-child::before {height: 38px; /* 可以自己调节到合适数值 */}/* 横线 */.el-tree-node::after {content: "";width: 45px;height: 20px;position: absolute;left: -3px;top: 25px;border-width: 1px;border-top: 1px solid #52627C;}/* 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了 */& > .el-tree-node::after {border-top: none;}& > .el-tree-node::before {border-left: none;}/* 展开关闭的icon */.el-tree-node__expand-icon{font-size: 16px;/* 叶子节点(无子节点) */&.is-leaf{color: transparent;/*display: none;*/ /* 也可以去掉 */}}/* 以上全是分支相关样式 end */}</style>
参考:
vue 为element树形组件el-tree添加虚线,指示线
vue中el-tree增加节点后重新刷新