axios
axios二次封装
XMLHttpRequest、fetch、JQ、axios
要在项目文件目录下安装axios:cnpm install --save axios
为什么需要进行二次封装axios?
请求拦截器、响应拦截器:请求拦截器可以在发请求之前处理一些业务;响应拦截器当服务器数据返回以后,可以处理一些事情。
api文件夹
在src中创建api文件夹,写一些关于axios的代码。
接口中:路径都带有/api,我们就设置baseURL:'/api'
接口统一管理
- 项目很小:完全可以在组件的生命周期函数中发请求
- 项目大:axios.get('xxx')。在api文件夹中加入一个index.js对API进行统一管理
如:三级联动
nprogress进度条的使用
安装:cnpm install -save nprogress
在request.js中引入进度条及其样式,并在请求和响应拦截器中设置开始和结束
vuex状态管理库
vuex是官方提供一个插件,状态管理库,集中式管理项目中组件共用的数据。切记,并不是全部的项目都需要vuex,项目很大,组件很多,数据很多,数据维护很费劲用vuex。
安装vuex
安装vuex @指定一下版本 只能安装3.xxx
stroe文件夹
1.在src中引入store文件配置vuex,创建index.js。
2.模块式开发写法:在store中创建各个模块的文件夹,里面创建index.js
三级联动模块
用JS完成hover效果
防抖方法下一章节
路由跳转
声明式导航router-link可以实现路由跳转与传参,但可能会出现卡顿现象。router-link可能循环出很多组件【创建组件实例】。解决方法:自定义属性+编程式导航。
遇到的问题:跳转页面后,URL丢失search。解决方法:在配置路由文件中占位后面添加一个?
鼠标移入和移开针对search和home页面的设计
过渡动画(前提:组件、元素务必要有v-if/v-show指令才可以进行过渡动画) 先用transition包裹
CSS
优化:因为主页和搜索页都有三级联动模块,都要向服务器发送请求,浪费资源,所以在App.vue中派发action
解决路由跳转之后参数不全的情况。在typeNav和header组件分别更改为
函数的防抖和节流
- 防抖:前面所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发,只会执行一次。
- lodash插件:里面封装函数的防抖与节流业务(闭包+延迟器)。lodash函数库对外暴露_函数
- 节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调。把频繁触发变为少量触发。(闭包+延时器)。不要用箭头函数。
mock数据(模拟)
开发Home首页当中的ListContainer组件与Floor组件:服务器返回的数据(接口)只有商品分类菜单分类数据,对于ListContainer组件与Floor组件数据服务器没有特供,需要mock.js插件:生成随机数据,拦截Ajax请求。
- 安装:cnpm install mockjs(注意不加.)
- 使用步骤:
- 在项目中的src文件夹中创建mock文件夹
- 准备JSON数据,创建banner.json文件,floor.json文件
- 把mock数据需要的图片放置到public文件夹中(public文件夹在打包的时候,会把相应的资源原封不动打包到dist文件夹中)
- 开始mock虚拟数据,通过mockServe.js文件模块实现(webpack默认对外暴露,图片/JSON数据格式默认暴露)
- mockServe.js文件在入口文件中引入(至少需要执行一次,才能模拟数据)
其余都跟request.js一样,修改baseURL
index.js引入
其他vuex的操作与之前的相同(写API,再写store三连环)
APP.vue
配置状态
组件获取数据
swiper
版本太高可能有问题,安装5版本:cnpm install swiper@5.因为很多模块都用swiper,所以直接在入口文件main.js中引入
swiper使用时必须结构完整。因为dispatch当中涉及到异步语句,导致v-for遍历的时候结构还没有完全,所以不能写到ListContainer中的index.vue的mounted中。v-for动态构建结构,数据来源于服务器,在mounted生命周期钩子之后。
解决方法:watch:监听已有数据的变化。+nextTick:在下次DOM更新 循环结束 之后,执行延迟回调。在修改数据之后 立即使用这个方法,获取更新后的DOM.错误方法:
正确方法:
floor组件
需要两个floor模块遍历数据。getFloorList这个action需要在Home路由组件中发,不能在floor组件内部发,因为我们需要v-for遍历floor组件。
src-pages-home-index.vue
信息都在home身上,需要向子组件floor进行通信
组件通信方式
- props:用于父子组件通信。
- 自定义事件:@on @emit可以实现子给父通信
- 全局事件总线:$bus 全能
- pubsub-js:vue中几乎不用,react中使用。全能
- 插槽:具名插槽、默认插槽、作用域插槽。父组件给子组件提供结构,子组件给父组件提供结构使用的数据
- vuex
轮播图可直接写到mounted里。因为第一次写轮播图的时候是在当前组件内部发请求,动态渲染结构。这次是在home父组件通过props传递过来的,而且结构都已经有了情况下执行mounted
把首页的轮播图拆分成一个公用组件
把floor的轮播图写成和第一次写的轮播图大概一个格式
src-components-Carousel-index.vue
在main.js注册引入全局组件
使用自定义全局组件
search模块开发
- 1.静态页面+静态组件拆分出来
- 2.发送请求(API)
- 3.vuex三连环
- 4.组件获取仓库数据,显示动态数据
getters
项目中的getters主要作用是:简化仓库中的数据(简化数据而生)=》可以把我们将来在组件中需要用的数据简化,获取数据更加方便
如果没有网,没法请求,state.serchList是空对象,取不到goodsList
正确:
发送action不能写在mounted中,因为只会加载一次
es6:Object.assign(目标对象,被拷贝的对象,被拷贝的对象),浅拷贝。但是只能发一次请求。
在search的子组件配置动态获取参数
应该这么写
但是remove功能没法实现地址栏的改变,所以需要进行路由跳转(search跳search)
兄弟组件通信——$bus
当面包屑中的关键字被x掉后(search),需要让兄弟组件Header组件中的关键字清除
在main.js中注册全局事件总线
Header.vue中
子父通信——自定义事件
点击了品牌后,整理参数,向服务器发送请求获取相应的数据进行展示。要在父组件发送请求,因为searchParams参数在父组件(search)身上,子组件只需要把点击的品牌信息传给父组件即可。
触发和传参写在子组件身上
父组件身上绑定回调函数
关于商品属性的设计也是类似的。父组件:
子组件
难点:排序操作
1:综合 2:价格 asc:升序 desc:降序,故有四种排列方式。初始状态是综合降序order:'1:desc'
分页器
v-for是可以遍历:Array/Object/number/sting/Iterable的。在search组件上安装分页器,但是鼠标点击的页数事件在子组件身上。需要自定义事件传参。先设虚拟数据调试成功后再用服务器数据
数据总数在search的state中
子组件绑定事件
购物车模块
详情页和购物车模块
特殊的一点是,在详情页中点击加入购物车,需要将参数带给服务器(发请求),但是服务器发回来的数据只是成功或者失败,所以不需要使用三连环进行储存。
还要进行路由跳转。在路由跳转的时候,还需要将产品信息(skuInfo)和产品加购的数量(skuNum)带给下一级路由组件。一些简单的数据(skuNum)通过query形式给路由组件传递。但是一些复杂的数据(skuInfo是个对象),如果使用query传输,地址栏会自动转换成一串字符串(乱码)不美观。所以选择通过会话存储(不持久化,会话结束数据消失)。且本地存储、会话存储都不能存储对象,一般存储的是字符串。
购物车中的加减和输入个数
要求传递差值
Promise.all
删除所有购物车中的数据。这个没有配置接口,需要通过调用删除一个产品的函数循环调用达到目标。
使用Promise.all。
全选框和上面的勾选框联动。判断全选框的isChecked状态,把它的值赋值给其他勾选框的isChecked
还是使用Promise.all,使用forEach遍历item,打印出来state判断路径哦。
assets文件夹
防止全部组件共用的静态资源
@
在样式中也可以使用@符号(src别名),但是要加波浪号
注册的业务
通过数据库存储用户信息(名字、密码)。
解构赋值真的方便。
要传递一个对象data,KV一致。
登录
登陆成功时,后台为了区分用户,服务器下发token(令牌:唯一标识符)。登录接口:做的不完美,一般登录成功服务器会下发token,前台持久化存储token,(带着token找服务器要用户信息进行展示)
在api文件夹下的request.js中的请求拦截器中,请求拦截器写一个判断,如果有token则带给服务器
vuex仓库储存数据不是持久化,所以要通过localStorage存储token(本身就是字符串,localStorage也是存储字符串的所以不用转换),在utils中设置一个新的js
在store组件中引入我们定义的三个方法。初始化state直接获取localStorage中的token。存在问题:除了home派发dispatch获取信息之外,其他页面一刷新就会丢失token。
路由守卫
to是要跳转的路由信息,from是从哪个路由信息来的,next()放行,next(path)放行到指定路由
引入仓库
设置前值守卫(之所以获取name而不是userInfo是因为如果是个空对象的话,判断布尔值也是true)
解决了其他页面一刷新丢失token的问题。重新派发action,获取信息。
结算
- html结构的a标签的target属性:
- target="_self" 内容在当前页面显示。
- target="_blank" 内容在新页面显示。
- target=“three” 内容在对应窗口显示
- target="_top" 在当前窗体打开链接,并替换当前的整个窗体(框架页),清除所有包含的框架
- target="_parent" 在父窗体中打开链接,在窗口与顶级框架中,等同于_self
find的使用
find()用于找出第一个符合条件的数组成员,没有找到则返回undefined
pay
开始练习不用vuex。1.在main.js中引入API就不用在每个组件中单独引用
2.设置点击事件,获取需要传递的data和query参数
3.使用$API,并在data中初始化orderId,把query参数传递,也可以写成字符串形式
生命周期函尽量不要添加async
可以和methods连用
组件库
React(Vue):antd[PC] antd-mobile(移动端) Vue:ElementUI[PC] vant[移动端]
配置完毕需要重启项目 element-ui版本下载2.15.5,15不行!!!改了好久。
两种写法
样式没有引入的话,在main文件中import 'element-ui/lib/theme-chalk/index.css'
生成二维码QRcode
npm i qrcode 在组件中import QRCode from 'qrcode',返回一个promise,可以把二维码地址字符串转换成二维码。
二级路由
全局守卫补充
在login.vue中
路由独享守卫
组件内守卫
补充
图片懒加载
表单验证
vee-validate
在main.js中
在注册组件中
全都符合标准再发请求
路由懒加载
把不同路由对应的组件分割成不同的代码块,然后当路由被访问时才加载对应组件,更高效。