首页 > 其他分享 >vue3微信公众号商城项目实战系列(6)用户登录

vue3微信公众号商城项目实战系列(6)用户登录

时间:2023-04-17 18:46:07浏览次数:46  
标签:axios 登录 微信 storage 接口 js api vue3 商城

1. 一个商城要实现购物的功能,需要能识别用户的身份,这样才能完成加购物车,下单,付款等操作。

但微信公众号商城和PC端商城有些不一样,区别在于微信公众号商城使用微信支付的时候需要一个openid的参数(以后再具体讲)

这个参数必须访问微信公众号提供的接口才能获取到,基于这个原因,用户登录的时候必须额外调用微信公众号的接口获取openid并保存下来,

以便付款的时候使用。

注:openid也可以在付款这个环节去获取,即时获取即时用,推荐在登录的时候处理。

 

2. 为了简化业务,将重点放在vue3前端技术上,我们的微信公众号商城设计尽可能简洁,用户表结构如下:

表名 字段 功能
userinfo

user_id (int) 用户编号

nickname (varchar) 昵称

acc (varchar) 账号

pwd (varchar) 密码

open_id (varchar) 微信openid

mobile (varchar) 联系电话

address (varchar) 收货地址

用户信息表

 

3. 对于一个商城来说,当用户不登录时是可以以游客的身份浏览商品的,当加购物车的时候再跳转到登录页,

所以登录页有2种类型的入口,一种是在 "我的" tab页,当用户是游客身份的时候要放置一个【登录】的连接;

另一种就是在进行【加购物车】等需要用户身份的时候自动跳转到登录页;

另外,登录页还需要提供注册功能,页面如下图:

当用户输入账号密码的时候,页面要编码调用后端的接口完成登录验证,如果验证通过,就将token及用户信息返回,

返回的信息需要保存到本地,这样后续调用需要用户身份的接口时就不需要重复登录了。

 

4. vue3项目和一般的web服务器项目比如 jsp 、 php 、asp.net  有少许不同,后者不但可以编写页面,还可以直接访问数据库,

而vue3是一个前端框架,它只负责页面的呈现、响应用户的操作,这个过程中需要或产生的数据需要以 ajax 的形式通过 webapi 来和数据库打交道。

vue3中官方推荐的 ajax 包是 axios , 可以用它来处理各种服务端的 webapi 请求,

官网地址:https://www.axios-http.cn/docs/intro,官方文档截图如下:

 

5. 使用 axios  非常简单:

第1步:安装 axios 包 , 命令: npm install axios,如下图:

安装完成:

 

第2步:导入 axios 并使用 Axios API 调用 后端的 webapi ,具体可以参考文档。

本系列中会对 Axios API 做封装,方便后续维护。

另外,用户登陆后需要在本地存储 token等信息以便其他接口使用,还需要对 token等信息做持久化处理。

 

6. 完整步骤如下:

第1步:新增如下文件夹和文件

storage.js持久化登录后的用户信息,request.js封装axios请求,api.js 记录具体的api接口,Login.vue是登录页面,代码分别如下。

storage.js 代码

 

const storage = {
    set:function(val) {
        localStorage.removeItem("userinfo");
        localStorage.setItem("userinfo", JSON.stringify(val));
    },
    get:function(){ 
        let info =  localStorage.getItem("userinfo"); 
        if(!info || typeof info == "undefined"){  
            return {};
        }
         
        try{  
            return JSON.parse(info);
        }
        catch(e){
            return {};
        } 
    },
    clear:function(){
        localStorage.removeItem("userinfo")
    },
    check:function(){
        let info =  localStorage.getItem("userinfo"); 
        if(info && info.length>1){
            return true;
        }
        return false;
    }
}


export default storage;

 

定义了一个storage对象,该对象有4个方法,分别用户处理持久化在本地的用户信息,localStorage 是浏览器上的全局对象

,我们用 storage 做了一下封装,如果以后要更换持久化的方式,在这里改就可以了,外部的调用不变。

注:

1. 微信浏览器内核是QQ浏览器X5内核。

2. localStorage的几个方法都需要一个key值,我们这里固定为 userinfo,实际项目也可以给 storage 的几个方法加个key的参数,这样可以从外部传入。

 

 

request.js 代码

import axios from 'axios';
import storage from '@/http/storage.js';


//配置默认的Content-Type格式
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';

//创建axios实例
const service = axios.create({   
    timeout: 60*1000, //请求超时时间60秒
    baseURL: '/dev-api',
})


