尚品汇项目搭建

一些问题

在这里插入图片描述

2.<html lang="en">

3.在使用 vuex的时候出现 commit 未定义错误

默认暴露情况下,在引入的时候,是不需要加{}

package.json中 --open是自动打开
// “serve”: “vue-cli-service serve --open”,
5.:把import router from "./router"中的router改成小写router的就行了,文件夹起啥名没关系,但是引入的时候,必须命名为router,要不然识别不出来

6.注意,这个地方不能写 this.searchParams.trademark=undefined,如果写了undefined的,就会报错Cannot read properties of undefined (reading ‘split‘),
需要写this.searchParams.trademark=“”; 因为undefined是不能被分割的
7.设置为某个路由组件的children组件的时候,router-link router-view

大体流程

1.首先components里面创建Header和Footer,然后pages(里面四个) 然后是Router,使用routerview,设置应该显示的位置 在网页中设置路径,观看是否已经设置成功了
2.设置Header中的路由跳转,一些a标签全部设置为router-link
3.显示隐藏footer组件
4.点击搜索按钮获取数据

一、基础配置

前面配置参考

请添加图片描述

2.1 项目运行自动打开浏览器,在package.json文件中这段代码的serve后面加上 --open

"scripts": {
    
    
        "serve": "vue-cli-service serve --open",
        "build": "vue-cli-service build",
        "lint": "vue-cli-service lint"
    },

2.2eslint校验工具关闭
eslint:检测语法是否正确
在根目录下创建.eslintrc.js
作用:避免不规范时浏览器报错,不然继续执行

module.exports = {
    
    
    root: true,
    env: {
    
    
      node: true
    },
    'extends': [
      'plugin:vue/essential',
      'eslint:recommended'
    ],
    parserOptions: {
    
    
      parser: '@babel/eslint-parser'
    },
    rules: {
    
    
      'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
      'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
       //在rules中添加自定义规则
       //关闭组件命名规则
       "vue/multi-word-component-names":"off",
    },
    // overrides: [
    //   {
    
    
    //     files: [
    //       '**/__tests__/*.{j,t}s?(x)',
    //       '**/tests/unit/**/*.spec.{j,t}s?(x)'
    //     ],
    //     env: {
    
    
    //       jest: true
    //     }
    //   }
    // ]
  }
  
  

2.3src文件夹简写方法,配置别名 @
根目录下创建jsconfig.json ,用@/代替src/,exclude表示不可以使用该别名的文件

{
    
    
    "compilerOptions": {
    
    
        "baseUrl": "./",
        "paths": {
    
    
            "@/*":[
                "src/*"
            ]
        }
    },
    "exclude": [
     //@不能使用的地方
        "node_modules",
        "dist"
    ]
}

请添加图片描述

  1. 引入文件的时候,引入的是.less,所以事先下载一个less插件

npm i less
npm i less-loader
两个都要下载,有的时候还需要指定版本
在这里插入图片描述

  • 不要安装在最新版本,安装最新版本less-loader会报错,报的错误setOption函数未定义
  • 需要在style标签的身上加上lang=“less”,不添加样式不生效

路由

在package.json中查看版本

在文件目录cmd,安装vue-router
npm install --save vue-router@3
新建一个routerxx文件夹,里面新建一个index.js,在里面输入

import Vue from "vue"
import VueRouter from "vue-router"
Vue.use(VueRouter)

export default new VueRouter({
    
    
routes:[
{
    
    }
]
})

在main.js中引入,

import router from "./routerxx"
然后在里面也要加上router
new Vue({
    
    
  router,
  render: h => h(App),
}).$mount('#app')

请添加图片描述
请添加图片描述

在这里插入图片描述
不使用这种方法,使用路由元信息
请添加图片描述

7)路由的跳转

路由的跳转就两种形式:声明式导航(router-link:务必要有to属性)
编程式导航:利用组件实例的$router.push||replace
编程式导航更好用:因为可以书写自己的业务逻辑

8)路由传参

params参数:路由需要占位,程序就崩了,属于路径URL当中一部分
query参数:路由不需要占位,不属于路径URL当中一部分,写法类似于ajax当中query参数,/home?k=v&kv=,

this.$router.push({name:“search”,params:{keyword:this.keyword},query:{k:this.keyword.toUpperCase()}})

路由传递参数面试题
1:路由传递参数(对象写法)path是否可以结合params参数一起使用?
不可以:不能这样书写,程序会崩掉,我们用的name和params
2:如何指定params参数可传可不传?
配置了路由,占位了(params参数),但是路由跳转的时候不传递,路径会出现问题)
在配置路由的时候,在占位的后面加一个问号,表示可传可不传
3:params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
传递空字符串会造成路径错误,可以使用undefined解决、
this.$router.push({name:“search”,params:{keyword:‘’||undefined},query:{k:this.keyword.toUpperCase()}})
4:如果指定name与params配置, 但params中数据是一个"", 无法跳转,路径会出问题
5: 路由组件能不能传递props数据?
//可以传递(三种方法,Vue笔记4)
请添加图片描述

编程式导航路由跳转到当前路由(参数不变), 多次输入相同的参数搜索就会抛出NavigationDuplicated的警告错误?
注意:编程式导航(push|replace)才会有这种情况的异常,声明式导航是没有这种问题,因为声明式导航内部已经解决这种问题。
这种异常,对于程序没有任何影响的。 为什么会出现这种现象:
由于vue-router最新版本3.5.2,引入了promise,当传递参数多次且重复,会抛出异常,因此出现上面现象,
第一种解决方案:是给push函数,传入相应的成功的回调与失败的回调
this.$router.push({name:“search”,params:{keyword:this.keyword},query:{k:this.keyword.toUpperCase()}},()=>{},()=>{})
第一种解决方案可以暂时解决当前问题,但是以后再用push|replace还是会出现类似现象,因此我们需要从‘根’治病,重写方法。

9)重写replace|和push方法

//先把VueRouter原型对象的push,先保存一份
let originPush=VueRouter.prototype.push;
let originReplace=VueRouter.prototype.replace;
//第一个参数:告诉原来的push方法,你往哪里跳转(传递那些参数)
/* call和apply区别
相同:都可以调用函数一次,都可以篡改函数的上下文一次
不同:call和apply传递参数,call传递参数用逗号隔开,apply方法执行,传递数组
*/
VueRouter.prototype.push=function(location,resolve,reject){
    
    
    if(resolve&&reject){
    
    
        //不使用call方法,this就是window,就不是push原来的上下文了
        originPush.call(this,location,resolve,reject)
    }
    else{
    
    
        originPush.call(this,location,()=>{
    
    },()=>{
    
    })
    }

}

VueRouter.prototype.replace=function(location,resolve,reject){
    
    
    if(resolve&&reject){
    
    
        //不使用call方法,this就是window,就不是push原来的上下文了
        originReplace.call(this,location,resolve,reject)
    }
    else{
    
    
        originReplace.call(this,location,()=>{
    
    },()=>{
    
    })
    }

}

10)router和route

$router:进行编程式导航的路由跳转
this.$router.push|this.$router.replace
$route:可以获取路由的信息|参数
this.$route.path
this.$route.params|query
this.$route.meta

在这里插入图片描述

axios

npm install --save axios请添加图片描述
请添加图片描述

引入进度条

npm install --save nprogress
打开package.json查看是否安装成功
在api文件夹中的request.js

在这里插入图片描述

请添加图片描述

vuex

npm install --save vuex@3
(记得在main.js中全局引入!!!!)
当项目比较大,组件通信数据比较复杂,这种情况在使用vuex

   Vuex是插件,通过vuex仓库进行存储项目的数据
   
   
   vuex:Vue官方提供的一个插件,状态管理库,插件可以管理项目共用数据。 vuex:书写任何项目都需要vuex?
   项目大的时候,组件很多,数据很多,需要有一个地方‘统一管理数据’即为仓库store state mutations actions
   getters modules
   
   vuex模块式开发【modules】
   由于项目体积比较大,你向服务器发请求的接口过多,服务器返回的数据也会很多,如果还用以前的方式存储数据,导致vuex中的state数据格式比较复杂。采用vuex模块式管理数据。
   Vuex核心概念:state、actions、mutations、getters、modules
   
   {
       state:{
            a:1,
            b:2,
            c:[],
            d:{}
       } }
   
   //模块式开发 {
       state:{
           home:{a:1},
           search:{},
           detail:{}
       } }

TypeNav
2)将Home组件的静态组件拆分(7个)
2.1静态页面(样式)
2.2拆分静态组件
2.3发请求获取服务器数据进行展示
2.4开发动态业务
拆分组件:结构+样式+图片资源

写接口,获取三级联动数据 categoryList

  • 移动上的时候,背景颜色蓝色,不移动上去的时候 蓝色去掉
  • 三级联动界面在哪个页面进行显示(show)
  • transition动画效果
  • 点击logo返回home界面
    节流+防抖
    点击搜索跳转goSearch()
    三级联动界面,怎么判断点击的是哪个,使用自定义属性(注意,得到的全是小写)console.log(event.target.dataset);// 先打印一下看看,发现属性的名字不管是大写还是小写,这个地方都是小写
    在这里插入图片描述

三级联动

  • 展示三级联动的样式,主要是先通过接口和数据库连接上,然后使用vuex发送请求数据获得数据,
  • 主要用到mapState中的actions,mutations等等这些东邪,将获取到的数据通过v-for遍历出来,注意,可以先打印出来,观察一下结构是什么样的
  • 设置三级联动的样式,通过事件委派
    1.直接通过css设置
  • 2.通过js:index代表索引,可以通过获取所以判断鼠标移入到那个标签上了,绑定一个鼠标移入函数,获取到索引,设置一个currentIndex代表,初始值为-1,代表不显示任何的背景颜色,获取到索引值后,动态的添加class样式cur,(通过判断索引值是否相等),
  • 当鼠标移出的时候,再将索引值设置为-1(有个小bug,移入到商品分类的时候,背景颜色是存在的,所以更改当前的框架,让全部商品当三级联动样式有一个相同的div)

二三级分类,谁有背景颜色,谁显示,设置动态的style,记得加单引号
三级组件的节流防抖

三级地址路由跳转
请添加图片描述
利用编程式导航和路由的委派实现路由跳转和传递参数 将goSearch加在最外面的div上是因为,这样的话,只需要生成一个回调函数,但是麻烦也在于我们如何判断点击的是a标签,以及如何判断点击的标签的名字以及id之类

防抖节流

防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发,只会执行最后一次请添加图片描述
节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发
请添加图片描述

lodash官网
防抖函数
节流函数
已经存在ladash了

导入和暴露用法需不需要加{},这个地方都写了

Home组件

1.先写Header Footer,然后把Home(包括七个)和Search界面搭起来,
Header上面的文字和logo的跳转(router-link),Header的搜索框,这个地方比较难,涉及到参数,记得显示的时候,如果用params参数,记得在路由的地方占位

2.Home组件
其中TypeNav被各个使用所以设置为全局组件

每一次从home到search,都会有mounted,所以我们将show的改变可以写在这里面

1.加上TypeNav,并且需要设置隐藏显示(添加一个属性show 和添加属性currentIndex很类似)和动画(只有和v-if v-show搭配,才可以设置动画)
2.TypeNav的优化
因为每次都执行一个mounted,导致getBaseCategoryList请求多次发送,所以我们将请求放在APP组件中,只执行一次,但是不能main.js中,虽然也是执行一次,但是this??是谁,我们需要的vue组件,我们通过this.$store给组件派发请求,然后储存在仓库中,组件需要的时候,就去仓库中拿取

3.点击三级组件-query参数,点击搜索,params参数
注意,在提交params参数的位置加上query参数,
在提交query参数的地方加上params参数
请添加图片描述

轮播图

mock

4.mock
npm install mockjs
mock发送数据的时候,不是真正向后端发请求的是,而是自己模拟的数据

首先自己生成模拟数据

在api新建mockAjax(书写请求代码),(仓库三连环)
在index中引入请求暴露请求,
在ListContainer中向store发出dispatch请求,
在actions,mutations中处理,
最后ListContainer接受请求 mapState

swiper官网
下载,把package包中的css,js带走

中文教程,在new Swiper之前,一定要有结构

https://www.swiper.com.cn/usage/index.html

npm install --save swiper@5

在这里插入图片描述
在这里插入图片描述
2)开发floor组件
两个相同的floor组件不是写出来的,是遍历出来的,这样的话,遍历的floor组件就会携带不同的信息
请添加图片描述

共用组件Carousel

把floor组件和banner组件中的轮播图封装起来,便于多次使用,
封装成公共的,使用的时候只需要向公共的传数据即可
(在这里只封装floor,banner留着对比)
1.带走html格式
2.带走watch数据
3.定义成全局组件
4.在需要使用的组件内引用并传参

二.search页面内

