同学们可以私信我加入学习群!
正文开始
前言
前面我们已经把vue自带的页面删除,也搭建了最简单的router路由,下面就可以真正开发我们自己的项目了,一般而言,很少有人从零开始写代码,博主也是为了完善这个系列博客,才会从零开始,把关键的代码都敲了一遍。
哪怕同学们有自己心仪的项目,搭建基础的架构,跟着博主学一遍关键的知识点,也有助于以后优化升级项目,修改别人的代码或者修复bug。
跟着博主写一遍,大概率是可以真正把控全局,把vue如何搭建网站彻底搞明白。
一、创建首页
上篇文章讲到,我们会习惯把所有路由信息都保存到一个js文件中,作为路由模块。例如:
c
export default [
{
path: '/',
name: 'login',
meta: {
title: '登录',
hideInMenu: true
},
component: () => import('@module-base/views/login/login.vue')
},
...
]
这段代码就是记录了部分路由信息,我们路由数组的第一个元素,一般就是项目默认登录的地址。component字段就是对应的组件,它的地址是默认地址"/",如果我们把项目运行到localhost:5173,那么只要我们在浏览器输入localhost:5173或者localhost:5173/,就会跳转到login.vue组件的内容。
我们login.vue中的代码十分简单,就是一个背景图+一个登录卡片,这是基础的html和vue知识,我们下面会一一讲解。
最终效果如图:
二、登录页代码讲解
只关注实战的同学可以快速略过代码讲解部分。
本系列主要为vue教程,所以可能在涉及html、js的基础知识时,会重点讲解,因为这属于上手vue的必学必会技能,但是css3相关知识可能会弱化,一个原因是知识点比较多,一个原因是新手入门抄样式也能磕磕绊绊地做项目。对css感兴趣同学,可以看博主源码,自行查阅资料。
登录代码可以分解为两个部分:
1.卡片组件
2.登录逻辑
- 卡片组件
c
<Card title="欢迎登录" :bordered="false">
<div class="form-con">
<login-form @on-success-valid="handleSubmit"></login-form>
<p class="login-tip">输入任意用户名和密码即可</p>
</div>
</Card>
这是iview提供的卡片组件,如果使用其它ui库,参考对应官网代码即可,都是换汤不换药。
关键代码讲解:
title:组件的标题
bordered:是否有边框
login-form:是一个组件,把form表单相关功能封装到一个单独的组件中,然后vue会把login-form组件里的所有内容,最终都渲染到这个位置
@on-success-valid:@标记是vue提供的语法,代表监听事件,这里就是监听一个名叫"on-success-valid"的事件。
这里涉及到了login-form组件,所以我们再看这个组件的代码:
c
<Form ref="loginForm" :model="form" :rules="rules" @keydown.enter.native="handleSubmit">
<FormItem prop="userName">
<Input v-model="form.userName" placeholder="请输入用户名">
<span slot="prepend">
<Icon :size="16" type="ios-person"></Icon>
</span>
</Input>
</FormItem>
<FormItem prop="password">
<Input type="password" v-model="form.password" placeholder="请输入密码">
<span slot="prepend">
<Icon :size="14" type="md-lock"></Icon>
</span>
</Input>
</FormItem>
<FormItem>
<Button @click="handleSubmit" class="c-btn-primary" long>登录</Button>
</FormItem>
</Form>
这段代码里,主要用到了iview的form组件,Form标签用来包裹在最外面,fomritem指表单中的每一个表单项,这里一共有三项:姓名输入框、密码输入框、登录按钮。
其他代码都是一些辅助代码,为了让我们的表单样式看起来更舒服,我们重点关注登录按钮,它定义了一个事件:handleSubmit。
我们上面讲过,在html元素中,@是vue定义的一个语法,代表着事件监听,@click不同于上面提到的@on-success-valid,是官方定义的监听事件,意思是监听点击事件。
完整逻辑就是在登录这个按钮上,监听了点击事件,当发现登录按钮被点击后,就调用后面定义的方法handleSubmit。我们继续看handleSubmit的代码:
c
methods: {
handleSubmit () {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.$emit('on-success-valid', {
userName: this.form.userName,
password: this.form.password
})
}
})
}
}
它先通过this.$refs.loginForm.validate验证上面的表单元素是否合规,如果合规的话,就运行后面emit的代码,emit是vue定义的触发方法,这里代码要触发一个叫on-success-valid的方法,这个方法是不是很熟悉?不错,它就是我们在login.vue中监听的方法@on-success-valid。
到这里,逻辑就比较清晰了,login.vue中引入了一个card组件,card组件是view提供的官方组件,card组件中引入了login-form组件,login-form组件是我们自己写的组件,并且在引入组件时,我们写了@on-success-valid用来监听login-form组件中触发的on-success-valid方法。
login-form中定义了一个点击事件,当点击登录按钮时,触发on-success-valid,这个信号被login.vue接收到,login.vue就会去调用@on-success-valid监听后面定义的方法。代码如下:
c
<login-form @on-success-valid="handleSubmit"></login-form>
在login.vue中也叫handleSubmit方法,找到login.vue中的handleSubmit方法:
c
handleSubmit ({ userName, password }) {
this.$router.push({
name: '_home'
})
}
发现它主要做了一件事,那就是利用router插件提供的方法,跳转到_home页面。
至此,一个最简单的登录逻辑完成。
三、对应的vue知识点:
1.@click、@on-success-valid是vue中事件监听的语法,意思是监听后面的操作,当发现触发了对应的操作,就调用对应的方法。
2.vue中最重要的就是组件的思想,不管是使用ui框架提供的组件,还是自定义组件,都是在一个大组件中拼接各种小组件,共同构成一个完整页面。每个组件只需要关注自己的功能,把所有功能串联起来,就是页面的完整功能。
3.代码中出现的:value、:size、:model等,是vue中v-bind语法的变种,等价于v-bind:value,v-bind:size,v-bind:model,这是在定义html元素的属性,不同于直接在html中写attribute,vue中这种语法,可以绑定一个动态变量,动态设置属性更加灵活。
四、附件-各文件代码
login.vue:
c
<style lang="less">
@import './login.less';
</style>
<template>
<div class="login">
<div class="login-con">
<Card icon="log-in" title="欢迎登录" :bordered="false">
<div class="form-con">
<login-form @on-success-valid="handleSubmit"></login-form>
<p class="login-tip">输入任意用户名和密码即可</p>
</div>
</Card>
</div>
<div style="position: absolute;bottom: 8px;width: 100%;display: flex;justify-content: center;color: white">
<a href="https://beian.miit.gov.cn/" target="_blank">冀ICP备2022011594号-1</a>
</div>
</div>
</template>
<script>
import LoginForm from '_c/login-form'
export default {
components: {
LoginForm
},
methods: {
handleSubmit ({ userName, password }) {
this.$router.push({
name: '_home'
})
}
}
}
</script>
<style scoped>
</style>
login-form.vue:
c
<template>
<Form ref="loginForm" :model="form" :rules="rules" @keydown.enter.native="handleSubmit">
<FormItem prop="userName">
<Input v-model="form.userName" placeholder="请输入用户名">
<span slot="prepend">
<Icon :size="16" type="ios-person"></Icon>
</span>
</Input>
</FormItem>
<FormItem prop="password">
<Input type="password" v-model="form.password" placeholder="请输入密码">
<span slot="prepend">
<Icon :size="14" type="md-lock"></Icon>
</span>
</Input>
</FormItem>
<FormItem>
<Button @click="handleSubmit" class="c-btn-primary" long>登录</Button>
</FormItem>
</Form>
</template>
<script>
export default {
name: 'LoginForm',
props: {
userNameRules: {
type: Array,
default: () => {
return [
{ required: true, message: '账号不能为空', trigger: 'blur' }
]
}
},
passwordRules: {
type: Array,
default: () => {
return [
{ required: true, message: '密码不能为空', trigger: 'blur' }
]
}
}
},
data () {
return {
form: {
userName: 'super_admin',
password: ''
}
}
},
computed: {
rules () {
return {
userName: this.userNameRules,
password: this.passwordRules
}
}
},
methods: {
handleSubmit () {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.$emit('on-success-valid', {
userName: this.form.userName,
password: this.form.password
})
}
})
}
}
}
</script>
总结
获取资源,或者联系我,都可以通过下面入口: