当前位置: 首页 > news >正文

vue3使用tsx渲染复杂逻辑的表单

前置

目前的应用场景是:检查项目是树结构,有的项目还需要动态显示对应的子集
项目用的是uniapp+vue3+ts+vite生成的app

tsx模版

统一渲染入口

<script lang="ts">import uniForms from '@dcloudio/uni-ui/lib/uni-forms/uni-forms.vue'import uniFormsItem from '@dcloudio/uni-ui/lib/uni-forms-item/uni-forms-item.vue'import uniDataCheckbox from '@dcloudio/uni-ui/lib/uni-data-checkbox/uni-data-checkbox.vue'import uniEasyinput from '@dcloudio/uni-ui/lib/uni-easyinput/uni-easyinput.vue'
export default {components:{uniForms, uniFormsItem,uniEasyinput,uniDataCheckbox},props: {params: {type: Object,},render: {type: Function,},},render() {return this.render(this.params)},
}
</script>
<style lang="scss" scope>// .sele-inp{// 	gap: 20px;// }.cus-column{flex-direction: column;:deep(.checklist-group){gap: 20upx;flex-direction: column!important;}}.renderForm{background: #fff;padding: 20upx;box-sizing: border-box;// margin-top: 40upx;}:deep(.uni-forms-item__label){color: rgba(0, 0, 0, 0.85);}
</style>

动态解析tsx

tsx中用到的组件需要再,统一入口去引入,名字需要保持一致,目前渲染的表单类型,之有两个,input和redio,可根据自己的业务自行扩展

