Vue2实战项目_尚品汇
尚品汇
项目配置
在后面加 –open可以使网页自动打开
项目的其他配置
v-if和v-show选择
v-show和v-if是Vue中用于条件渲染的两个指令,它们的作用是根据条件来控制元素的显示和隐藏。虽然它们最终都能实现类似的效果,但它们的工作原理有所不同。
v-show指令会根据条件来切换元素的CSS属性”display”,当条件为true时,元素显示;当条件为false时,元素隐藏。这意味着无论条件如何变化,元素始终保留在DOM中,只是通过改变CSS属性来控制显示和隐藏。
v-if指令则是真正的条件渲染,当条件为true时,元素被渲染到DOM中;当条件为false时,元素从DOM中移除。这意味着当条件变化时,v-if会销毁或重新创建元素,而不仅仅是改变CSS属性。
一般来说,如果需要频繁切换元素的显示和隐藏,可以使用v-show;如果条件在运行时不经常变化,可以使用v-if。另外,v-if还可以与v-else和v-else-if结合,实现更复杂的条件逻辑。
路由元信息
路由传参
在 Vue Router 中,有两种主要的参数传递方式:params
参数和 query
参数。
1. params
参数:
params
参数是通过路由的path中的占位符来传递的。例如,在以下路由配置中:
1 | // 路由配置 |
在这个例子中,:id
是一个动态参数,它会被作为 params
参数传递给 UserProfile
组件。在组件中,你可以通过 this.$route.params.id
访问这个参数。
2. query
参数:
query
参数是通过 URL 查询字符串传递的,通常在 URL 中以 ?
开头。例如:
1 | // 路由配置 |
在这个例子中,你可以通过 this.$route.query
访问查询参数。例如,如果你的 URL 是 /search?keyword=vue&category=programming
,那么在组件中可以通过 this.$route.query.keyword
和 this.$route.query.category
访问这两个查询参数。
总结一下:
params
是通过路由路径中的占位符传递的,可以通过this.$route.params
访问。query
是通过 URL 查询字符串传递的,可以通过this.$route.query
访问。
路由传递参数(对象写法)path是否可以结合params参数一起使用?
不可以,在对象写法中,path不能和params一起使用,必须使用name来代替path
如何指定params参数可传可不传?
对于可选params参数,可以在路由路径中使用问号(?
),例如
/user-with-optional/:id?
,这样 id
就成了可选的参数。
params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
通过给params参数赋值underfined,例如:
1 | id: route.params.id !== undefined ? route.params.id : '' |
无论用户传递了空串还是没有传递参数,组件都会接收到一个 id
属性,并且在没有提供参数时,默认为一个空串。
路由组件能不能传递props数据?
是的,路由组件可以通过 props
属性接收来自路由的数据。在 Vue Router 中,你可以使用不同的方式传递数据给组件的 props
。
布尔模式 (props: true
):
当你在路由配置中将 props
设置为 true
时,路由会把所有的路由参数注入到组件的 props
中。(只有params
参数)
1 | // 路由配置 |
函数模式 (props: route => ({ id: route.params.id })
):
1 | // 路由配置 |
更加推荐使用函数模式。
对象模式:少用
1 | // 路由配置 |
重写push和replace方法
编程式路由跳转到当前路由(参数不变),多次执行会抛出NavigationDuplicated的警告错误?
原因分析:
vue-router3.1.0之后, 引入了push()的promise的语法, 如果没有通过参数指定回调函数,就返回一个promise来指定成功/失败的回调, 且内部会判断如果要跳转的路径和参数都没有变化, 会抛出一个失败的promise
解决:
1 |
|
postman测试接口可用
- postman是用来测试API接口的工具
- postman也是一个活接口文档
使用步骤
(1) 启动 ===> 选择登陆==> cancel ===> 进入主界面
(2) 输入url/参数进行请求测试
(3) 注意post请求体参数需要指定为json格式
(4) 保存测试接口 ==> 后面可以反复使用
测试成功:
api接口统一管理和解决跨域问题:
1 | const { defineConfig } = require('@vue/cli-service') |
axios二次包装和nprogress进度条使用
1 | /* |
vuex模块化开发
Vuex是一个专为Vue.js应用程序开发的状态管理模式。它充当了一个集中式存储,用于管理所有组件的状态。Vuex的作用在于解决了多个组件共享状态时的管理问题,确保状态的一致性和可维护性。
Vuex的核心概念包括state(状态)、getters(获取器)、mutations(突变)和actions(动作)。State代表应用程序的状态数据,Getters用于从state中派生出一些新的状态,Mutations是用于修改state的方法,而Actions则是用于提交mutations的方法,可以包含任意异步操作。
使用Vuex的好处在于,它可以帮助开发者更好地组织和管理应用程序的状态,避免了状态分散在各个组件中导致的混乱和难以维护的问题。此外,Vuex还提供了一些高级特性,如严格模式、插件等,以及开发工具的支持,帮助开发者更好地调试和监控状态的变化。
总之,Vuex是一个强大的状态管理工具,适用于中大型的Vue.js应用程序,能够提高应用程序的可维护性和可扩展性。
三级列表的Vuex实现
TypeNav的index.vue:
vuex调用和映射:
1 | <script> |
三级列表动态渲染:
1 | <div class="sort"> |
store/home/index.js :
三级列表属于home分仓库的内容
发送请求得到数据和vuex的具体流程:
1 | //引入二次包装的获取商品的三级分类列表的axios请求 |
三级列表的动态背景颜色实现
- 可以直接用简单的css的hover属性实现
- 上面的css方法虽然简便,但没有我们vue体现到数据响应的本质,所以这里我们可以用js的事件绑定来响应数据,并用到事件委托来控制父子元素的事件关联
防抖和节流
正常:事件触发非常频繁,而且每一次的触发,回调函数都要去执行(如果时间很短,而回调函数内部有计算,那么很可能出现浏览器卡顿)
节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发
防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发只会执行一次
正常:就像商城每次输入都要触发回调,放抖就是让只有最后一次输入过一段你规定的时间生效,前面的都不生效
为了实现防抖,我们需要引入Lodash这个工具库,并使用它里面的防抖动函数
防抖:类似于回城被打断
节流:类似于技能的cd
三级列表联动节流
node_modules已经有Lodash
三级联动组件的路由跳转与传递参数
声明式导航和编程式导航的选择:
我们选择利用事件委托+编程式导航来实现路由的跳转与传递参数:
事件委托:
需要用自定义事件和自定义属性来筛选获取当前点击的a标签:
进行路由跳转的方法:
实现效果:
Search模块中商品分类与过渡动画
要在search中动态显示商品分类,默认是不展示的
所以要对TypeNav组件进行v-show动态绑定数据,而且search模块也要有能鼠标经过显示商品分类和鼠标离开隐藏商品分类的功能,所以还要给全部商品分类绑定两个函数,判断当当前路由不是Home组件的时候,实现上面的功能。
第一行为绑定能鼠标经过显示商品分类和鼠标离开隐藏商品分类的函数
第二行为v-show动态绑定实现显示和隐藏的切换
第一行为判断当当前路由不是Home组件的时候,改变show属性为false
第二行为show属性默认是true
第三行为实现其它用到该全局组件TypeNav时也要有能鼠标经过显示商品分类和鼠标离开隐藏商品分类的功能实现
三级列表获取数据性能优化
没优化前:组件的切换和销毁每次在挂载时都要发送一个数据请求
思路:放在只会挂载一次的地方,也就是App.vue里
优化后,无论组件怎么切换和销毁,都只会发送一次数据请求
参数合并
这两个编程式导航因为有两个可能会传参的search路由跳转地方,
没有传query的加上query,没有传params的加上params,这样传输的search参数就是完整的了
mockjs模拟数据
为了实现轮播图和Floor的数据实现,我们使用mockjs来模拟数据,并拦截Ajax请求,只在前端工作,不涉及到后端。
第一步:
安装mockjs
1 | npm i --save mockjs |
第二步:
编写模拟JSON数据:
a. 首页广告轮播数据: src/mock/banners.json
b. 首页楼层数据: src/mock/floors.json
注意一定要格式化文档,先用json格式化文档再用prettier格式化文档
第三步:
把mock数据需要的图片放置到public文件夹中。public文件夹在打包的时候,会把相应的资源原封不动打包到dist文件夹
第四步:
创建mockServe.js,开始mock(虚拟的数据了),通过mockjs模块实现
1 | //先引入mockjs数据 |
第五步:
把mockServer.js文件在入口文件中引入(至少需要执行一次,才能模拟数据)
1 | //引入mockServe.js ----mock数据 |
轮播图数据获取:
为专门请求mock接口的axios封装:mockAjax.js
在index.js发送轮播和楼层列表请求封装:
1 | import mockAjax from './mockAjax' |
在轮播图组件里挂载发送请求:
1 | mounted(){ |
在home的分仓库store处理这个请求:
1 | //获取首页轮播图数据 |
后面的操作和Vuex的三件套基本操作一致,即action,mutation,state。
Swiper+watch+nextTick实现轮播图ListContainer组件
第一步:安装swiper@5
1 | npm i --save swiper@5 |
第二步:引包(相应的JS/CSS)
1 | //引包 |
1 | //引入swiper样式,这里是因为需要用到轮播样式的不止一个组件,所以在入口函数引入,这样简化了组件的引入操作 |
第三步:new Swiper实例(给轮播图添加动态效果)
这里要先有结构才能有new这个实例,所以在组件里先写好这个dom结构,才能new
现在问题来了,我要在哪里new这个实例呢?
1、在mounted里面new这个实例
不可行。组件挂载完毕,正常来说组件结构(Dom)已经全有了,但由于数据的得到是需要经过异步操作,所以mounted完毕后,组件结构还没有办法渲染出来
2、在mounted里面用定时器实现
暂时可行。但还是有不足之处,这样的延迟不满足要求
3.最完美的解决方案:watch+nextTick
通过数据监听,监听已有数据变化
$nextTick:
$nextTick:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个
$nextTick:可以保证也页面中的结构一定是有的,经常和很多插件一起使用
1 | watch:{ |
这里小小的优化:把
1 | document.querySelector(".swiper-container") |
改写成
1 | this.$refs.swiper |
当然,这里要改变dom
结构,将它的 id 改为 ref就可以实现
实现Floor组件动态展示
这里实现Floor组件的方法和轮播图差不多,就是发送二次包装过的axios请求,获取数据,通过Vuex管理仓库,再把数据传给组件
这里要注意的点有两个:
1.发送请求这时候不能放在floor组件中
因为floor组件是单个组件,但返回的数据可以生成多个floor组件数据,所以这里要把发送dispatch请求的任何委托给
Home组件下的挂载,计算的数据也要放在Home组件当中
1 | mounted(){ |
2.对自定义组件用v-for遍历生成
这样可以批量生成floor组件,也不用担心数据怎么单独发给这每一个独立的组件
1 | <template> |
然后父组件Home要给子组件Floor传递数据,所以这里用props传递数据
根据传递来的数据来动态渲染轮播图:
这一次的轮播图实例可以在该组件Floor的mounted函数中创建,那为什么上一次在ListContainer组件不行呢。
这是因为上次书写轮播图的时候,是在当前组件内部发送请求,动态渲染解构,所以前台至少要等到服务器数据回来。而在这次,组件的数据是通过父组件props传递给子组件的,所以不需要等待,挂载的时候,dom结构也已经渲染完毕
对比上个轮播图:
剩下的没有比轮播图更复杂的,就大部分直接用v-for渲染列表就完事了。
把轮播图拆分为一个全局组件,方便使用
以后在开发项目的时候,如果看到某一个组件在很多地方都使用,你把它变成全局组件,
注册一次,就可以在任意地方使用,共用的组件|非路由组件放到components文件夹中
最重要的是把多个相同的组件抽取加工变为统一的结构
例如:该轮播图的模板,脚本都能适应ListContainer组件的异步要求和Floor组件的普通要求,这样才能成为一个公用的组件
1 | <template> |
注意点:全局组件要在入口函数main.js中引入并且注册
这样,即使是对组件传不同数据,也可以简单的通过自定义组件的props传递数据,实现功能
Search组件开发
步骤:
1:先把静态页面+静态组件拆分出来
2:发请求(API)
3:vuex(三连环)
4:组件获取仓库数据,动态展示数据
发请求(API)_API的封装:
vuex:
组件获取仓库数据,动态展示数据:
getters计算属性简化仓库数据,这里没有设置命名空间,所以getters是所有组件公共的
动态展示数据
Search模块根据不同的参数获取数据展示:
SearchSelector模块中子组件的动态开发
这里在Search的SearchSelector子组件中使用getters计算数据,并将它动态渲染到模板中
Bug
这里我写好了模板却始终展示不出来数据。我检查vuex发现子组件也已经有收到getters数据了,而且数据也不是空数据,所以我以为是组件没有注册或者引用的问题,但检查了半天,发现没有什么问题,后面,我检查了一下控制台的输出,发现报错在attr上,我检查代码,才发现v-for被我写成了v-fro,导致整个组件根本没有渲染出来,特此提醒今日的错误。
监听路由的变化再次发请求获取数据
通过数据监听实现,这里要将一些不会变的参数(categoryid)恢复为空,否则影响搜索