1.axios发请求,可以
axios.get(“url”);
axios({})

查看接口格式

  • 去main.js 测试这个接口,一定要注意,至少是一个空对象,然后在控制台的network中刷新查看
  • 验证一个接口返回的数据格式
    在这里插入图片描述
    如果在仓库里,一直没有数据,记得点一下search按钮

发送请求获取数据

  • 去仓库中取数据,用mapGetters简化
  • 完成销售产品goodlist的展示
  • 在子组件中完成 ‘trademarkList’,"attrsList"的展示,书写中间的框框,品牌以及每一个牌子的属性,在searchSelector那个组件里面(首先获取仓库中的数据,获取之后查看是否成功获取,然后遍历显示)
  • 合并所有的搜索,并且多次发送请求(监视路由)

面包屑相关

  • 面包屑(生成显示面包屑/删除面包屑,删除时要发生路由的跳转更新呢数据,路径里面的路由信息也要 发生变化)
    出错是因为在监视的路由的时候将所有的参数都置为空了

  • 面包屑处理关键字(删除面包屑/清空搜索框(全局事件总线)/更改路由)

  • 面包屑处理品牌的点击(子将点击的元素传递给父,父发送请求,自定义事件)

  • 其他售卖属性的处理,也传递给父组件,传递之后,点击的元素也加入到面包屑当中

在这里插入图片描述

路由没有改变的时候,一定要加上this.getData();,路由改变,可以依靠监视之中的watch,没有改变的,一定要加!!!因为有些地方会引起路由的改变,路由又被监视了,所以有的时候是不需要再次发起请求的,路由里面有发起请求

Object.assign

在这里插入图片描述

阿里图标库

vue 项目中使用阿里巴巴矢量图标库
地址链接
首先加入购物车,添加项目中,可以生成在线链接,然后引入到index.html中,link引入的时候,注意把链接前面补充上协议(https:)

动态添加样式和图标的切换在这里插入图片描述
在这里插入图片描述

升序降序

把是升序还是降序给后端接口传递传递过去了,至于升序降序排序就是后端进行的事情,然后将拍好的数据传递给我们
1.使用计算属性方便,点击的时候改变样式改变箭头方向
请添加图片描述

分页器

1.把分页器定义成全局组件,因为有可能会多次使用(定义并全局注册)
2.先传入一些假数据进行测试,再与服务器进行连接
pageNo:当前处在那一页
pageSize:每页展示数据的个数
total:数据总数
continues:页面标签连续的个数
3.把整体架构搭建出来,分页器的样式,在父组件内引入

  • 计算总页数,计算连续显示的起始值Start和结束值end
  • 根据起始值和结束值判断哪个button应该显示,连续的部分是遍历end得到的(1->end)(v-for是可以遍历数字的(数组,数字,字符串,对象都可以)),同时要隐藏多余的,只显示连续个数
  • 第一页和最后一页时 禁用上下一页按钮
  • 通过自定义函数实现上一页下一页和点击切换 $emit(传递的是PageNo这个属性)
  • 动态显示class,有判断条件,点击的数字的背景颜色改变

vue 中的const {XXX } =this 的作用效果

const {
    
     xxx } = this.state;
上面的写法是es6的写法,其实就相当于:

const xxx = this.state.xxx

在这里插入图片描述

遍历下标,并且隐藏掉不想要的

三.详情页开发

1.捣鼓静态组件

  • 注册为路由组件
  • 告诉detail点的是哪一个,所以跳转的时候携带信息
  • 点击图片跳转
  • 优化route文件夹
  • 跳转的时候,滚动条在哪个地方 vue跳转滚动行为

2.向服务器请求数据

  • 写接口 api中index.js
  • vuex 获取产品详情信息 新建一个detail.js,在总的仓库中引入
  • 在index.vue发请求捞数据(在控制台仓库看看捞取成功了吗)

如果仓库中没有数据,在network中看看请求发送成功了吗,没发送成功可能是参数大小写,可以先打印一下看看有没有

3.动态展示导航条和右侧的简介信息

从仓库中要数据,getters简化数据
把放大镜图片数据 从detail组件传递给detail的子组件
传递数据中,先从开发者工具 组件中查看一下数据是否传递过去了
,这个地方有一个很严重的空数组问题

放大镜

4.拆分遍历 放大镜右边的信息
5.产品的售卖属性值切换高亮,记得给函数传参,告诉函数点击的是哪一个,再把全部参数传过去,方便修改

6.轮播图+容器内有三张图片,每次切换一张
+点击哪张图片,就给哪张图片加换色边框(先不要用css,练习一下js)
7.小图点击哪张图片,大图显示哪一张(兄弟组件之间的通信)
8.放大镜的一些其他操作

  • offsetX表示鼠标指针的水平坐标

  • offsetWidth是一个只读属性,返回一个元素的布局宽度

  • 先确定绿色遮盖层的移动,并且约束它的位置

  • handler方法里面不需要加event
    鼠标右移,对于大图里面的图片来说,是图片左移
    请添加图片描述

购物车

进行api请求的时候,把method写成methods了,无法正常发送请求
1.购物数量加减
2.用户修改产品个数时候,怎么判断非法数据(isNAN/不能是负数/小数取整)
3.购物车路由跳转之前,要先将产品的id和个数传给服务器(写接口/连接接口/)派发action:这次的派发的action的时候要带着参数,我们是把数据传递给服务器,所以服务器这次不需要传递给我们数据,因为服务器都没给我们传数据,所以我们都不用三连环存了

成功与失败的结果在谁那?在仓库那里

一个函数,加上了async,返回的一定是promise,所以
addorUpdateShopCart这个函数返回的是promise,要么成功,要么失败,也就是下面这一句话的返回结果result是个promise

result=this.$store.dispatch("addorUpdateShopCart",{
     
     skuId:this.$route.params.id,skuNum:this.skuNum})

try后面加成功 catch后面加失败

4.将AddCartSuccess注册成路由组件 跳转+将产品的信息也带过去
路由传递params或者query传递,不好,因为变成字符串乱码了,

  • 一些简单的信息数据,可以通过路由传递过去(id通过这个携带)
  • 但是向商品信息,通过会话存储,持久化,但是本地存储或者会话存储,一般存储的都是字符串,不能存对象(通过JSON转化)

5.引入shopcart组件
to要不要加:取决于是不是动态的
展示静态组件,这个地方有点问题,需要删con3,并且重新修改一下大小

四.addCartSuccess开发

1.获取购物车数据

1.写接口/cart/cartList
2.在仓库中新建一个模块,引入到大仓库中
3.三连环,派发actions

问什么不会请求不到数据呢?因为服务器不知道who are you?
在这里插入图片描述

使用uuid生成随机的id

2.发现包已经下载了(74集)
在这里插入图片描述
3.

  • detail.js中的state中添加一个游客临时身份

  • 新建一个util文件夹,封装游客身份模块,暴露一个函数,来确定本地存储有没有id,如果没有,随机生成一个

  • 在ajax.js中,在请求头中加入信息,可以确保把id加入到随机序列中,config.headers中的信息可以在network中查看
    在这里插入图片描述

  • 最终,多次刷新,发现uuid是不变的,而且不会重复的
    在这里插入图片描述

4.当仓库中能获取数据后,(数据格式不完美)三连环,然后在shopCart中的index.vue取数据,然后查看一下shopCart仓库和组件中是否分别都有数据了
简化一下数据cartList

5.捞到数据,并且简化之后,我们就要在ShopCart.vue中展示了,将所有需要的数据展示清楚之后,(遍历)

  • //勾选框是否勾选(isChecked)
  • //计算购买商品的总价,函数totalPrice
  • //判断左下角的全选, isAllchecked(函数),如果上面的全选了,就√上,用到封装的every函数

every函数

在这里插入图片描述

请添加图片描述
如果我们向查看CartInfoList中所有的isChecked是不是1,如果是,返回true,有两种做法

    isAllchecked() {
    
    
      // 判断所有的isChecked是不是1,如果是,res=1,如果不是 res=false
      let res = this.CartInfoList.every((item) => {
    
    
        return item.isChecked == 1;
      });

      return res;
      // let count = 0;
      // let res =true;
      //  this.CartInfoList.forEach((item) => {
    
    
      //   if (item.isChecked != 1) {
    
    
      //     count++;
      //   }
      // });
      // if (count > 0) res = false;
      // return res;
    },

