阅读 851

开发一个简单Vue项目(1) 注册与登录

作为前端的初学者,学一个前端框架是必不可少的。因为对于新手而言,VUE相较于REACT更容易上手,所以作者选择了VUE。如果你正好也想学一个框架,那你走运了哦。跟着作者一起来发开发一个简单的电商项目,来学习VUE吧!

这是一个基于 vue & axios & mock & token & stylus & Cube-UI的电商项目demo,面向 vue 初学者,场景虽简单,但五脏俱全。涵盖非常多的vue及其相关技术的基本操作。有详细的注释,帮助大家快速上手 vue 。且我整理了一些在vue开发过程中,有可能会用到的技术文章,希望大家能在这些前辈们身上有所收获。

当然如果您觉得这篇文章or这个项目对您的学习有所帮助,请不吝点个star鼓励一下,当然如果存在问题,也非常希望您能跟我留言,一起学习,共同进步。

登陆注册演示图

  • 话不多说上效果图

项目技术栈

  • 前台:vue & vue-router & vuex & vue-cli(webpack) & Cube-UI
  • 后台:mock(用mock写模拟api)
  • 前后台交互:axios
  • 单点登录:token

学习VUE项目开发推荐阅读

此处有引用大佬赢弱小金鱼的博客文章

  1. vue-cli 生成项目主体框架
  2. vue 全家桶
  3. axios前后台交互

    vue 和 node 的交互还是主要采用 ajax 来进行,此处就介绍一个主流交互工具 axios,当然别的工具例如 vue-resource、jquery 都可以。但是 vue-resource 不维护了,jquery如果只是为了 ajax 就引入又太庞大,所以我个人是比较推荐axios

  4. token
  5. 模拟后端mock

    Mock.js 是一款模拟数据生成器,旨在帮助前端攻城师独立于后端进行开发,帮助编写单元测试。提供了以下模拟功能:根据数据模板生成模拟数据,模拟 Ajax 请求,生成并返回模拟数据,基于 HTML 模板生成模拟数据

  6. 来自滴滴的CUBE-UI

    随着 vue 的不断发展,社区越来越活跃,因此产生了许多组件库。由于滴滴的这个组件没有停止更新和维护,特别适合开发上线项目,所以我们这里选择Cube-UI。


正文部分

  学了那么多文章,一定进步不少吧。让我们来进行实战开发,进行应用。一起来吧,先苦后甜!
复制代码

项目结构

引入Cube-UI并使用

 npm install cube-ui --save
复制代码

安装后会自动出现cube-ui.js

import Vue from 'vue'
import Cube from 'cube-ui'

Vue.use(Cube)

复制代码

下面我们来使用它

我们来写注册页面

<template>
  <div>
      <img class="headerimg" src="https://www.baidu.com/img/bd_logo1.png" alt="">
    <cube-form
      :model="model"
      :schema="schema"
      @submit="submitHandler"
    ></cube-form>
  </div>