//请求拦截器
service.interceptors.request.use(config => {  
    //***在发送请求之前做些什么*** 
    if(storage.check()){ 
        //如果已登录就把token信息加到请求头中,不同的webapi这里的添加方式不一样,这是ASP.NET的写法
        let info = storage.get(); //获取存储在本地的token信息
        config.headers['Authorization'] = 'Bearer ' + info.token 
    } 
    return config;
}, error => {  
    //***对请求错误做些什么***
    return Promise.reject(error);
})


//响应拦截
service.interceptors.response.use(response => {
    //***2xx 范围内的状态码都会触发该函数***
    //***对响应数据做点什么***
    return response.data.data; 
}, error => {   
    //***超出 2xx 范围的状态码都会触发该函数***
    //***对响应错误做点什么***
    return Promise.reject(error); 
})


//导出实例对象
export default service;

这里的代码基本上是从axios上复制而来,只在请求拦截器上加了一个校验,如果 持久化存储中的 userinfo 有值,就把 token 加到请求头中,userinfo 的 json 格式如下:

{
userId:111,
nickname:'张三',
acc:'abcd1'
pwd:'1',
open_id:'xxxxx',
mobile:'15900008888'
address:'阳光大道123号豫王府2栋1单元1601',
token:'xxxxxxxxxxxxxxxxx'
}

每段代码都有注释,重点说一下 "baseURL: '/dev-api'," 这一段,baseURL 是请求的基地址 , 先看 官方文档上的解释:

它可以是一个完整api接口前缀 , 也可以是本文上面配置的 "/dev-api" ,配置完后,我们调用接口的时候

,实际的请求地址会和 baseURL 拼接成完整的地址作为最终的接口地址,这里我们为什么要配置成  "/dev-api"的形式

,而不用完整的地址呢,接下来会讲到这样做的目的。

api.js 代码:

import request from './request.js'

//登录接口
//write by: 屏风马
//date : 2023-4-17
export function signin(data) {
    return request({
      url: '/sign/signin', 
      method: 'post',
      data: data
    })
}

这里对每个接口请求做了封装,统一放置在这里,如果有其他接口,只需要在这里加方法就可以了

,import request 就是 request.js中导出的service对象,它代表的是一个配置好的 axios 实例对象,return request( ) 传入的参数是一个 json 对象

,url 是接口地址 , 实际请求会和 baseURL 拼接后再发送出去,如果 baseURL = 'https://some-domain.com/api/' ,那么实际请求地址

就是 'https://some-domain.com/api/sign/signin' ,相应的, 如果baseURL = '/dev-api' ,那么实际请求地址就是 '/dev-api/sign/signin' 。method和

data分别表示请求的参数和方法。Login.vue页面调用的时候只需要传入请求的参数就可以,非常简洁,因为所有接口都在这个文件中,后期如果

要改接口对应的路径,比如部分路径不符合 RESTful 风格可能要调整,直接到这个文件修改就可以了,否则,大量的接口 url 散落在项目的各个文件中

,维护起来就比较头大。

 

Login.vue 代码

 1 <template>
 2     <div class="login"> <br /> 
 3         <div><span>用户登录</span></div> <br />
 4         <div>
 5             <dl>
 6                 <dd>账号</dd> 
 7                 <dt><input name="acc" v-model="loginForm.acc" /></dt>
 8                 <dd>密码</dd>
 9                 <dt><input name="pwd" v-model="loginForm.pwd" /></dt> 
10                 <dt><input type="button" value="登录" @click="onLogin" /></dt> 
11                 <dt>没有账号?去注册</dt>
12             </dl> 
13         </div> 
14     </div>    
15 </template>
16  
17 <script setup>
18 import { reactive } from 'vue';
19 import { useRouter } from "vue-router";
20 import { signin } from "@/http/api";
21 import storage from '@/http/storage.js';
22 
23 const router = useRouter();
24 const loginForm = reactive({
25     acc: 'abcde',
26     pwd: '1'
27 })
28 
29 function onLogin() { 
30     signin(loginForm).then(res=>{  
31         storage.set(res);
32         router.push({name:'home'});
33     }); 
34 } 
35 </script>
36  
37 <style>
38 .login{
39     width: 370px;
40     margin: 0 auto; 
41     text-align: center;
42 }
43 </style>

我们逐行分析一下这里的代码:

第7行和9行是一个输入框对象,上面有一个 v-model的属性 , 它对应的是 24 行定义的 loginForm 对象的2个属性,这种写法是 vue3 的绑定语法

,任何一个 json对象都可以用 vue3 框架内置的 reactive() 函数处理一下,这样做的结果就是 <script>代码块中的 loginForm 对象的2个属性和