购物车界面

  1. 在购物车结算的界面,更改数量:
  • 是需要要发请求的,告诉服务器我改数据, 要是不发请求,刷新之后还是原来的数(但是发请求的时候携带的参数要注意)参数应该后来状态数值-起始状态数字 handlerNum函数
  • + - 或者在对话框内输入值,三种情况派发的action是同一个,但是我们可以传值进行区分
  • 修改可以使用Switch进行修改,注意这个地方也需要获取服务器中的数据是否修改成功,也就是这个地方也需要使用async+await
  • (要节流,避免因为更改过快,造成数据变成负数的情况)
    在这里插入图片描述

7.删除购物车商品的操作

  • 写删除购物车的接口/cart/deleteCart reqDeleteCartById
  • 在仓库中写actions,注意这个也是不需要数据的,只需要知道修改是否成功即可 deleteCartListBySkuId
  • 点击删除按钮,派发action deleteCartById

8.修改产品的勾选状态,也需要向服务器发请求,告诉服务器我修改勾选状态了,在后端将勾选状态也改过来

  • 先写接口 reqCheckedById
  • 在仓库里写请求 checkedById(注意,里面是否勾选的参数要传值1或者2 不是布尔值)
  • 派发actions,(event事件可以得到checked的状态),这个地方使用try catch ,如果成功,正好重新请求一次数据,如果失败 alert提醒

9.删除选中的全部商品
注意:没有一次删除很多产品的接口

  • 但是有一次删除一个的,所以我们要多次调用,这个地方就要用到上下文context中的dispatch, getters,使用 getters获取到数据,如果checked=1,那么就dispatch刚才写好的删除一个的函数,得到的是一个promise对象
  • 用一个数组将得到的promise对象保存起来,最后调用Promise.all方法,
  • 如果所有的勾选都删除成功,就返回一个成功,那么我在.vue页面也要使用async和await 以及try catch
  • 记得删除成功后,要再次发请求,请求数据

请添加图片描述
如果成功此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。但是只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
成功的截图在这里插入图片描述

10.勾选左下角,所有的产品全选或者全不选
有个bug,刷新两次才能更新

注意:没有一次勾选很多产品的接口

  • 但是有一次勾选一个的,所以我们要多次调用,这个地方就要用到上下文context中的dispatch, state(getters其实也可以,我们使用的时候,注意一下那些属性名字是什么),使用 state获取到数据,
    如果不论Checked=0还是1,都dispatch刚才写好的勾选一个的函数,得到的是一个promise对象
    注意,isChecked这个地方必须传0/1 !!不能传true or false

  • 用一个数组将得到的promise对象保存起来,最后调用Promise.all方法,在.vue页面也要使用async和await 以及try catch

  • 成功后,要再次发请求,请求数据

登录界面

  1. 注册的静态组件
  2. assets文件夹放置所有组件共用的静态图片
    在css中也可以用@,需要加一个 ~ 代表src
    background-image: url(~@/assets/icons.png);

注册页面

1.收集表单数据,手机号,获取验证码

  • 获取验证码的接口 不是15那个,在最后 85集

  • 写api接口 仓库中新建一个user.js,在大仓库中引入并注册,注意commit之后,别忘了返回OK,三连环,将返回的data存储起来

  • 在获取验证码那个地方派发action,await一定是加在this.$store.dispatch()这句话上面的,加到别的地方会出错。data获取到仓库中的data,

2.点击注册的时候,先告诉服务器我注册了一个用户,保存给服务器。
判断一下密码和第二次的输入是不是相同,手机号是否相同等等
然后进行路由的跳转

登录界面

登陆业务

1.收集账号密码
2.登录的接口 在api中写接口
在仓库中写配置
在.vue中写,派发请求(登录的前提是电话被注册了)注意拦截默认事件
登录成功的时候,后台为了区分用户是谁,服务器下发token(令牌:唯一标识符)
接口做的不够完美,一般来说,登录成功的时候,服务器只会下发token,前台持久化储存token,带着token找服务器要用户信息进行展示
3.发送请求之后,可以看到服务器返回的data中有token,我们把token三连环保存起来 ,
查看仓库,发现一旦登录就会有token信息
记得把token和uuid类似,存储在header中 把token在Ajax中头部存起来)
在这里插入图片描述

用户登录携带token获取用户信息

  • 写接口(reqUSerInfo)
  • 仓库getUserInfo
  • 在home中的mounted派发请求,home一刷新就能获取到User数据
    派发请求之后,获取到数据,把用户信息存储在仓库中userInfo
  • 简化userInfo的信息, 更改头部,如果登录了,变成用户的信息,如果没登录,还是原来的信息,可以用v-if,如果用户名存在就说明登录了(不是持久化存储)

有一个问题,一刷新,登录信息就消失了???因为一刷新我没有再次派发请求

实现持久化存储:localStorage

在util中新建一个token.js实现持久化存储,在登录业务userLogin中本地存储,可以引入token,调用封装的token函数(一开始登录,登录的时候,正好存在本地,等到刷新的时候,虽然不是持久化存储,但是我把仓库中的token设置成从本地捞取,那么就实现持久化存储)

存在问题: 但是为什么search组件里面没有了?
1.多个组件展示用户信息,需要在每一个组件里面的mounted中进行

  //获取用户信息,在首页进行展示
     this.$store.dispatch("getUserInfo");

退出登录

1.向服务器发请求,告诉服务器退出登录了(服务器清除token)
2.前台中关于用户的所有信息也要清除

  • 写接口 reqLogout
  • 在仓库中写退出登录userLogout , commit的时候写clear请求,不仅要把后台的数据清除,还要把前台的数据清除(所以在token.js中写removeToken函数)
  • 点击header中的退出登录,就派发action,记得退出登录之后要跳转到首页(try catch async await)

用户没登录,就不能去购物车等界面

导航路由守卫

需求:用户已经登录了 ,就不能跳转到登录页面,
导航:表示路由正在发生改变,进行路由跳转
守卫:当做“护卫”

1.在路由中先写前置路由守卫,解决登录之后不能去login的情况(如果仓库中的token存在,那么就说明处在登录状态)于是引入store,获取token,如果是去往login,我们让他去home
2.因为在其他组件里面,一刷新,用户信息就没有了,那么就可以去login了,这种如何解决?

  • 空对象判断的时候永远为真,所以我们可以判断里面的属性有没有值
  • 如果属性没有值,那么久重新发送请求,获取用户信息
  • 如果重新发送信息也不成功,那么久调用退出那个接口,清空前后台的token,重新登录
    uuid_token和token两者都存在,以token优先

现在用这个登录,要不然没有地址
统一登录的账号
13700000000 111111

获取用户地址信息前提是登录

交易页面

出现这种错误的时候,要么引入的时候引入指定的.js(最后一个)
要么把文件夹里trade.js改名改成index.js,这样引入的时候只引入trade文件夹就是可以的

import shopcart from "./shopcart"
import user from "./user"
import trade from "./trade/trade.js"

在这里插入图片描述
1.静态路由 trade 引入,并且配置路由
在shopcart界面给结算两字加上click
2.写接口api两个,获取地址信息,获取订单信息(reqAddressInfo,reqOrderInfo)
写仓库 也是地址信息订单信息 记得去Vuex中查看能否拿到信息
写请求 两个 然后mapState获取信息,记得去组件中查看能否成功拿到信息

3.用户信息的展示 遍历展示
谁是默认地址怎么判断,以及默认勾选的是哪个
点击谁,谁有背景颜色(排他 把所有置为0,只有自己点的那个置为1)
4.计算最后的地址信息,可以计算出来一个userDefaultAddress,计算的就是选中的那一个。注意,一定要加一个|| {} , 要不然会出错(说属性xxxx undefined)

5.动态的展示页面的数据,循环遍历order,以及最后的商品种数和个数

6.点击提交订单的时候,还需要向服务器发起一次请求,把信息传过去,包括user 地址之类的
api中写接口
不用Vuex,用组件存储,但是有个问题,所以的接口都需要挨个引入,而我们想将api只暴露一次,在所有的组件里都可以用
所以在main.js函数中统一引入,就不需要再组件里一次一次引入了,提交订单的时候需要多次测试,因为有的时候被人已经提交过了,所以显示不能多次重复提交

import * as API from "@/api";
  Vue.prototype.$API=API;

成功的话,就给订单号赋值,并且路由跳转

支付界面

1.拉进来静态组件,配置路由
2.根据订单号捞取数据

  • 写接口
  • 在组件内调用,注意,别在生命周期函数中async,像一些需要请求返回是否成功的,可以在mounted里调用函数,请求在函数中写。写一个请求payinfo的函数,带着order去,把order和总金额替换掉

3.使用elementUI
首先下载 npm install --save element-ui,
如果想要按需加载,还需要下载插件npm install babel-plugin-component -D,参考文档补充 .babelrc,注意,配置文件发生变化,需要重启
安装一个插件,叫vue-helper,对于UI组件有提示。

  • 引入,注册,注意注册的时候有两种方法,可以在组件的快速上手中观看
  • -关于组件一下展示的属性,在每一个具体的组件的Options中查看

4.二维码的生成与使用
在npm官网里搜索qrcode,然后下载 安装,引入到要使用的组件中

  • async// await QRCode.toDataURL(放内容),生成二维码的链接,注意<img src=${} />和模板字符那个地方必须要空一个格
  • 怎么获取支付的情况是成功还是失败?有一个接口查询支付的情况(失败,ing,成功,而且弹出层要一直向服务器询问是否成功,直至成功。所以这个地方我们用一个定时器,一秒发送一次请求,如果res.code==200,那么进行一系列操作(清空定时器,保存code…),并进行路由跳转
  • 点击支付成功按钮(未支付,xxxx,支付了xxxxx)我觉得这个逻辑是错误的,支付的话就直接跳转了,就不需要在这点击了???

个人中心界面

1.把组件拖进来,进行注册
2.center这个地方要用到二级组件,配置路由,记得重定向一个默认路由,可以将我的订单作为默认路由
router-link router-view
3.写接口,请求我的订单详情,写好接口之后,把组件遍历展示
有好几笔交易,每一笔交易里有好几件商品
注意 rowspan是合并列,也就是有几个商品,合并几行,但是我们只展示第一个

           <td
                :rowspan="record.orderDetailList.length"
                v-if="index == 0"
                width="13%"
                class="center"
              >

4.分页器
直接沿用前面的全局分页器,但是需要注意getPageNo这个函数

5.完善路由守卫

  • (全局前置守卫)
    首先将我的订单购物车应该跳转的路径写完
    未登录时,不能访问trade pay center之类的界面,要跳转到login界面,next里面的内容就是query参数,所以我们带上重定向 的内容(把未登录的时候 想去但是没去成的信息存储在地址栏中),然后在login界面,我们看一下是否有重定向的内容,如果没有,登录之后就跳转到home界面,如果有,登录之后就跳转到想跳的界面
  • 路由独享守卫
    在某个组件的路由内配置,仅供当前路由使用
  • 组件内守卫
    在某个组件中使用,在paysuccess组件内使用,必须是pay界面跳转过来才可以。next(false): 中断当前的导航,也就是停留在当前的导航不动

图片懒加载

,插件和组件的区别
首先在npm官网搜索vue-lazyload 然后下载npm i [email protected]
json数据和图片默认对外暴露,
配置的时候要import引入一个GIF图片,然后把某一个img里面的:src修改为v-lazy

7.自定义插件,plugin文件里里面有myPlugins.js,在main.js里面暴露,在APP.vue引入,但是测试失败了… 106集

.表单验证

vee-validate

第一步:插件安装与引入
npm i vee-validate@2 --save 安装的插件安装2版本的

第二步:提示信息

import VeeValidate from 'vee-validate'
import zh_CN from 'vee-validate/dist/locale/zh_CN'   // 引入中文 message
Vue.use(VeeValidate)
VeeValidate.Validator.localize('zh_CN', {
    
    
messages: {
    
    
...zh_CN.messages,
is: (field) => `${
    
    field}必须与密码相同` // 修改内置规则的 message,让确认密码和密码相同
},
attributes: {
    
     // 给校验的 field 属性名映射中文名称
phone: '手机号',
code: '验证码',
password:'密码',
password1:'确认密码',
isCheck:'协议'
agree:"协议"
}
})

第三步:基本使用

<input
          placeholder="请输入你的手机号"
          v-model="phone"
          name="phone"
          v-validate="{ required: true, regex: /^1\d{10}$/ }"
          :class="{ invalid: errors.has('phone') }"
        />
<span class="error-msg">{
    
    {
    
     errors.first("phone") }}</span>


//自定义校验规则
//定义协议必须打勾同意
VeeValidate.Validator.extend('agree', {
    
    
validate: value => {
    
    
return value
},
getMessage: field => field + '必须同意'
})

第四步

const success = await this.$validator.validateAll(); //全部表单验证

路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

10.在vue.config.js中加上这句话,减少一些.map的打包,可以减少很大一部分容量。
productionSourceMap:false,

买服务器,使用服务器上线等等

猜你喜欢

转载自blog.csdn.net/Kerryliuyue/article/details/125032379