鸿蒙OSUniApp 实现的表单验证与提交功能#三方框架 #Uniapp
UniApp 实现的表单验证与提交功能
前言
在移动端应用开发中,表单是用户与应用交互的重要媒介。一个好的表单不仅布局合理、使用方便,还应该具备完善的验证与提交功能,以确保用户输入的数据准确无误。本文将分享如何在 UniApp 中实现表单验证与提交功能,帮助你构建更加健壮的表单系统。
作为一个经常与表单打交道的开发者,我发现很多初学者往往忽视了表单验证的重要性,或者实现方式不够优雅。通过本文,希望能为你提供一些关于 UniApp 表单处理的实用技巧和最佳实践。
为什么需要表单验证?
想象一下,如果没有表单验证,用户可能会提交不完整或格式错误的数据:
- 手机号码少输一位或输入了字母
- 密码太简单,不符合安全要求
- 重要字段被遗漏
- 日期格式错误
- 上传的图片尺寸过大或格式不支持
这些问题不仅会导致后端数据处理错误,还会影响用户体验。因此,前端表单验证显得尤为重要。
UniApp 表单验证的实现方式
在 UniApp 中,有多种方式可以实现表单验证:
- 使用原生方法自行实现
- 使用第三方验证库(如 async-validator)
- 结合 uView 等 UI 框架使用内置验证功能
下面我们主要讨论前两种方式的实现。
方式一:自行实现表单验证
自行实现的优点是灵活、无需引入额外依赖,但需要自己编写各种验证规则和处理逻辑。
基本思路:
- 定义表单数据模型
- 编写验证规则函数
- 在提交前调用验证函数
- 根据验证结果决定是否提交
让我们看一个简单的注册表单验证示例:
export default {data() {return {// 表单数据form: {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false},// 错误信息errors: {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: ''}}},methods: {// 验证用户名validateUsername() {if (!this.form.username) {this.errors.username = '用户名不能为空';return false;}if (this.form.username.length < 3 || this.form.username.length > 20) {this.errors.username = '用户名长度应为3-20个字符';return false;}this.errors.username = '';return true;},// 验证密码validatePassword() {if (!this.form.password) {this.errors.password = '密码不能为空';return false;}if (this.form.password.length < 6) {this.errors.password = '密码长度不能少于6个字符';return false;}// 包含数字和字母的正则表达式const passwordPattern = /^(?=.*[0-9])(?=.*[a-zA-Z]).{6,}$/;if (!passwordPattern.test(this.form.password)) {this.errors.password = '密码必须包含数字和字母';return false;}this.errors.password = '';return true;},// 验证确认密码validateConfirmPassword() {if (!this.form.confirmPassword) {this.errors.confirmPassword = '请确认密码';return false;}if (this.form.confirmPassword !== this.form.password) {this.errors.confirmPassword = '两次输入的密码不一致';return false;}this.errors.confirmPassword = '';return true;},// 验证手机号validateMobile() {if (!this.form.mobile) {this.errors.mobile = '手机号不能为空';return false;}// 中国大陆手机号正则表达式const mobilePattern = /^1[3-9]\d{9}$/;if (!mobilePattern.test(this.form.mobile)) {this.errors.mobile = '请输入有效的手机号码';return false;}this.errors.mobile = '';return true;},// 验证邮箱validateEmail() {if (!this.form.email) {this.errors.email = '邮箱不能为空';return false;}// 邮箱正则表达式const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;if (!emailPattern.test(this.form.email)) {this.errors.email = '请输入有效的邮箱地址';return false;}this.errors.email = '';return true;},// 验证用户协议validateAgree() {if (!this.form.agree) {this.errors.agree = '请同意用户协议';return false;}this.errors.agree = '';return true;},// 验证所有字段validateForm() {const usernameValid = this.validateUsername();const passwordValid = this.validatePassword();const confirmPasswordValid = this.validateConfirmPassword();const mobileValid = this.validateMobile();const emailValid = this.validateEmail();const agreeValid = this.validateAgree();return usernameValid && passwordValid && confirmPasswordValid && mobileValid && emailValid && agreeValid;},// 提交表单submitForm() {// 先清空所有错误信息for (let key in this.errors) {this.errors[key] = '';}// 验证表单if (!this.validateForm()) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 验证通过,可以进行提交操作uni.showLoading({title: '提交中...'});// 模拟提交请求setTimeout(() => {uni.hideLoading();uni.showToast({title: '注册成功',icon: 'success'});// 重置表单或跳转页面// this.resetForm();// uni.navigateTo({ url: '/pages/login/login' });}, 1500);},// 重置表单resetForm() {this.form = {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false};for (let key in this.errors) {this.errors[key] = '';}}}
}
对应的模板部分可以这样编写:
<template><view class="register-form"><view class="form-item"><text class="label">用户名</text><input class="input" v-model="form.username" placeholder="请输入用户名" @blur="validateUsername" /><text v-if="errors.username" class="error-tip">{{ errors.username }}</text></view><view class="form-item"><text class="label">密码</text><input class="input" v-model="form.password" type="password" placeholder="请输入密码" @blur="validatePassword" /><text v-if="errors.password" class="error-tip">{{ errors.password }}</text></view><view class="form-item"><text class="label">确认密码</text><input class="input" v-model="form.confirmPassword" type="password" placeholder="请再次输入密码" @blur="validateConfirmPassword" /><text v-if="errors.confirmPassword" class="error-tip">{{ errors.confirmPassword }}</text></view><view class="form-item"><text class="label">手机号</text><input class="input" v-model="form.mobile" type="number" placeholder="请输入手机号" @blur="validateMobile" /><text v-if="errors.mobile" class="error-tip">{{ errors.mobile }}</text></view><view class="form-item"><text class="label">邮箱</text><input class="input" v-model="form.email" placeholder="请输入邮箱" @blur="validateEmail" /><text v-if="errors.email" class="error-tip">{{ errors.email }}</text></view><view class="form-item checkbox-item"><checkbox v-model="form.agree" /><text class="agreement-text" @click="form.agree = !form.agree">我已阅读并同意《用户协议》</text><text v-if="errors.agree" class="error-tip">{{ errors.agree }}</text></view><button class="submit-btn" type="primary" @click="submitForm">立即注册</button></view>
</template>
并添加一些基本样式:
<style scoped>
.register-form {padding: 30rpx;
}.form-item {margin-bottom: 40rpx;position: relative;
}.label {display: block;margin-bottom: 10rpx;font-size: 28rpx;color: #333;
}.input {width: 100%;height: 80rpx;border: 1rpx solid #dcdfe6;border-radius: 8rpx;padding: 0 20rpx;box-sizing: border-box;font-size: 28rpx;
}.error-tip {position: absolute;left: 0;bottom: -36rpx;font-size: 24rpx;color: #f56c6c;
}.checkbox-item {display: flex;align-items: center;
}.agreement-text {font-size: 26rpx;margin-left: 10rpx;
}.submit-btn {margin-top: 60rpx;
}
</style>
方式二:使用 async-validator 库
对于复杂的验证需求,使用成熟的验证库会更加便捷。async-validator 是一个流行的表单验证库,支持丰富的验证规则和自定义验证功能。
首先,安装依赖:
npm install async-validator --save
然后,在组件中使用:
import Schema from 'async-validator';export default {data() {return {// 表单数据form: {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false},// 错误信息errors: {}}},computed: {// 定义验证规则rules() {return {username: [{ required: true, message: '用户名不能为空' },{ min: 3, max: 20, message: '用户名长度应为3-20个字符' }],password: [{ required: true, message: '密码不能为空' },{ min: 6, message: '密码长度不能少于6个字符' },{ pattern: /^(?=.*[0-9])(?=.*[a-zA-Z]).{6,}$/, message: '密码必须包含数字和字母' }],confirmPassword: [{ required: true, message: '请确认密码' },{ validator: (rule, value, callback) => {if (value !== this.form.password) {callback(new Error('两次输入的密码不一致'));} else {callback();}} }],mobile: [{ required: true, message: '手机号不能为空' },{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号码' }],email: [{ required: true, message: '邮箱不能为空' },{ type: 'email', message: '请输入有效的邮箱地址' }],agree: [{ validator: (rule, value, callback) => {if (!value) {callback(new Error('请同意用户协议'));} else {callback();}} }]};}},methods: {// 验证单个字段validateField(field) {const descriptor = {};descriptor[field] = this.rules[field];const validator = new Schema(descriptor);const source = {};source[field] = this.form[field];validator.validate(source, (errors) => {if (errors) {// 有错误this.$set(this.errors, field, errors[0].message);} else {// 没有错误this.$set(this.errors, field, '');}});},// 验证所有字段validateForm() {return new Promise((resolve, reject) => {const validator = new Schema(this.rules);validator.validate(this.form, (errors) => {if (errors) {// 有错误const errorObj = {};errors.forEach(error => {errorObj[error.field] = error.message;});this.errors = errorObj;resolve(false);} else {// 验证通过this.errors = {};resolve(true);}});});},// 提交表单async submitForm() {const valid = await this.validateForm();if (!valid) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 验证通过,可以进行提交操作uni.showLoading({title: '提交中...'});// 模拟提交请求setTimeout(() => {uni.hideLoading();uni.showToast({title: '注册成功',icon: 'success'});// 重置表单或跳转页面// this.resetForm();// uni.navigateTo({ url: '/pages/login/login' });}, 1500);},// 重置表单resetForm() {this.form = {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false};this.errors = {};}}
}
模板部分可以与前面的例子类似,只需要修改验证方法的调用:
<input class="input" v-model="form.username" placeholder="请输入用户名" @blur="validateField('username')" />
表单提交功能的实现
表单验证通过后,我们需要将数据提交到服务器。在 UniApp 中,可以使用 uni.request()
方法发送网络请求。
下面是一个完整的表单提交示例:
// 提交表单
async submitForm() {const valid = await this.validateForm();if (!valid) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 显示加载提示uni.showLoading({title: '提交中...'});try {// 发送请求const res = await uni.request({url: 'https://api.example.com/register',method: 'POST',data: this.form,header: {'content-type': 'application/json'}});// 请求成功if (res.statusCode === 200 && res.data.code === 0) {uni.hideLoading();uni.showToast({title: '注册成功',icon: 'success'});// 存储登录信息uni.setStorageSync('token', res.data.data.token);uni.setStorageSync('userInfo', res.data.data.userInfo);// 跳转到首页setTimeout(() => {uni.switchTab({url: '/pages/index/index'});}, 1500);} else {throw new Error(res.data.message || '注册失败');}} catch (error) {uni.hideLoading();uni.showToast({title: error.message || '网络错误,请稍后重试',icon: 'none'});}
}
实战案例:会员信息编辑表单
下面是一个完整的会员信息编辑表单案例,综合了表单验证和提交功能:
<template><view class="profile-form"><view class="form-header"><view class="avatar-wrapper"><image class="avatar" :src="form.avatar || '/static/default-avatar.png'" @click="chooseAvatar"></image><text class="edit-hint">点击修改头像</text></view></view><view class="form-content"><view class="form-item"><text class="label">姓名</text><input class="input" v-model="form.name" placeholder="请输入您的姓名" @blur="validateField('name')" /><text v-if="errors.name" class="error-tip">{{ errors.name }}</text></view><view class="form-item"><text class="label">性别</text><view class="radio-group"><view class="radio-item" @click="form.gender = 1"><view class="radio-box" :class="{ 'checked': form.gender === 1 }"></view><text class="radio-label">男</text></view><view class="radio-item" @click="form.gender = 2"><view class="radio-box" :class="{ 'checked': form.gender === 2 }"></view><text class="radio-label">女</text></view></view></view><view class="form-item"><text class="label">手机号</text><input class="input" v-model="form.mobile" type="number" placeholder="请输入手机号" @blur="validateField('mobile')" /><text v-if="errors.mobile" class="error-tip">{{ errors.mobile }}</text></view><view class="form-item"><text class="label">邮箱</text><input class="input" v-model="form.email" placeholder="请输入邮箱" @blur="validateField('email')" /><text v-if="errors.email" class="error-tip">{{ errors.email }}</text></view><view class="form-item"><text class="label">生日</text><picker mode="date" :value="form.birthday" @change="onBirthdayChange"><view class="picker-box"><text class="picker-text">{{ form.birthday || '请选择出生日期' }}</text><text class="picker-arrow">></text></view></picker></view><view class="form-item"><text class="label">地址</text><textarea class="textarea" v-model="form.address" placeholder="请输入您的详细地址" @blur="validateField('address')" /><text v-if="errors.address" class="error-tip">{{ errors.address }}</text></view><view class="form-item"><text class="label">个人简介</text><textarea class="textarea" v-model="form.bio" placeholder="介绍一下自己吧(选填)" /></view></view><button class="submit-btn" type="primary" @click="submitForm">保存修改</button></view>
</template><script>
import Schema from 'async-validator';export default {data() {return {// 表单数据form: {avatar: '',name: '',gender: 1, // 1-男,2-女mobile: '',email: '',birthday: '',address: '',bio: ''},// 错误信息errors: {}}},computed: {// 定义验证规则rules() {return {name: [{ required: true, message: '姓名不能为空' },{ max: 20, message: '姓名长度不能超过20个字符' }],mobile: [{ required: true, message: '手机号不能为空' },{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号码' }],email: [{ required: true, message: '邮箱不能为空' },{ type: 'email', message: '请输入有效的邮箱地址' }],address: [{ required: true, message: '地址不能为空' },{ max: 100, message: '地址长度不能超过100个字符' }]};}},onLoad() {// 获取用户信息(示例数据)const userInfo = {avatar: '/static/avatar.png',name: '张三',gender: 1,mobile: '13800138000',email: 'zhangsan@example.com',birthday: '1990-01-01',address: '北京市朝阳区某某街道某某小区',bio: '热爱生活,热爱编程。'};// 填充表单this.form = { ...userInfo };},methods: {// 选择头像chooseAvatar() {uni.chooseImage({count: 1,sizeType: ['compressed'],sourceType: ['album', 'camera'],success: (res) => {const tempFilePaths = res.tempFilePaths;this.form.avatar = tempFilePaths[0];// 实际场景中应该先上传图片,再获取图片的URLthis.uploadAvatar(tempFilePaths[0]);}});},// 上传头像uploadAvatar(filePath) {uni.showLoading({title: '上传中...'});// 模拟上传setTimeout(() => {uni.hideLoading();uni.showToast({title: '头像上传成功',icon: 'success'});// 实际场景中,这里应该返回服务器的图片URL// this.form.avatar = res.data.url;}, 1500);},// 生日改变onBirthdayChange(e) {this.form.birthday = e.detail.value;},// 验证单个字段validateField(field) {if (!this.rules[field]) return;const descriptor = {};descriptor[field] = this.rules[field];const validator = new Schema(descriptor);const source = {};source[field] = this.form[field];validator.validate(source, (errors) => {if (errors) {// 有错误this.$set(this.errors, field, errors[0].message);} else {// 没有错误this.$set(this.errors, field, '');}});},// 验证所有字段validateForm() {return new Promise((resolve, reject) => {const validator = new Schema(this.rules);validator.validate(this.form, (errors) => {if (errors) {// 有错误const errorObj = {};errors.forEach(error => {errorObj[error.field] = error.message;});this.errors = errorObj;resolve(false);} else {// 验证通过this.errors = {};resolve(true);}});});},// 提交表单async submitForm() {const valid = await this.validateForm();if (!valid) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 显示加载提示uni.showLoading({title: '保存中...'});// 模拟提交请求setTimeout(() => {uni.hideLoading();uni.showToast({title: '保存成功',icon: 'success'});// 返回上一页setTimeout(() => {uni.navigateBack();}, 1500);}, 1500);/* 实际场景中的提交代码try {const res = await uni.request({url: 'https://api.example.com/update-profile',method: 'POST',data: this.form,header: {'content-type': 'application/json','Authorization': `Bearer ${uni.getStorageSync('token')}`}});if (res.statusCode === 200 && res.data.code === 0) {uni.hideLoading();uni.showToast({title: '保存成功',icon: 'success'});// 更新本地存储的用户信息uni.setStorageSync('userInfo', res.data.data.userInfo);// 返回上一页setTimeout(() => {uni.navigateBack();}, 1500);} else {throw new Error(res.data.message || '保存失败');}} catch (error) {uni.hideLoading();uni.showToast({title: error.message || '网络错误,请稍后重试',icon: 'none'});}*/}}
}
</script><style scoped>
.profile-form {padding: 30rpx;
}.form-header {display: flex;justify-content: center;margin-bottom: 50rpx;
}.avatar-wrapper {display: flex;flex-direction: column;align-items: center;
}.avatar {width: 150rpx;height: 150rpx;border-radius: 50%;margin-bottom: 10rpx;
}.edit-hint {font-size: 24rpx;color: #666;
}.form-content {margin-bottom: 40rpx;
}.form-item {margin-bottom: 40rpx;position: relative;
}.label {display: block;margin-bottom: 10rpx;font-size: 28rpx;color: #333;
}.input, .textarea, .picker-box {width: 100%;border: 1rpx solid #dcdfe6;border-radius: 8rpx;padding: 0 20rpx;box-sizing: border-box;font-size: 28rpx;
}.input, .picker-box {height: 80rpx;line-height: 80rpx;
}.textarea {height: 160rpx;padding: 20rpx;line-height: 1.5;
}.picker-box {display: flex;justify-content: space-between;align-items: center;
}.picker-text {color: #333;
}.picker-arrow {color: #999;transform: rotate(90deg);
}.radio-group {display: flex;margin-top: 10rpx;
}.radio-item {display: flex;align-items: center;margin-right: 50rpx;
}.radio-box {width: 40rpx;height: 40rpx;border: 2rpx solid #dcdfe6;border-radius: 50%;display: flex;justify-content: center;align-items: center;box-sizing: border-box;position: relative;
}.radio-box.checked {border-color: #2979ff;
}.radio-box.checked:after {content: '';width: 20rpx;height: 20rpx;border-radius: 50%;background-color: #2979ff;position: absolute;
}.radio-label {margin-left: 10rpx;font-size: 28rpx;
}.error-tip {position: absolute;left: 0;bottom: -36rpx;font-size: 24rpx;color: #f56c6c;
}.submit-btn {margin-top: 60rpx;
}
</style>
表单验证的最佳实践
- 实时验证与提交验证结合:在输入框失去焦点时进行单个字段验证,在表单提交时进行全表单验证
- 友好的错误提示:错误信息应该清晰明了,位置合适
- 良好的用户体验:添加适当的过渡效果,不要让错误提示突兀出现
- 避免重复验证:已验证过且符合要求的字段无需重复验证
- 表单防抖:防止用户频繁点击提交按钮
- 状态保持:表单提交失败后不要清空用户输入
- 进度提示:使用加载提示,让用户知道表单正在提交
总结
本文介绍了在 UniApp 中实现表单验证与提交功能的多种方式,包括自定义验证和使用第三方库验证。我们通过实例详细讲解了各种验证规则的编写,以及表单提交的完整流程。
表单验证看似简单,但实际上涉及众多细节,一个设计良好的表单验证系统能极大提升用户体验。希望本文对你在 UniApp 中开发表单功能有所帮助。
在实际项目中,你可能需要根据业务需求进行更多定制化的开发,例如添加更复杂的验证规则、优化表单的交互效果、处理更多的表单场景等。不论如何变化,本文提供的基本思路和方法都是适用的。
进一步思考
- 如何处理更复杂的表单依赖验证?(例如,当选择A选项时,B字段必填)
- 如何处理文件上传类型的表单字段?
- 如何优化大型复杂表单的性能?
- 如何实现多步骤表单?
这些都是表单开发中的进阶话题,欢迎在实践中探索更多解决方案。
相关文章:
鸿蒙OSUniApp 实现的表单验证与提交功能#三方框架 #Uniapp
UniApp 实现的表单验证与提交功能 前言 在移动端应用开发中,表单是用户与应用交互的重要媒介。一个好的表单不仅布局合理、使用方便,还应该具备完善的验证与提交功能,以确保用户输入的数据准确无误。本文将分享如何在 UniApp 中实现表单验证…...

如何在 Windows 11 或 10 的 CMD 中检查固件
检查 Windows 11 或 10 中现有设备的硬件固件版本,可以帮助用户安装和更新准确的驱动程序,进行故障排除活动,确保兼容性以及维护系统性能。因此,在本教程中,我们将讨论如何在命令提示符(CMD)中使用一些命令查找 Windows 服务器或桌面中硬件固件版本的方法。由于本教程将…...

进阶-数据结构部分:3、常用查找算法
飞书文档https://x509p6c8to.feishu.cn/wiki/LRdnwfhNgihKeXka7DfcGuRPnZt 顺序查找 查找算法是指:从一些数据之中,找到一个特殊的数据的实现方法。查找算法与遍历有极高的相似性,唯一的不同就是查找算法可能并不一定会将每一个数据都进行访…...
Oracle 11.2.0.4 pre PSU Oct18 设置SSL连接
Oracle 11.2.0.4 pre PSU Oct18 设置SSL连接 1 说明2 客户端配置jdk环境3服务器检查oracle数据库补丁4设置ssla 服务器配置walletb 上传测试脚本和配置文件到客户端c 服务器修改数据库侦听和sqlnet.orad 修改客户端的sqlnet.ora和tnsnames.ora的连接符e 修改java代码的数据连接…...
服务器连接多客户端
一、epoll 核心函数详解 1. epoll_create/epoll_create1 - 创建 epoll 实例 c #include <sys/epoll.h> int epoll_create(int size); // Linux 2.6.8前需指定size(>1),后续版本可忽略 int epoll_create1(int flags); // 推荐使用…...

基于QT和FFmpeg实现自己的视频播放器FFMediaPlayer(一)——项目总览
在音视频开发的学习过程中,开发一款视频播放器是FFmpeg进阶的最好实战方法。本文将基于 QT 和 FFmpeg 着手实现自定义视频播放器 FFMediaPlayer,作为系列文章的开篇,我们先来整体了解项目的设计思路、架构与配置。 一、软件设计五大原则 …...
服务器死机了需要检查哪些问题
在这个数字化的时代,服务器就像是我们信息世界的“大管家”,可要是它突然死机了,那可真是让人头疼。今天咱们就来聊聊,服务器死机了,到底需要检查哪些问题。 一、硬件问题 电源供应:检查电源是否稳定&…...

【HCIA】浮动路由
前言 我们通常会在出口路由器配置静态路由去规定流量进入互联网默认应该去往哪里。那么,如果有两个运营商的路由器都能为我们提供上网服务,我们应该如何配置默认路由呢?浮动路由又是怎么一回事呢? 文章目录 前言1. 网络拓扑图2. …...

使用instance着色
本节我们学习使用instance着色器进行着色 //拾取var handler new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction(function(movement){console.log(movement);var pickedObject viewer.scene.pick(movement.position);if(Cesium.defined(picke…...

【NLP 72、Prompt、Agent、MCP、function calling】
命运把我们带到哪里,就是哪里 —— 25.5.13 一、Prompt 1.User Prompt 用户提示词 当我们与大模型进行对话时,我们向大模型发送的消息,称作User Prompt,也就是用户提示词,一般就是我们提出的问题或者想说的话 但是我们…...

Mysql数据库之集群进阶
一、日志管理 5.7版本自定义路径时的文件需要自己提前创建好文件,不会自动创建,否则启动mysql会报错 错误日志 rpm包(yum) /var/log/mysql.log 默认错误日志 ###查询日志路径 [rootdb01 ~]# mysqladmin -uroot -pEgon123 variables | grep -w log_e…...

临床决策支持系统的提示工程优化路径深度解析
引言 随着人工智能技术在医疗领域的迅猛发展,临床决策支持系统(CDSS)正经历从传统规则引擎向智能提示工程的范式转变。在这一背景下,如何构建既符合循证医学原则又能适应个体化医疗需求的CDSS成为医学人工智能领域的核心挑战。本报告深入剖析了临床决策支持系统中提示工程的…...
精益数据分析(64/126):移情阶段的用户触达策略——从社交平台到精准访谈
精益数据分析(64/126):移情阶段的用户触达策略——从社交平台到精准访谈 在创业的移情阶段,精准找到目标用户并开展深度访谈是验证需求的关键。今天,我们结合《精益数据分析》中的方法论,探讨如何利用Twit…...

苹果新一代车载系统CarPlay Ultra来袭,全屏接管+ChatGPT助力,智能驾驶要“起飞”
AITOP100获悉,苹果又搞出大动作啦!正式推出了新一代车载系统——CarPlay Ultra。这次,苹果可是下了狠功夫,把iPhone和汽车的所有显示屏深度整合到了一起,还首次把ChatGPT引入到了驾驶体验当中。这系统可不简单…...

无线信道的噪声与干扰
目录 1. 无线信道(wireless channel)与电磁波 2.1 电磁波的传输(无线信道传输) 2.2 视线(line of sight)传播与天线高度 2. 信道的数学模型 2.1 调制信道模型 2.1.1 加性噪声/加性干扰 2.1.2 乘性噪声/乘性干扰 2.1.3 随参信道/恒参信道 2.2 编码信道模型 2.3 小结 …...

MySQL 8.0 OCP 1Z0-908 101-110题
Q101.which two queries are examples of successful SQL injection attacks? A.SELECT id, name FROM backup_before WHERE name‘; DROP TABLE injection; --’; B. SELECT id, name FROM user WHERE id23 oR id32 OR 11; C. SELECT id, name FROM user WHERE user.id (SEL…...

BBR 的 buffer 动力学观感
这周很忙,今天还加了一天班,但还是抽空实现了五一在安徽泾县山区喝着一壶酒写的 BBR ProbeRTT 的想法,没多少行代码,它真就消除了带宽锯齿,皮了个鞋👞,昨天我还在群里说了今天再说说 BBR 的&…...

Spring之Bean的初始化 Bean的生命周期 全站式解析
目录 导图 步骤 第一步 实例化 第二步 属性赋值 第三步 初始化 aware 接口 BeanPostProcessor 接口 InitializingBean 和 init-method 第四步使用 第五步使用后销毁 描述一下 Bean 的 生命周期 导图 步骤 总体上可以分为五步 首先是 Bean 的实例化Bean 在进行实例…...

FreeCAD源码分析: Transaction实现原理
本文阐述FreeCAD中Transaction的实现原理。 注1:限于研究水平,分析难免不当,欢迎批评指正。 注2:文章内容会不定期更新。 一、概念 Ref. from What is a Transaction? A transaction is a group of operations that have the f…...

flutter缓存网络视频到本地,可离线观看
记录一下解决问题的过程,希望自己以后可以参考看看,解决更多的问题。 需求:flutter 缓存网络视频文件,可离线观看。 解决: 1,flutter APP视频播放组件调整; 2,找到视频播放组件&a…...

Kotlin 中 infix 关键字的原理和使用场景
在 Kotlin 中,使用 infix 关键字修饰的函数称为中缀函数,使用是可以省略 . 和 (),允许以更自然(类似自然语言)的语法调用函数,这种特性可以使代码更具可读性。 1 infix 的原理 中缀函数必须满足以下条件&…...

c++从入门到精通(五)--异常处理,命名空间,多继承与虚继承
异常处理 栈展开过程: 栈展开过程沿着嵌套函数的调用链不断查找,直到找到了与异常匹配的catch子句为止;也可能一直没找到匹配的catch,则退出主函数后查找过程终止。栈展开过程中的对象被自动销毁。 在栈展开的过程中,…...
mock 数据( json-server )
json-server 实现数据 mock 实现步骤: 1. 在项目中安装 json-server npm install -D json-server 2. 准备一个 json 文件 server/data.json {"posts": [{ "id": "1", "title": "a title", "views"…...
Java多线程编程中的常见问题与陷阱汇总
线程安全问题 多线程环境下,多个线程同时访问共享资源时,可能会导致数据不一致或程序行为异常。常见的线程安全问题包括竞态条件、死锁、活锁等。 public class Counter {private int count 0;public void increment() {count;}public int getCount()…...
ARP Detection MAC-Address Static
一、ARP Detection(ARP检测) ✅ 定义: ARP检测是一种防止ARP欺骗攻击的安全机制。它通过监控或验证网络中的ARP报文,来判断是否存在伪造的ARP信息。 🔍 工作原理: 网络设备(如交换机…...

gcc/g++常用参数
1.介绍 gcc用于编译c语言,g用于编译c 源代码生成可执行文件过程,预处理-编译-汇编-链接。https://zhuanlan.zhihu.com/p/476697014 2.常用参数说明 2.1编译过程控制 参数作用-oOutput,指定输出名字-cCompile,编译源文件生成对…...

nginx配置之负载均衡
版权声明:原创作品,请勿转载! 1.实验环境准备 准备3台linux服务器(ubuntu和centos均可,本文使用centos7.9),两台web和一台负载均衡服务器,均安装nginx服务 主机名IP软件lb0110.0.0…...
相机Camera日志分析之十一:高通相机Camx hal预览1帧logcat日志process_capture_result详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:高通相机Camx 日志分析之五:camx hal预览1帧logcat日志process_capture_request详解 这一篇我们开始讲: 高通相机Camx 日志分析之十一:camx hal预览1帧logcat日志process_capture_result详解,这里我…...
Python函数库调用实战:以数据分析为例
一、引言 Python之所以在编程领域广受欢迎,很大程度上得益于其丰富且强大的函数库。这些函数库涵盖了从数据分析、科学计算到Web开发、机器学习等众多领域,极大地提高了开发效率。本文将以数据分析为例,介绍如何调用Python的一些常用函数库。…...

去年开发一款鸿蒙Next Os的window工具箱
持拖载多个鸿蒙应用 批量签名安装 运行 http://dl.lozn.top/lozn/HarmonySignAndFileManagerTool_2024-11-26.zip 同类型安卓工具箱以及其他软件下载地址汇总 http://dl.lozn.top/lozn/ 怎么个玩法呢,比如要启动某app, 拖载识别到包名 点启动他能主动读取包名 然后…...