输入框的 v-model 属性进行了绑定,当用户在页面上修改 输入框的值时 , loginForm 对象中的属性被同步修改了,反之亦然, 即做到了输入框的值和

代码中的值数据完全同步 !这就是 vue3 的响应式编程的双向数据绑定,如果用传统的3件套来写,取值赋值及onblur事件都要写一堆的代码,效率很低。

这些问题在 vue3 中只要用 reactive( ) 把一个 json对象处理一个就解决了全部的问题。

第10行是一个按钮,上面有一个click事件,只要在 click 前面加上 @ 符号,后面的字符串 "onLogin"  就和 <script>代码块中的

函数 function onLogin() { }绑定在一起了,当用户点击登录按钮的时候就会执行 onLogin() 这个方法。

第18行 , reactive 是 vue 框架中的函数,使用前要先导入进来。

第19行,useRouter 是路由对象 vue-router 中的函数,如果不用 <router-link>标签来导航而用编程的方式(类似 location.href )来跳转需要用到这个函数。

第20行,导入 api.js 中的 signin 方法,因为接下来登录会用到它,如果要用到多个,用逗号隔开就可以了。

js 文件导入时可以省略 .js 的后缀名。from 后的 @ 代表路径 "/src" ,因为它的使用频率很高,就用 @ 代替,这是在 vite.config.js中配置的,如下:

 

resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url))
      }
    },

第21行,导入 storage 这个对象用来存储登录成功后 接口端传递过来的用户信息,其 json 格式上面有介绍。

第29行,这个函数响应用户的登录操作,signin( ) 是 api.js中暴露出来的登录接口对应的函数,只需要传入 loginForm 就可以了

,因为它是一个响应对象 ,同步记录了用户的输入,一些都是那么简单

,signin() 的返回值是一个 Promise 对象执行成功后用 .then( ) 来处理返回值,传入一个箭头函数

,先把返回值 存储在了 localStorage 中,然后用 23 行生成的 路由对象的 push 方法跳转到 home 这个页面。

关于 router 对象:

1. 导航到另一个页面用 router.push 方法,从方法名可以看除了导航到目标页面外,它还把页面压入栈中

,这样当用户点返回按钮的时候就能退回到上一个页面,而不需要我们在程序中做任何处理。

2. router 可以带参数,这个后面根据情况具体讲。

3. 这里的 router 是根据路由表中定义的名称来导航的,见 /src/router/routerx.js 中的配置:

 

const routes = [
    {path:"/",name:'welcome',component:()=>import("../views/Welcome.vue")},
    {path:"/home",name:'home',component:()=>import("../views/Home.vue")},
    {path:"/login",name:'login',component:()=>import("../views/Login.vue")},
]

 

我们还可以根据 path 属性来导航,为了整个项目风格统一,我们就用 name 来导航。

4. 每一个页面都需要在上面的 routers 数组中预先配置好,这样不至于导航的时候找不到对应的页面。登录 login.vue 能够访问是因为这里做了配置。

接下来,我们在 chrome 中模拟访问 /login 页面, 如下:

页面报错了,这是因为在 request.js 中把 baseURL 设置成了 "/dev-api",这个路径因为没有完整的URL,axios 默认给我们把当前开发 web 服务器的ip 加上去了,如下图:

实际项目中,后端接口是另一个小组的同事在写,为了开发方便,这个接口写好后通常会部署在公网的一台开发服务器上,方便前端同事调用

,其接口地址类似:https://some-domain.com/api/sign/signin,所以我们需要配置后端接口所在的开发服务器,打开 vite.config.js , 加入如下的配置信息:

server: { 
    host: true,
    port:80,
    open:true, 
    proxy:{
      '/dev-api':{
        target: 'http://testapi.xxx.com/api',
        changeOrigin: true, 
        secure: false, 
        rewrite:(path)=> path.replace('\/dev-api', '')
      }, 
    } 
  },

host 可以是开发服务器所在的 ip 地址 , 如果不限 ip , 用 true 就可以。port 是端口号,默认是 5173,这里我们改成 80 ,这样在chrome中调试就可以省略端口号了。

proxy 用于配置代理服务器信息。在开发阶段,后端接口服务地址前缀一般是这样的 "http://testapi.xxx.com/api/" ,我们本机开发环境运行vue3项目是 localhost:5173

, 去访问远程服务器时会存在跨域问题,这是因为 vue3 项目是运行在浏览器内核上的,如果访问的服务器域名+端口+协议(https和http是不同的协议)不同

,浏览器就认为跨域了,会禁止访问,所以在这里配置代理信息,当我们的访问网址中含有 "/dev-api" 这个路径的时候,就以  'http://testapi.xxx.com/api' 的名义去访问