<script setup lang="tsx">import uniDataCheckbox from '@dcloudio/uni-ui/lib/uni-data-checkbox/uni-data-checkbox.vue'import { h, resolveComponent } from 'vue'// import uniForms from '@dcloudio/uni-ui/lib/uni-forms/uni-forms.vue'// import uniFormsItem from '@dcloudio/uni-ui/lib/uni-forms-item/uni-forms-item.vue'// import uniEasyinput from '@dcloudio/uni-ui/lib/uni-easyinput/uni-easyinput.vue'
type RenderType = {temList?: any[]
}const defalutItem = {itemType: '', itemTypeName: '', itemId: '',parentId: '', 
itemName: '', itemCode: '', itemRes: '',itemResLabel: ''
}
// 属性
const props = withDefaults(defineProps<RenderType>(),{temList: () => []
})// 表单值
const formDate = reactive({
})// 类型暂无用处
const options = {input: "uniEasyinput",radio: "uniDataCheckbox"
}
const setLabel = (val, id,key,parentItem) => {formDate[id][key] = val.detail.data.textlet item = val.detail.data.dataif(item && item.children && item.children.length > 0){formDate[parentItem.code] ? formDate[parentItem.code] : formDate[parentItem.code] = {}formDate[parentItem.code]['itemType'] = item.typeformDate[parentItem.code]['itemTypeName'] = item.typeNameformDate[parentItem.code]['itemId'] = item.idformDate[parentItem.code]['parentId'] = item.parentIdformDate[parentItem.code]['itemName'] = item.nameformDate[parentItem.code]['itemCode'] = item.code// formDate[parentItem.code]['itemResLabel']  ? formDate[parentItem.code]['itemResLabel'] : ''// formDate[parentItem.code]['itemRes'] ? '' : formDate[parentItem.code]['itemRes'] = ''}else {delete formDate[parentItem.code]}
}
const renderFormRef = ref()
const initDefaultItemForm = (item) => {formDate[item.id] ? formDate[item.id] : formDate[item.id] = {}formDate[item.id]['itemType'] = item.typeformDate[item.id]['itemTypeName'] = item.typeNameformDate[item.id]['itemId'] = item.idformDate[item.id]['parentId'] = item.parentIdformDate[item.id]['itemName'] = item.nameformDate[item.id]['itemCode'] = item.codeformDate[item.id]['itemResLabel']  ? formDate[item.id]['itemResLabel'] : ''formDate[item.id]['itemRes'] ? '' : formDate[item.id]['itemRes'] = ''console.log('initDefaultItemForm')
}
// <view class=""> {formDate[item.id] === ss.parentId ? <view class="theme theme-flex sele-inp"><text>{ ss.name }</text><uniEasyinput v-model={formDate[ss.id]}></uniEasyinput> </view>: '' }</view> 
const typeProcessor = (type?: string, item?: any, node?: any[]) => {if(type === 'input'){return <uniFormsItem  label={item.name} name={"[" + item.id + ", itemRes ]"}><uniEasyinput v-model={formDate[item.id]['itemRes']} placeholder={'请输入'+item.name}></uniEasyinput></uniFormsItem>}else if(type === 'radio'){const list = [] as any[]// let node = []if(item.children && item.children.length > 0){item.children.forEach((it:any) => {list.push({text: it.name, value: it.code, 'data': it})if(it.children && it.children.length > 0){it.children.forEach((ss:any) => {// 删除对应的值// delete formDate[ss.id]node!.push(ss)})}})}console.log('list',list)return [<view class={node && node.length > 0 ? '' : ''}><uniFormsItem  label={item.name} name={"[" + item.id + ", itemRes ]"}><uniDataCheckbox class={item.children.length > 3 ? '' : ''} v-model={formDate[item.id]['itemRes']} localdata={list} placeholder={'请选择'+item.name} onChange={(val) => setLabel(val, item.id, 'itemResLabel',item)}></uniDataCheckbox></uniFormsItem>{node!.map(no => {let parent_code  = nulltry{// 匹配父级codelet codes = no.code.split('_');codes = [...codes.slice(0, -1)]parent_code = codes.join('_')}catch(e){}formDate[item.id]['itemRes'] === parent_code ? (initDefaultItemForm(no)) : delete formDate[no.id]return [formDate[item.id]['itemRes'] === parent_code ?<uniFormsItem  label={no.name} name={"[" + no.id + ", itemRes ]"}><uniEasyinput v-model={formDate[no.id]['itemRes']} placeholder={'请输入'+ no.name}></uniEasyinput> </uniFormsItem>: '']})}</view>]}
}const renderFn = (formDate: any) => {console.log('formDate', formDate)return [<uniForms class="renderForm" label-width={100} modelValue={formDate} ref={renderFormRef}>{props.temList.map((item) => {initDefaultItemForm(item)let node = [] as any[]return  [<view>{typeProcessor(item.renderType, item, node)}</view>]})}</uniForms>]
}
const submit = () => {// reanderTemplateRefconsole.log(formDate)console.log(renderFormRef.value)
}
defineExpose({submit,formDate
})
</script><template><jsxRender :params="formDate" :render="renderFn" />
</template><style lang="scss" scoped>
.jsx-render {color: #41B883;
}
// .sele-inp{
// 	gap: 20px;
// }
</style>

案例

使用

<template><view class="re-box"><view v-for="(item ,index) in props.tagLists"><view class="box-top"><uni-section class="mb-10" :title="item.typeName" type="line" titleFontSize="20px"></uni-section></view><ReanderTemplate :temList="item.items"  ref="reanderTemplateRef" :key="index"/><!-- 	<uni-forms-item label="医生建议" ><uni-easyinput type="textarea" v-model="'expandParamMap['+item.type +'][docAdvice]'" placeholder="请输入医生建议" /></uni-forms-item> --><view style="padding: 10px;box-sizing: border-box;padding-top: 0;"><uni-forms-item label="医生建议"><uni-easyinput type="textarea"  v-model="expandParamMap[item.type]['docAdvice']"  placeholder="请输入医生建议" /></uni-forms-item></view></view><view style="padding: 10px;box-sizing: border-box;padding-top: 0;"><uni-forms-item label="签名"><view class="signature" v-if="signatureUrl"><image class="signatureImg" :src=" imgUrlPreFix + signatureUrl" /></view><wd-button plain hairline v-else @click="$tab.navigateTo(`/pages/signature/index`)">点击签名</wd-button></uni-forms-item> </view></view>
</template><script setup lang="ts" name="RenderBox">import { getCurrentInstance, ref } from 'vue'import { useToast } from 'wot-design-uni'import useUpload from '@/hooks/upload'import { upload } from '@/api/system/uploadService'import ReanderTemplate from '@/components/reanderTemplate/index.vue'import { examineFinish } from '@/api/app/speExamineTypeService'import { onLoad } from '@dcloudio/uni-app'const imgUrlPreFix = import.meta.env.VITE_APP_GATEWAY + '/file';const proxy = getCurrentInstance().proxytype EmitType = {(e: 'saveFallback') :void}const signatureUrl = ref()const toast = useToast()const reanderTemplateRef = ref()const emits = defineEmits<EmitType>()const itemAll = inject('itemAll')const expandParamMap = ref<any>({})const props = withDefaults(defineProps<{tagLists?: any[], formDataObj?: any[]}>(),{tagLists: () => [],formDataObj: () => []})watchEffect(() => {props.tagLists.forEach((item) => {expandParamMap.value[item.type]  = {itemType: item.type, passed: true, docAdvice: ''}})if(props.formDataObj && props.formDataObj.length > 0){nextTick(() => {for(let i=0; i < reanderTemplateRef.value.length; i++){let item = reanderTemplateRef.value[i]Object.assign(item.formDate,props.formDataObj[i])console.log('item.formDate',item.formDate)}})}})const submit = (params: any, url: string) => {proxy.$pop.showConfirm('','确认保存数据吗',true).then((res: any) => {console.log(res)if(res.confirm){submitFun(params, url)}})}const submitFun = (params: any) => {let itemResList = [] as ExamineTypeParams[]reanderTemplateRef.value.forEach((item: any) => {console.log('item.formDate',item.formDate)itemResList = itemResList.concat(Object.values(item.formDate) as ExamineTypeParams[])})let saveData = {signUrl: signatureUrl.value,expandParamMap: expandParamMap.value,infoId: params.infoId as string,itemResList: itemResList,itemAll: itemAll.value as SpeExamineInfoDocScanCodeDto[]}console.log('saveData',saveData)uni.showLoading({mask: true,title: '保存中...'});examineFinish(saveData).then(res => {console.log(res)proxy?.$pop.toast("保存成功")emits('saveFallback')}).finally(() => (uni.hideLoading()))}const signatureFun = (val: string) => {uni.showLoading({mask: true,title: '签名上传中...'})let ss =new Date().getTime() + '.jpg'let pa = {fileName: ss, localPath: val}useUpload(pa).then((res:any)=>{signatureUrl.value = res.data.fileUrlPath}).finally(() => (uni.hideLoading()))}onLoad(() => {uni.$on('signature', signatureFun)})onUnmounted(() => {uni.$off('signature', signatureFun)})defineExpose({submit})
</script><style lang="scss" scoped>.re-box{margin-top: 20upx;background-color: #fff;}.box-top{// padding: 20upx;font-size: 30upx;background: #fff;}.signature{width: 100px;height: 100px;.signatureImg{display: block;width: 100%;height: 100%;}}
</style>

数据结构及案例效果图

整理完后,后面贴

相关文章:

vue3使用tsx渲染复杂逻辑的表单

前置 目前的应用场景是&#xff1a;检查项目是树结构&#xff0c;有的项目还需要动态显示对应的子集 项目用的是uniappvue3tsvite生成的app tsx模版 统一渲染入口 <script lang"ts">import uniForms from dcloudio/uni-ui/lib/uni-forms/uni-forms.vueimport…...

python助力WRF自动化运行

对大部分人而言&#xff0c;特别是新用户&#xff0c;WRF模式的安装繁琐且不必要&#xff0c;可以作为后续进阶掌握的技能&#xff0c;本学习跳过繁琐的安装步骤&#xff0c;直接聚焦模式的运行部分&#xff0c;通过短平快的教学&#xff0c;快速掌握模式运行。进一步将python语…...

Windows 下 Postgres 安装 TimescaleDB 插件

Windows 下 Postgres 安装 TimescaleDB 插件 一、准备工作 安装 PostgreSQL&#xff1a;首先确保你已经在 Windows 系统中成功安装了 PostgreSQL 数据库。可以从 PostgreSQL 官方网站下载适合你系统的安装包&#xff0c;并按照安装向导进行安装。安装过程中&#xff0c;记住设…...

【Vim Masterclass 笔记21】S09L39:Vim 设置与 vimrc 文件的用法示例(二)

文章目录 S09L39 Vim Settings and the Vimrc File - Part 21 Vim 的配色方案与 color 命令2 map 命令3 示例&#xff1a;用 map 命令快速生成 HTML 代码片段4 Vim 中的 Leader 键5 用 mkvimrc 命令自动生成配置文件 写在前面 本篇为 Vim 自定义配置的第二部分。当中的每个知识…...

【Docker】Supervisor 实现单容器运行多服务进程

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…...

【网络协议】【http】【https】ECDHE-TLS1.2

【网络协议】【http】【https】ECDHE-TLS1.2 ECDHE算法 1.客户端和服务器端事先确定好使用哪种椭圆曲线&#xff0c;和曲线上的基点G&#xff0c;这两个参数都是公开的&#xff0c; 双方各自随机生成一个随机数作为私钥d&#xff0c;并与基点 G相乘得到公钥Q(QdG)&#xff0c…...

(十五)WebGL中gl.texImage2D函数使用详解

在 WebGL 中&#xff0c;gl.texImage2D 是一个非常关键的函数&#xff0c;用于将图像数据上传到 WebGL 上下文中并作为纹理对象的一部分。它允许你将图像、视频、画布等作为纹理源。理解如何使用 gl.texImage2D 是在 WebGL 中处理纹理的核心之一。 文章目录 gl.texImage2D 的基…...

CSS 颜色

所有浏览器都支持的颜色名 所有现代浏览器均支持以下 140 种颜色名称&#xff08;单击颜色名称或十六进制值&#xff0c;可查看将以该颜色为背景颜色以及不同的文本颜色&#xff09;&#xff1a; 颜色名十六进制颜色值颜色AliceBlue#F0F8FFAntiqueWhite#FAEBD7Aqua#00FFFFAqu…...

C#,入门教程(03)——Visual Studio 2022编写彩色Hello World与动画效果

C#&#xff0c;入门教程(01)—— Visual Studio 2022 免费安装的详细图文与动画教程https://blog.csdn.net/beijinghorn/article/details/123350910 C#&#xff0c;入门教程(02)—— Visual Studio 2022开发环境搭建图文教程https://blog.csdn.net/beijinghorn/article/detail…...

杀死安装 CentOS-7-x86_64-DVD-1908

使用 VMware 安装 CentOS-7-x86_64-DVD-1908 CentOS是 reahat 的 免费版本&#xff0c;有了ubutun &#xff0c;为什么还要使用 CentOS呢&#xff1f; 在linux 服务器实际开发中&#xff0c;大家都用的CentOS&#xff0c;因为两个原因&#xff0c;一个是免费&#xff0c;第二是…...

55.【5】BUUCTF WEB NCTF2019 sqli

进入靶场 输入admin 123 过滤的这么严格&#xff1f;&#xff1f;&#xff1f; 过滤很严格&#xff0c;此时要么爆破&#xff0c;要么扫描 直接扫描&#xff0c;得到robots.txt 访问后又得到hint.txt 继续访问 图片内容如下 $black_list "/limit|by|substr|mid|,|admi…...

LeetCode 题目 2545. 根据第 K 场考试的分数排序

在本篇文章中&#xff0c;我们将探讨如何根据第 K 场考试的分数对学生进行排序。这个问题是 LeetCode 上的一个中等难度问题&#xff0c;涉及到排序算法和自定义比较函数的使用。 问题描述 解题思路 理解问题 首先&#xff0c;我们需要理解问题的核心&#xff1a;根据第 K 场…...

算法随笔_12:最短无序子数组

上一篇: 算法随笔_11: 字符串的排列-CSDN博客 题目描述如下: 给你一个整数数组 nums &#xff0c;你需要找出一个 连续子数组 &#xff0c;如果对这个子数组进行升序排序&#xff0c;那么整个数组都会变为升序排序。请你找出符合题意的最短子数组&#xff0c;并输出它的长度。…...

计算机毕业设计PySpark+Hadoop+Hive机票预测 飞机票航班数据分析可视化大屏 航班预测系统 机票爬虫 飞机票推荐系统 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Linux-C/C++--初探linux应用编程概念

对于大多数首次接触 Linux 应用编程的读者来说&#xff0c;可能对应用编程&#xff08;也可称为系统编程&#xff09;这个概念并不 太了解&#xff0c;所以在正式学习 Linux 应用编程之前&#xff0c;笔者有必要向大家介绍这些简单基本的概念&#xff0c;从整体上认识 到应用编…...

用sklearn运行分类模型,选择AUC最高的模型保存模型权重并绘制AUCROC曲线(以逻辑回归、随机森林、梯度提升、MLP为例)

诸神缄默不语-个人CSDN博文目录 文章目录 1. 导入包2. 初始化分类模型3. 训练、测试模型&#xff0c;绘图&#xff0c;保存指标 1. 导入包 from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier, GradientBoostingClass…...

动手学大数据-3社区开源实践

目录 数据库概览&#xff1a; MaxComput&#xff1a; HAWQ&#xff1a; Hologres&#xff1a; TiDB&#xff1a; Spark&#xff1a; ClickHouse&#xff1a; Apache Calcite 概览 Calcite RBO HepPlanner 优化规则&#xff08;Rule&#xff09; 内置有100优化规则 …...

使用Pydantic驾驭大模型

本文介绍Pydantic 库&#xff0c;首先介绍其概念及优势&#xff0c;然后通过基本示例展示如何进行数据验证。后面通过多个示例解释如何在LangChain中通过Pydantic进行数据验证&#xff0c;保证与大模型进行交互过程中数据准确性&#xff0c;并显示清晰的数验证错误信息。 Pydan…...

【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发之常见布局

目录 1 -> 自适应布局 1.1 -> 线性布局 1.1.1 -> 线性布局的排列 1.1.2 -> 自适应拉伸 1.1.3 -> 自适应缩放 1.1.4 -> 定位能力 1.1.5 -> 自适应延伸 1.2 -> 层叠布局 1.2.1 -> 对齐方式 1.2.2 -> Z序控制 1.3 -> 弹性布局 1.3.1…...

【论文投稿】Python 网络爬虫:探秘网页数据抓取的奇妙世界

目录 前言 一、Python—— 网络爬虫的绝佳拍档 二、网络爬虫基础&#xff1a;揭开神秘面纱 &#xff08;一&#xff09;工作原理&#xff1a;步步为营的数据狩猎 &#xff08;二&#xff09;分类&#xff1a;各显神通的爬虫家族 三、Python 网络爬虫核心库深度剖析 &…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...