</template>
<script>
export default {
    data(){
        return{
            model:{//数据源
                username:'',
                password:''
            },
            schema:{//生成表单依赖的模式
                fields:[//子配置项 模式用于定义表单中的各个字段,可以选择是否分组。 无分组
                //用户名配置
                    {
                        type:'input',//字段类型
                        modelKey:'username',//在表单的 model 数据源对象中所对应的 key 名字
                        label:'用户名',//字段的标签值
                        props:{
                            placeholder: '请输入用户名',
                        },
                        rules:{
                            //校验规则
                            required: true,
                            type: 'string',
                            min: 3,
                            max: 15,
                        },
                        trigger: 'blur',//如果设置为 'blur' 那么则会在离焦后校验
                        messages:{
                            required: '用户名不能为空',
                            min: '用户名不能少于三个字符',
                            max: '用户名不能超过十五个字符',
                        }
                    },
                    //密码配置
                    {
                        type:'input',//字段类型
                        modelKey:'password',//在表单的 model 数据源对象中所对应的 key 名字
                        label:'密码',//字段的标签值
                        props:{
                            placeholder: '请输入密码',
                            type:'password',
                            eye:{
                                open: false,
                            }
                        },
                        rules:{
                            required:true,
                        },
                        trigger: 'blur',
                    },
                    {
                        type:'submit',
                        label: '注册'
                    }
                ]
            }
        }
    },
复制代码

这个是注册页面的UI代码,我们引用组件中的cube-form表单,对它输入的值进行规则限定与验证,如果还不懂可以看看前面作者发的cube-ui文档哦,里面有详细介绍,也可以去GitHub下载demo,自己操作试试。 登陆页面也类似,我就不赘述啦~

用mock写模拟api

作为一个前端开发人员,在后端没有提供接口的情况下,自己编写模拟接口,对项目功能进行测试是十分重要的一项技能。拥有这项技能,将不会影响整个项目的开发进度。下面我们一起来编写。

我在vue.config.js对vue的配置文件中写啦,注册与登陆的接口,并编写了模拟数据,代码如下:

module.exports = {
  configureWebpack: {
    devServer: {
      port: 8080, //端口号
      open: true, //自动打开浏览器
      //mock 接口编写的地方 //假数据 //每次做更改配置文件时,都必须重启项目才会生效
      before(app) {
        //     app.get('请求地址',(req,res) =>{
        //         res.json({
        //             xinxi
        //         })
        // })
        //注册接口
        //用户信息池
        let userpoor = [{
            username: 'xxyang',
            password: '123456'
          },
          {
            username: 'liuqiangdong',
            password: '888888'
          }
        ]
        //注册接口
        app.get('/api/register', (req, res) => {
          const {
            username,
            password
          } = req.query
          const userlength = userpoor.filter(v => v.username == username).length //过滤 查找是否存在用户名
          if (userlength > 0) {
            res.json({
              success: false,
              message: '用户名已存在'
            })
          } else {
            res.json({
              success: true,
              message: '注册成功'
            })
          }
        })
        //登陆接口
        let tokenkey = 'xdclass'
        app.get('/api/login', (req, res) => {
          const {
            username,
            password
          } = req.query
          if (username == 'xxyang' && password == '123456' || username == 'liudongqiang' && password == '123456') {
            res.json({
              code: 0,
              message: '登陆成功',
              token: tokenkey + '-' + username + '-' + (new Date().getTime() + 60 * 60 * 1000) //token过期时间1个小时
            })
          } else {
            res.json({
              code: 1,
              message: '账号或密码错误'
            })
          }
        })
      }
    }
  },

  css: {
    loaderOptions: {
      stylus: {
        'resolve url': true,
        'import': [
          './src/theme'
        ]
      }
    }
  },

  pluginOptions: {
    'cube-ui': {
      postCompile: true,
      theme: true
    }
  }
}
复制代码

以上代码中作者有详细注释,烦请不懂的话自行看一下。我解释下这一句代码:

const userlength = userpoor.filter(v => v.username == username).length //过滤 查找是否存在用户名
复制代码

用filter过滤方法将输入的用户账号和已有的账号进行对比,如果相同则会返回true。这时就会获得userpoor的这条用户账号,此时长度大于零,所以输出false,提示用户已存在。

用token加密并储存密码

不知各位小伙伴知不知道,每年都要大量用户的信息泄露,例如CSDN以前被黑客攻击泄露了,几百万条用户信息,而且用户密码是明文的。这个时间爆发,让CSDN受到了,很大的影响。可想而知,对密码进行加密是十分重要的。token可以对密码进行加密,下面请看这个demo密码加密后的图片:

如图所示对密码进行了加密,而且加了头部xdclass进一步简单加密。而且我们储存在本地浏览器中了,避免在短时间内要多次登陆。下面我们来看代码吧。

登陆接口

 //登陆接口
        let tokenkey = 'xdclass'
        app.get('/api/login', (req, res) => {
          const {
            username,
            password
          } = req.query
          if (username == 'xxyang' && password == '123456' || username == 'liudongqiang' && password == '123456') {
            res.json({
              code: 0,
              message: '登陆成功',
              token: tokenkey + '-' + username + '-' + (new Date().getTime() + 60 * 60 * 1000) //token过期时间1个小时
            })
          } else {
            res.json({
              code: 1,
              message: '账号或密码错误'
            })
          }
        })
复制代码

这里我们对token进行了头部加密,和设置了token的有效时间为一个小时,一个小时内,用户不用重新登陆。

用VUEX将token储存在本地

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    token: ''
  },
  mutations: {
    //设置vuex的token
    settoken(state,token){
      state.token=token
    }
  },
  actions: {
  },
  modules: {
  },
  getters:{

  }
})
复制代码

调用API返回并储存token

methods: {
        async submitHandler(e) {
            e.preventDefault()
            try{
                const result = await this.$http.get('/api/login',{params:this.model})
                // console.log(result.data.token)
                if(result.code == '0'){
                    // alert(result.data.message)
                    this.$store.commit('settoken', result.token)
                    window.localStorage.setItem('token', result.token)
                    this.$router.replace({path:'/botnav/index'})
                }else{
                    alert(result.message)
                }
            }catch(err){
                console.log(err)
            }
        },
复制代码

判断账号密码是否正确,如果正确本地保存token,并且跳转路由到首页。

用axios进行拦截

前面有提到axios是用来进行前后台交互的,起一个中间件的作用,为服务器端处理了一些事情,可以减轻服务器的压力。我们之前有给token设置了一个有效时间,过期了怎么办,改进行什么操作呢,这时候我们的axios出现啦!

我们用axios去对http进行全局拦截,并把token放在头部,每次请求有返回的都是先经过拦截器的。如果登陆过期,需要重新登陆并清空vuex和localstorage 的token,而且会跳转到login页面。话不多说,我们上代码:

import axios from 'axios'
import store from './store'
import router from './router'


//http 全局拦截
//token 要放在我们请求的header上面带回去给反馈

export default function sexAxios() {
    axios.interceptors.request.use(
        config => {
            if(store.state.token){
                config.headers.token = store.state.token
            }
            return config
        }
    )
        //每次请求有返回的都是先经过拦截器的
    axios.interceptors.response.use(
        response => {
            if(response.status == 200){
                const data = response.data
                if(data.code == -1){
                    //登陆过期 需要重新登陆 清空vuex和localstorage 的token
                    store.commit('settoken','')
                    localStorage.removeItem('token')
                    //跳转到login页面
                    router.replace({path:'/login'})
                }
                return data
            }
            return response
        }
    )
}
复制代码

这里作者就不做过多解释,业务逻辑理清楚啦,有问题的小伙伴可以给我留言或者私信。


写在后面

引用小金鱼的一句话,当然纸上学来终觉浅,绝知此事要躬行。学完理论就需要去实践,大家看完之后一定要自己去操作一下,不然似懂非懂,第二天就忘啦。在此作者再次附上GitHub的地址vue-jingdong (不要吝惜你的小星星哦)。这是一个系列文章,未完待续,期待与你一起学习。如果对你有帮助的话,不妨送上你的star,送人玫瑰,手留余香,谢谢!