,这样原来的地址 "http://localhost:5173/dev-api/sign/signin" 会被 axios 代理成 "http://testapi.xxx.com/api/dev-api/sign/signin"

,配置中的属性 rewrite 是用正则表达将路径中的 "'/dev-api'" 替换成空字符串,所以实际的代理地址是 "http://testapi.xxx.com/api/sign/signin"

,这正是我们要访问的真是地址。

 

将浏览器地址中的端口去掉,刷新页面后点登录按钮如下:

登录成功,并跳转到了 Home.vue 页面。

 

标签:axios,登录,微信,storage,接口,js,api,vue3,商城
From: https://www.cnblogs.com/pfm33/p/17321197.html

相关文章

  • Vue3 ref函数处理基本类型或对象类型
    基本类型视频对象类型视频2.ref函数作用:定义一个响应式的数据语法:constxxx=ref(initValue)创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。JS中操作数据:xxx.value模板中读取数据:不需要.value,直接:<div>{{xxx}}</div>备注:接收的数据可以是:基本......
  • ECShop开源商城与COS互通:降低本地存储负载、提升访问体验
    ECShop简介ECShop是一款开源电子商务平台,具有简单易用、安全稳定、模块化设计等特点。它提供了完整的电子商务解决方案,包括商品管理、订单管理、支付管理、配送管理、会员管理、促销管理、数据统计等功能。ECShop支持多语言、多货币、多种支付方式和配送方式,并可通过插件扩展更多......
  • vue全家桶进阶之路32:Vue3 WatchEffect和watch 监听
    在Vue3中,watchEffect是一个用于监听响应式数据变化的API。它可以在函数内部自动跟踪数据的依赖,并在依赖变化时重新运行函数。watchEffect 的作用以及各个参数的功能讲解:watchEffect(effect:(onInvalidate:InvalidateCbRegistrator)=>void|(()=>void)|Promise<vo......
  • 【vue3-element-admin】Husky + Lint-staged + Commitlint + Commitizen + cz-git 配
    前言本文介绍vue3-element-admin如何通过Husky+Lint-staged+Commitlint+Commitizen+cz-git来配置Git提交代码规范。核心内容是配置Husky的pre-commit和commit-msg两个钩子:pre-commit:Husky+Lint-staged整合实现Git提交前代码规范检测/格式化(前提......
  • Vue3中 如何使用ref标签,对组件进行操作
    在Vue2中一般用this.$ref.xxxx进行获取组件对象Vue3中就不使用这个方法了例如:<el-uploadclass="upload-demo"action="":http-request="handleUpload":on-change="handleChange":before-upload="handl......
  • 直播小程序源码,小程序生成二维码 (兼容H5、微信小程序)
    直播小程序源码,小程序生成二维码(兼容H5、微信小程序)1、<canvastype="2d"style="width:127px;height:127px;position:fixed;top:-1000px;"id="myQrcode"></canvas>注意:不能再v-if内,否则会导致找不到该节点 2、importdrawQrcodefrom'@/common/qrcodeJs......
  • vue3中使用ref语法糖
    自从引入组合式API的概念以来,一个主要的未解决的问题就是ref和响应式对象到底用哪个。响应式对象存在解构丢失响应性的问题,而ref需要到处使用.value则感觉很繁琐,并且在没有类型系统的帮助时很容易漏掉.value写法优化以上是官方原话。大概就是新的语法糖可以让我们......
  • Vue3 vue-cli创建工程的工程结构分析
    视频不能用vue2的写法了componentsHelloWorld.vue<template><divclass="hello"><h1>{{msg}}</h1><p>Foraguideandrecipesonhowtoconfigure/customizethisproject,<br>checkoutthe......
  • vivo全球商城:电商交易平台设计
    vivo全球商城:电商交易平台设计 作者:vivo官网商城开发团队-ChengKun、LiuWei本文介绍了交易平台的设计理念和关键技术方案,以及实践过程中的思考与挑战。点击查阅:《vivo全球商城》系列文章一、背景vivo官方商城经过了七年的迭代,从单体架构逐步演进到微服务架构,我们......
  • 前端学习笔记——Vue3组件间数值传递
    依据个人的学习需求,对Vue官网中组件部分内容的搬运和总结,可用于参看,想详细了解Vue3这部分特性的可以直接参考官网内容:https://cn.vuejs.orgprops是一种特别的attributes,我们可以在组件上生命注册。比如:如果我们要传递给博客文章组建一个标题的话,我们则必须在该组件的props列表......