一,购物车的删除
1.封装请求删除购物车商品函数
//请求删除购物车商品 /api/cart/deleteCart/{skuId} delete
export const reqDeleteCart = (skuId) => Ajax.delete(`/cart/deleteCart/${skuId}`)
2.在vuex中定义发送请求
//删除一个
async deleteShopCart({commit},skuId){
const result = await reqDeleteCart(skuId)
if(result.code === 200){
return '删除成功'
}else{
return Promise.reject(new Error('删除失败'))
}
},
3.在组件中模板中点击删除按钮,dispatch到vuex中,调用删除的请求,然后在调用发送页面数据的请求,获取新数据
<a href="javascript:;" class="sindelet" @click="deleteCart(cart)">删除</a>
回调
//删除单个的购物车商品
async deleteCart(cart){
try {
await this.$store.dispatch('deleteShopCart',cart.skuId)
//重新发送请求,获取页面数据
this.getShopCartList()
} catch (error) {
alert(error.message)
}
},
回调
//删除选中的多个购物车商品
async deleteChecked(){
try {
await this.$store.dispatch('deleteCheckedShopCart')
//重新发送请求,获取页面数据
this.getShopCartList()
} catch (error) {
alert(error.message)
}
}
4.2,在vuex中处理删除商品的逻辑
//删除一个
async deleteShopCart({commit},skuId){
const result = await reqDeleteCart(skuId)
if(result.code === 200){
return '删除成功'
}else{
return Promise.reject(new Error('删除失败'))
}
},
// 删除多个
deleteCheckedShopCart({commit,dispatch,state}){
let promises = []
state.shopCartList.forEach(item => {
// 没选中的不发送删除请求
if(!item.isChecked) return
// 选中的发送删除请求
let promise = dispatch('deleteShopCart',item.skuId)
promises.push(promise)
})
return Promise.all(promises)
}
二,注册和登录静态页面实现和准备工作,购物车完成,点击结算按钮,应该去创建订单页面
注,src-assets,该文件夹是保存的公共的静态资源,比如图片
登录和注册页面有连接按钮可以互相跳转,需要在各自组件中配置连接路由
1,注册的逻辑及验证码的处理
1,1 封装请求注册接口函数
//请求注册 /api/user/passport/register post
export const reqRegister = (userInfo) => Ajax.post('/user/passport/register',userInfo)
1,2在vuex,user.js中发送请求
const actions = {
async userRegister({commit},userInfo){
const result = await reqRegister(userInfo)
if(result.code === 200){
return '注册成功'
}else{
return Promise.reject(new Error('注册失败'))
}
},
1,3,在组件中,点击完成注册按钮,dispatch到vuex,发送注册请求,然后跳转到登录页面
<div class="btn"> <button @click="register">完成注册</button> </div>
回调
async register(){ let {mobile,password,code,password2} = this if(mobile&&password&&code&&password2&&password === password2){ let userInfo = {mobile,password,code} try { await this.$store.dispatch('userRegister',userInfo) alert('注册成功,自动跳转登录页面') this.$router.push('/login') } catch (error) { alert(error.message) } } },
<input type="text" placeholder="请输入你的手机号" v-model="mobile"> <input type="text" placeholder="请输入确认密码" v-model="password2"> <input type="text" placeholder="请输入验证码" v-model="code"> <input type="text" placeholder="请输入确认密码" v-model="password2">
data(){
return {
mobile:'',
password:'',
code:'',
password2:'',
}
},
注
<!-- 这两种都是ok的,上面的使用的是img图片的src特殊性,发送的普通请求 不跨域 --> <!-- 下面我们使用的是代理服务器转发的,我们认为是跨域的 --> <!-- <img ref="code" src="http://182.92.128.115/api/user/passport/code" alt="code" @click="changeCode"> --> <img ref="code" src="/api/user/passport/code" alt="code" @click="changeCode">
1,4点击验证码图片,重新设置src地址
changeCode(){
this.$refs.code.src = '/api/user/passport/code'
}
三,用户登录逻辑处理
登录:
静态组件
api
store
收集数据发送请求
请求成功后需要把用户信息保存在localStorage用于自动登录
state的用户信息也要修改,
state的用户信息读取先从localStorage里面去读,没有就是{},通过登录去修改
以后每次发请求都要携带这个用户信息的token
修改头部的用户状态信息
1.封账登录接口的函数,userinfo为请求体,需要收集登录账号,和密码
//请求登录 /api/user/passport/login post
export const reqLogin = (userInfo) => Ajax.post('/user/passport/login',userInfo)
在user.js中的vuex中的actions发送登录请求
//登录发送请求
async userLogin({commit},userInfo){
const result = await reqLogin(userInfo)
if(result.code === 200){
//把用户的信息保存起来,为了自动登录(下次再来还可以找到登录状态的用户信息)
localStorage.setItem('USERINFO_KEY',JSON.stringify(result.data))
commit('RECEIVEUSERINFO',result.data)
}
},
在mutations中配置数据
const mutations = {
RECEIVEUSERINFO(state,userInfo){
state.userInfo = userInfo
},
const state = {
userTempId:getUserTempId(),
userInfo: JSON.parse(localStorage.getItem('USERINFO_KEY')) ||{}
}
2.在登录login组件中,收集登录账号和密码.
注:在form表单中,是有默认提交跳转功能的,而button,默认时点击跳转的按钮,此时,需要阻止其默认行为,在vue中需要用到事件修饰符
<form> <div class="input-text clearFix"> <span></span> <input type="text" placeholder="邮箱/用户名/手机号" v-model="mobile" /> </div> <div class="input-text clearFix"> <span class="pwd"></span> <input type="text" placeholder="请输入密码" v-model="password" /> </div> <div class="setting clearFix"> <label class="checkbox inline"> <input name="m1" type="checkbox" value="2" checked /> 自动登录 </label> <span class="forget">忘记密码?</span> </div> <button class="btn" @click.prevent="login">登 录</button> </form>
在data中初始化mobile,password为空。 并且点击登录按钮dispatch到vuex.
async login() {
let { mobile, password } = this;
if (mobile && password) {
let userInfo = { mobile, password };
try {
await this.$store.dispatch("userLogin",userInfo);
alert('登录成功,跳转到首页去了')
this.$router.push('/home')
} catch (error) {
alert(error.message)
}
}
}
computed:{
//从用户的state当中获取用户信息
...mapState({
userInfo:state => state.user.userInfo
})
},
2.然后新建一个p标签,通过登录账号,以及 v-if, v-else,逻辑来判断用户是否登录成功
<!-- 判断用户是否是登录状态,如果是显示这个p --> <p v-if="userInfo.name"> <a href="javascript:;">{{userInfo.name}}</a> <a href="javascript:;" class="register" @click="logout">退出</a> </p> <!-- 如果用户不是登录状态,显示这个p --> <p v-else> <span>请</span> <router-link to="/login">登录</router-link> <!-- <a href="###">登录</a> --> <router-link to="/register" class="register">免费注册</router-link> <!-- <a href="###" class="register">免费注册</a> --> </p>
//登录发送请求
async userLogin({commit},userInfo){
const result = await reqLogin(userInfo)
if(result.code === 200){
//把用户的信息保存起来,为了自动登录(下次再来还可以找到登录状态的用户信息)
localStorage.setItem('USERINFO_KEY',JSON.stringify(result.data))
commit('RECEIVEUSERINFO',result.data)
}
},
const state = {
userTempId:getUserTempId(),
userInfo: JSON.parse(localStorage.getItem('USERINFO_KEY')) ||{}
}
//请求退出登录 /api/user/passport/logout get
export const reqLogout = () => Ajax.get('/user/passport/logout')
async userLogout({commit}){
const result = await reqLogout()
if(result.code === 200){
//退出成功后,去清除state.userInfo的信息 变为{}
// 还要去清除localStorage里面用户信息
localStorage.removeItem('USERINFO_KEY')
commit('RESETUSERINFO')
}
}
RESETUSERINFO(state){
state.userInfo = {}
}
在header组件中,点击退出登录按钮,dispatch到vuex,退出后,跳转到home页
<!-- 判断用户是否是登录状态,如果是显示这个p --> <p v-if="userInfo.name"> <a href="javascript:;">{{userInfo.name}}</a> <a href="javascript:;" class="register" @click="logout">退出</a> </p>
js逻辑
//退出登录
async logout(){
try {
await this.$store.dispatch('userLogout')
alert('退出成功,自动跳到首页')
this.$router.push('/home')
} catch (error) {
alert(error.message)
}
}
//请求拦截器内部一般不会处理错误的信息
service.interceptors.request.use(config => {
//config是发送请求的配置对象,必须处理完返回这个配置对象
//开启我们的进度条
NProgress.start()
//在请求头当中添加用户的临时id,让每个ajax请求都带着这个userTempId(购物车)
let userTempId = store.state.user.userTempId
if(userTempId){
config.headers.userTempId = userTempId
}
//添加用户登录过后的token信息,让每个ajax请求都带这个token,为了找到用户登录后相关信息(订单、购物车)
let token = store.state.user.userInfo.token
if(token){
config.headers.token = token
}
return config
});
注,登录状态下,每次发送请求,请求头都会携带该token
userTempId 未登录状态下的用户身份识别标识
token 登录状态下的用户身份识别标识
两个都存在的话,后台会合并临时id和对应信息到token对应的信息上,主流电商都会这么搞
{
code: 200
message: "成功"
data:{
nickName:"Administrator",
name:"Admin",
token: 90aa16f24d04c7d882051412f9ec45b"
}
ok: true
}<div class="sumbtn"> <router-link to="/trade" class="sum-btn">结算</router-link> <!-- <a class="sum-btn" href="###" target="_blank">结算</a> --> </div>