用uniapp写一个添加收货地址

admin 129 0
在uniapp中实现添加收货地址功能,需创建表单页面包含收货人、手机号、省市区选择(使用picker组件联动)及详细地址输入,通过uni.setStorageSync存储地址数据至本地,或调用接口提交至后端,表单需校验手机号格式、地址完整性等必填项,提交成功后通过uni.showToast提示,并返回上一页刷新列表,核心代码包括表单双向绑定、省市区数据联动及本地存储逻辑,确保用户便捷管理收货信息。

Uniapp实现添加收货地址功能:从零开始的详细教程

在电商、外卖、社区团购等类型的应用中,收货地址管理都是核心功能之一,本文将详细介绍如何使用Uniapp框架从零开始实现"添加收货地址"功能,涵盖页面结构设计、表单验证、省市区联动、本地存储等关键环节,帮助开发者快速掌握这一常见功能的开发方法。

环境准备与项目创建

在开始编码前,确保已安装以下工具:

  • HBuilderX:Uniapp官方推荐IDE,支持代码编写、调试和打包。
  • Uniapp项目模板:可通过HBuilderX创建"默认模板"项目,选择Vue2或Vue3(本文以Vue2为例)。

创建项目后,在pages目录下新建address文件夹,并添加add-address.vue文件,作为添加收货地址的页面。

页面结构设计:表单组件布局

添加收货地址的本质是一个表单填写过程,需要包含收货人姓名、手机号、省市区选择、详细地址、是否默认地址等字段,我们先设计页面的基本结构,使用Uniapp提供的组件搭建UI。

add-address.vue模板代码:

<template>
    <view class="add-address-container">
        <view class="form-wrapper">
            <!-- 收货人姓名 -->
            <view class="form-item">
                <text class="label">收货人</text>
                <input 
                    type="text" 
                    v-model="form.name" 
                    placeholder="请输入收货人姓名"
                    maxlength="20"
                    @blur="validateName"
                />
                <text v-if="errors.name" class="error-text">{{ errors.name }}</text>
            </view>
            <!-- 手机号 -->
            <view class="form-item">
                <text class="label">手机号</text>
                <input 
                    type="number" 
                    v-model="form.phone" 
                    placeholder="请输入手机号"
                    maxlength="11"
                    @blur="validatePhone"
                />
                <text v-if="errors.phone" class="error-text">{{ errors.phone }}</text>
            </view>
            <!-- 省市区选择 -->
            <view class="form-item" @click="showPicker = true">
                <text class="label">所在地区</text>
                <view class="picker-value">
                    {{ form.region || '请选择省市区' }}
                    <text class="arrow">></text>
                </view>
            </view>
            <!-- 详细地址 -->
            <view class="form-item">
                <text class="label">详细地址</text>
                <textarea 
                    v-model="form.detail" 
                    placeholder="请输入详细地址(街道、门牌号等)"
                    maxlength="100"
                    @blur="validateDetail"
                ></textarea>
                <text v-if="errors.detail" class="error-text">{{ errors.detail }}</text>
            </view>
            <!-- 默认地址 -->
            <view class="form-item">
                <text class="label">设为默认地址</text>
                <switch 
                    :checked="form.isDefault" 
                    @change="handleDefaultChange"
                    color="#fa2c19"
                />
            </view>
        </view>
        <!-- 提交按钮 -->
        <view class="submit-btn" @click="submitForm">保存地址</view>
        <!-- 省市区选择器 -->
        <picker 
            mode="region" 
            :value="regionArray" 
            @change="onRegionChange"
            @cancel="showPicker = false"
            v-if="showPicker"
        >
            <view class="picker-mask"></view>
        </picker>
    </view>
</template>

脚本部分:

<script>
export default {
    data() {
        return {
            form: {
                name: '',
                phone: '',
                region: '',
                detail: '',
                isDefault: false
            },
            errors: {
                name: '',
                phone: '',
                detail: ''
            },
            showPicker: false,
            regionArray: []
        }
    },
    methods: {
        // 验证收货人姓名
        validateName() {
            if (!this.form.name.trim()) {
                this.errors.name = '请输入收货人姓名';
                return false;
            }
            if (this.form.name.length < 2) {
                this.errors.name = '姓名至少2个字符';
                return false;
            }
            this.errors.name = '';
            return true;
        },
        // 验证手机号
        validatePhone() {
            const phoneRegex = /^1[3-9]\d{9}$/;
            if (!this.form.phone) {
                this.errors.phone = '请输入手机号';
                return false;
            }
            if (!phoneRegex.test(this.form.phone)) {
                this.errors.phone = '请输入正确的手机号';
                return false;
            }
            this.errors.phone = '';
            return true;
        },
        // 验证详细地址
        validateDetail() {
            if (!this.form.detail.trim()) {
                this.errors.detail = '请输入详细地址';
                return false;
            }
            if (this.form.detail.length < 5) {
                this.errors.detail = '详细地址至少5个字符';
                return false;
            }
            this.errors.detail = '';
            return true;
        },
        // 处理默认地址切换
        handleDefaultChange(e) {
            this.form.isDefault = e.detail.value;
        },
        // 省市区选择变化
        onRegionChange(e) {
            this.regionArray = e.detail.value;
            this.form.region = this.regionArray.join(' ');
            this.showPicker = false;
        },
        // 提交表单
        submitForm() {
            const isNameValid = this.validateName();
            const isPhoneValid = this.validatePhone();
            const isDetailValid = this.validateDetail();
            if (!isNameValid || !isPhoneValid || !isDetailValid) {
                uni.showToast({
                    title: '请检查表单信息',
                    icon: 'none'
                });
                return;
            }
            // 模拟保存到本地存储
            const addressList = uni.getStorageSync('addressList') || [];
            const newAddress = {
                ...this.form,
                id: Date.now(),
                createTime: new Date().toISOString()
            };
            addressList.push(newAddress);
            uni.setStorageSync('addressList', addressList);
            uni.showToast({
                title: '地址保存成功',
                icon: 'success'
            });
            // 返回上一页
            setTimeout(() => {
                uni.navigateBack();
            }, 1500);
        }
    }
}
</script>

样式设计:

<style lang="scss">
.add-address-container {
    min-height: 100vh;
    background-color: #f5f5f5;
    padding: 20rpx;
    .form-wrapper {
        background-color: #fff;
        border-radius: 12rpx;
        padding: 30rpx;
        margin-bottom: 30rpx;
        .form-item {
            display: flex;
            align-items: center;
            min-height: 100rpx;
            border-bottom: 1rpx solid #eee;
            position: relative;
            .label {
                width: 160rpx;
                font-size: 28rpx;
                color: #333;
                flex-shrink: 0;
            }
            input, textarea {
                flex: 1;
                font-size: 28rpx;
                color: #333;
                padding: 10rpx 0;
            }
            textarea {
                min-height: 120rpx;
                padding: 10rpx 0;
            }
            .picker-value {
                flex: 1;
                font-size: 28rpx;
                color: #666;
                display: flex;
                align-items: center;
                .arrow {
                    margin-left: 10rpx;
                    color: #999;
                    font-size: 24rpx;
                }
            }
            .error-text {
                position: absolute;
                right: 0;
                bottom: -20rpx;
                font-size: 24rpx;
                color: #fa2c19;
            }
        }
    }
    .submit-btn {
        background-color: #fa2c19;
        color: #fff;
        text-align: center;
        padding: 24r

标签: #uniapp #添加收货地址