1.用户登录页面开发
1.查询vant组件 2.实现组件模板部分 3.模型层准备 4.数据上传
1.1 创建版权声明组件Copyright
新建文件:src\components\common\Copyright.vue
javascript
<template>
<!-- 版权声明 -->
<div class="copyright">
copyright xxx旅游网©2024
</div>
</template>
<style lang="less">
.copyright{
position: fixed;
bottom: 0;
padding: 10px;
color:#999;
width: 100%;
text-align: center;
font-size: 12px;
}
</style>
1.2 登录页面Login
新建文件:src\views\accounts\Login.vue
1.2.1 脚本script:
html
<script setup>
import Copyright from '@/components/common/Copyright.vue';
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import TripFooter from '@/components/common/Footer.vue';
const route = useRoute() //获得属性
const router = useRouter() //获取地址
const username = ref('')
const password = ref('')
//用户名的验证规则
const rulename = ref([{
required: true,//用户名组件中通过该属性开启必填验证
message: '请填写用户名'
}, {
pattern: /1\d{10}/,//用户名组件中,通过该属性开启正则表达式验证
message: '请填写正确的手机号'
}])
const goBack = () => {
router.go(-1)
}
</script>
1.2.2 模板template
html
<template>
<div class="page-account-login">
<!-- 导航条 -->
<van-nav-bar title="用户登录" left-text="返回" @click-left="goBack"></van-nav-bar>
<!-- 表单输入 -->
<van-form>
<!-- 文本框 -->
<van-field v-model="username" label="用户名" placeholder="用户名" maxlength="11" :rules="rulename" clearable />
<!-- 密码框 -->
<van-field v-model="password" type="password" label="密码" placeholder="密码" :rules="[{ required: true }]" autocomplete="off"/>
<div>
<van-button square type="primary" native-type="submit" color="green">提交</van-button>
</div>
</van-form>
<!-- 文字提示 -->
<div>
登录表示同意<a href="#">用户使用协议</a>及<a href="#">隐私条款</a>
</div>
<div>
没有账户?<RouterLink :to="{name:'AccountRegister'}">点击注册</RouterLink>
</div>
<!-- 版权信息 -->
<Copyright />
<TripFooter/>
</div>
</template>
1.2.3 配置路由:
文件地址:src\router\index.js
javascript
import AccountLogin from '@/views/accounts/Login.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path:'/account/login',
name:'AccountLogin',
component:AccountLogin
}
]
})
2.用户注册界面开发
2.1 封装短信验证组件SendSmscode
新建文件:src\components\common\SendSmsCode.vue
2.1.1 脚本script
html
<script setup>
//defineProps用于父子组件通信
import { ref, onMounted, computed, defineProps } from 'vue'
import { useRoute, useRouter } from 'vue-router'//用于控制页面跳转工具,传值工具
import { ajax } from '@/utils/ajax';
import { SightApis } from '@/utils/apis';
import { showToast } from 'vant';
const router = useRouter()
const route = useRoute()
const goBack = () => {
router.go(-1)//跳转至上一页(1:跳转至下一页)
}
const props = defineProps({
phoneNum: String
})
//存放验证信息(响应式数据)
const isSmsSend = ref(false)
const sendBtnText = ref('点击发送验证码')
const timer = ref(null)
const counter = ref(60)
//清空验证码计时
const reset = () => {
isSmsSend.value = false
sendBtnText.value = '点击发送验证码'
if (timer.value) {
clearInterval(timer.value)//停止回调函数
counter.value = 60
timer.value = null
}
}
//倒计时
const countDown = () => {
//回调函数,重复调用
timer.value = setInterval(() => {
sendBtnText.value = `(${counter.value}秒)后重新发送`
counter.value--
if (counter.value < 0) {
reset()
}
}, 1000)
}
//发送验证码
const sendSmsCode = () => {
//判断手机号是否输入
if (!props.phoneNum) {
showToast('请输入手机号码')
return false
}
isSmsSend.value = true //调用接口,发送短息
countDown() //开始倒计时
}
defineExpose({//向父级暴露函数
reset
})
</script>
2.1.2 模板template:
html
<template>
<!-- 短信验证码发送相关逻辑 -->
<van-button size="small" type="primary" @click.prevent="sendSmsCode()" :disabled="isSmsSend">
{{ sendBtnText }}
</van-button>
</template>
2.2 注册页面Register
新建文件:src\views\accounts\Register.vue
2.2.1 脚本script:
html
<script setup>
import Copyright from '@/components/common/Copyright.vue'
import SendSmsCode from '@/components/common/SendSmsCode.vue'
import { ref, toRef } from 'vue';
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter();
// 用户名的验证规则
const ruleName = ref([{
required: true,
message: '请填写用户名'
}, {
pattern: /1\d{10}/,
message: '请填写正确的手机号'
}])
// 重复密码验证
const rulePassword = ref([
{
required: true,
message: '请重复一次密码'
}, {
validator: () => form.value.password === form.value.passwordRepeat,
message: '两次密码输入不一致'
}])
const form = ref({
username: '',
nickname: '',
sms_code: '',
password: '',
passwordRepeat: ''
})
//手机号变化时,重置验证码组件状态
const refSms = ref({})
const onPhoneChange = () => {
//调用验证码组件中reset函数,重置验证码
refSms.value.reset()
}
const onSubmit = () => {
// 提交表单
}
const goBack = () => {
router.go(-1)
}
</script>
2.2.2 模板template
html
<template>
<!-- 用户注册 -->
<div class="page-account-register">
<!-- 导航条 -->
<van-nav-bar title="用户注册" left-text="返回" left-arrow @click-left="goBack" />
<!-- 表单输入 -->
<van-form @submit="onSubmit">
<van-field v-model="form.username" label="手机号码" placeholder="手机号码" type="tel" maxlength="11" clearable
:rules="ruleName" @input="onPhoneChange" />
<van-field v-model="form.sms_code" center clearable label="短信验证码" placeholder="短信验证码"
:rules="[{ required: true, message: '请输入短信验证码' }]">
<template #button>
<SendSmsCode ref="refSms" :phoneNum="form.username" />
</template>
</van-field>
<van-field v-model="form.nickname" label="用户昵称" placeholder="用户昵称" maxlength="32" clearable
:rules="[{ required: true, message: '请输入用户昵称' }]" />
<van-field v-model="form.password" type="password" label="密码" placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]" autocomplete="off"/>
<van-field v-model="form.passwordRepeat" type="password" label="确认密码" placeholder="确认密码"
:rules="rulePassword" autocomplete="off" />
<div style="margin: 16px;">
<van-button round block type="info" native-type="submit">
提交
</van-button>
</div>
</van-form>
<!-- //表单输入 -->
<!-- 文字提示 -->
<div class="tips">
注册表示同意 <a href="#">用户使用协议</a>及<a href="#">隐私条款</a>
</div>
<div class="tips">
已有账号? <router-link :to="{ name: 'AccountLogin' }">点击登录>></router-link>
</div>
<!-- 版权信息 -->
<Copyright />
</div>
</template>
2.2.3 配置路由:
文件地址:src\router\index.js
javascript
import AccountRegister from '@/views/accounts/Register.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{//用户注册
path: '/account/register',
name: 'AccountRegister',
component: AccountRegister
}
]
})
3.个人主页界面开发Mine
新建文件:src\views\Mine.vue
3.1 脚本script
import TripFooter from '@/components/common/Footer.vue'
3.2 模板template
html
<template>
<div class="page-mine">
<!-- 标题栏 -->
<van-nav-bar title="个人中心" />
<!-- 用户基本信息(头像/昵称) -->
<div class="user-header">
<div class="avatar">
<img src="/static/mine/avatar.png">
</div>
<div>
<p>Welcome,Adela</p>
<a class="btn-link" href="#">退出登录</a>
</div>
</div>
<!-- 订单菜单列表 -->
<van-row>
<van-col span="6">
<RouterLink to="/">
<van-icon name="records" />
<span>全部订单</span>
</RouterLink>
</van-col>
<van-col span="6">
<RouterLink to="/">
<van-icon name="pending-payment" />
<span>待支付</span>
</RouterLink>
</van-col>
<van-col span="6">
<RouterLink to="/">
<van-icon name="tosend" />
<span>已完成</span>
</RouterLink>
</van-col>
<van-col span="6">
<RouterLink to="/">
<van-icon name="logistics" />
<span>已取消</span>
</RouterLink>
</van-col>
</van-row>
<!-- 底部导航 -->
<TripFooter />
</div>
</template>
3.3 样式style(范例)
html
<style lang="less">
.page-mine {
font-family: 'Arial', sans-serif;
color: #333;
background-color: #f7f7f7;
.van-nav-bar {
background-color: #07c; //
color: #fff;
.van-nav-bar__title {
color: #fff;
text-align: center;
}
}
// 用户头部区域样式
.user-header {
background: url(/static/mine/bg.jpg) no-repeat center;
background-size: cover;
color: #fff;
height: 200px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 200px; // 确保有足够的高度
.avatar {
margin-bottom: 20px;
img {
width: 60px;
height: 60px;
border-radius: 50%;
}
}
p {
font-size: 18px;
}
.btn-link {
margin-top: 10px; // 添加顶部外边距以在垂直方向上居中
margin-left: 25px;
}
}
// 订单菜单列表样式
.van-row {
.van-col {
a {
display: flex;
flex-direction: column;
align-items: center;
text-decoration: none;
color: #333;
padding: 10px;
.van-icon {
font-size: 24px;
margin-bottom: 5px;
}
span {
font-size: 14px;
}
}
&:not(:last-child) {
border-right: 1px solid #eee;
}
}
}
// 底部导航样式
.trip-footer {
background-color: #fff;
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
position: fixed;
bottom: 0;
width: 100%;
}
}
</style>
3.4 配置路由
文件地址:src\router\index.js
javascript
import Mine from '@/views/Mine.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{//个人中心
path: '/mine',
name: 'Mine',
component: Mine
}
]
})
3.5 图示效果: