v-show:通过样式display控制
v-if:通过操作DOM元素进行操作
1:v-show|v-if(首页|搜索底部是有Footer组件,而登录注册是没有Footer组件
Footer组件显示|隐藏,选择v-show|v-if)
2:按需加载(对于loadsh插件,element,它里面封装的函数功能很多)
3.函数防抖与节流
4.请求性能优化:
APP文件
mounted(){
// TypeNav向仓库派发行为 获取数据
// 放到这里,只需进行一次请求,Home小仓库获得数据后,全局组件TypeNav都会存储到Home小仓库获得的这个数据
this.$store.dispatch("categroylist");
},
main虽然也是执行一次,但是它不是组件,没有this,组件才有$store属性
1:路由传递参数(对象写法)path是否可以结合params参数一起使用?
不可以:不能这样书写,程序会崩掉
2:如何指定params参数可传可不传?
3:params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
4:如果指定name与params配置, 但params中数据是一个"", 无法跳转,路径会出问题
5: 路由组件能不能传递props数据?
好处:
// 这个文件进行统一的API管理
// 引入axios
import requests from './request'
// 引入mockAjax
import mockrequest from './mockAjax'
// 三级联动的接口
// 这里设置一个函数对外暴露,外面若需要发起三级联动的数据请求调用即可 记住要给函数返回,不然无返回值默认undefined
export const reqCategoryList = ()=>{
// 发请求成功返回的是promise对象 直接使用封装好的axios
return requests({
url:'/product/getBaseCategoryList',
method:'get'
})
}
// 获取首页banner(首页轮播图的数据)
export const reqGetBannerList = ()=>mockrequest.get('/banner')
//获取floor的数据
export const reqGetFloor = ()=>mockrequest.get('/floor')
// 获取search的数据 这个函数需要不需要外部传递的参数?要给服务器带参进行params给服务器传递参数 调这个函数得有相应的参数 错错错需要接收home页传递过来的params数据和query数据/api/list
// 当前这个接口。给服务器发请求的时候,至少得是一个空对象
export const reqGetSearchInfo = (params)=>requests({
url:'/list',
method:'post',
data:params
})
// 这里进行axios的二次封装
// 主要想用请求拦截器和响应拦截器
import axios from 'axios'
// 引入进度条 start开始 end结束
import nprogress from 'nprogress'
// 引入进度条样式
import "nprogress/nprogress.css"
// 1.利用axios的create方法创建一个axios实例
// 2.request其实就是axios,只不过我们又进行了配置和封装
const requests = axios.create({
// create里面可以传配置对象
// 配置对象
// 基础路径:baseURL就是给每个请求的路径上自动加上所配置的,就不用自己再去书写
baseURL: '/api',
// 请求超时的时间
timeout: 5000
})
// 3.设置请求拦截器,在发请求之前,请求拦截器可以监测到,可以在请求发出去之前做一些事情
requests.interceptors.request.use((config) => {
// config其实是一个配置对象,里面有属性headers请求头
// 进度条开始
nprogress.start()
return config
});
//4.设置响应拦截器,里面传入成功的回调和失败的回调
requests.interceptors.response.use((response)=>{
// 成功的回调函数,服务器在响应数据成功的时候,响应拦截器可以检测得到,做一些事情
// 进度条结束
nprogress.done()
// 返回data字段
return response.data
},(error)=>{
// 服务器响应失败回调函数
// 终结promise
return Promise.reject(new Error('false'))
})
// 对外暴露
export default requests
正常:事件触发非常频繁,而且每一次的触发,回调函数都要去执行(如果时间很短,而回调函数内部有计算,那么很可能出现浏览器卡顿)
防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发,只会执行最后一次
<button>点击</button>
<script>
// 防抖
const btn = document.querySelector('button')
// 事件处理函数
function pay() {
console.log("已经购买");
// 没有处理过就是指向window 正常是button
console.log(this);
}
// 防抖函数
function debounce(func, delay) {
// 3.只创建了一次,是唯一的只不过不断的给timer赋值进行延时而已
// 每个清除延时就是清除上一个定义的延时,而不是清除新建立的延时
let timer
// 因为要在防抖函数里面执行原来的事件处理函数,所以要接收参数来接收,并且去执行这个函数的参数(事件处理函数)
// 1.一旦监听到了函数就会马上执行,因为要进行处理,使用高阶函数(函数返回函数)
return function () {
// 因为在防抖函数里面的定时器里面的this是指向全局变量window的所以要提前保存this
let This = this
let arg= arguments
// 这里虽然提前声明且清除函数调用函数了,但是每个防抖函数都是独立的没有相互联系,因此要使用作用域链(闭包)将声明放在外面
// let timer
// 设置清除延时
// 2.不能清除一个没有定义的变量名,因此将变量名提前声明
clearTimeout(timer)
timer = setTimeout(function () {
// 通过call方法进行绑定这个this给
// func.call(This)
// 因为后续可能给事件处理函数传参因此使用apply
func.apply(This,arg)
}, delay)
}
}
btn.addEventListener('click', debounce(pay, 1000))
// 节流
</script>
节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发
<script>
const btn = document.querySelector('button')
function pay() {
console.log("已经购买");
console.log(this);
}
// 节流函数
function throtte(func, delay) {
// 节流核心是如果timer被赋值了(有定时在就不进行操作,如果没有赋值就执行任务)
let timer
return function () {
let This = this
let arg= arguments
if(timer){
return;
}
timer = setTimeout(function () {
func.apply(This,arg)
// 等时间过去,不用清除定时,直接情况timer的值即可
// 因为这个清空是在延迟执行任务以后发生
timer = null
}, delay)
}
}
btn.addEventListener('click', throtte(pay, 1000))
</script>
方法二
<script>
const btn = document.querySelector('button')
function pay() {
console.log("已经购买");
console.log(this);
}
// 节流函数
function throtte(func, delay) {
// 节流核心是如果timer被赋值了(有定时在就不进行操作,如果没有赋值就执行任务)
let pre = 0;
return function () {
let This = this
let arg= arguments
let now = new Date()
if(now - pre>dalay){
fun.apply(This.arg);
pre = now;
}
}
}
btn.addEventListener('click', throtte(pay, 1000))
</script>
1.第一种声明式导航:为什么使用router-link组件的时候,会出现卡顿那?
router-link是一个组件:相当于VueComponent类的实例对象,一瞬间
new VueComponent很多实例(1000+),很消耗内存,因此导致卡顿。
{{ c1.categoryName }}
2.第二种编程式导航:push|replace
三级分类由于使用router-link的时候,会出现卡顿现象,因此采用编程式导航。
因为是有很多的级联,v-for循环得到的,因此在循环过程中,回调函数也会依次增加
优化:编程式导航+事件委派的冒泡原理将绑定一个回调函数,则会相应的隐射到每一个子节点
路由跳转的时候【home->search】:需要进行路由传递参数【分类的名字、一、二、三级分类的id】
this.$router.push()
{
name:'search',
query:{
categoryName:'电子书',
category2Id:4
}
}
// 三级联动路由跳转和传递参数的业务
goSearch(event) {
// alert(444)
// 问题1:如何判断点击子节点的是A标签
// 答:把子节点当中的a标签,加上自定义的属性,其余子节点是没有的(自定义属性:浏览器会将驼峰命名转换为一般的命名)
// 问题2:如何判断是几级的目录?
// 答:也是根据自定义属性加上的自身的ID值进行条件判断
// 问题3:如何获取当前的事件 答:event
// event.target :获取到的是触发事件的元素(h3,a,dt,dl)
let node = event.target;
// 节点有一个属性dataset属性,可以获取自定义属性与属性值 (这里一定要小写,不是给你说了么,浏览器会将自定义属性变为全部小写)
let { categoryname, category1id, category2id, category3id } =
node.dataset;
console.log(event);
// 当这个标签是A标签的时候才会进入判断
if (categoryname) {
/* {
name:'search',
query:{
categoryName:'电子书',
category2Id:4
} */
// 准备路由跳转的参数 设置对象
let location = { name: "search" };
let query = { categoryname: categoryname };
// 一级目录
if (category1id) {
query.category1id = category1id;
} else if (category2id) {
query.category2Id = category2id;
} else {
query.category3id = category3id;
}
// 路由跳转前要合并参数
// 1.判断路由中是否有params参数,有则进行合并
if (this.$route.params) {
// 动态的给location添加params属性
location.params = this.$route.params;
// 动态的给location添加query属性
location.query = query;
}
this.$router.push(location);
}
},
在home模块当中,使用了一个功能三级联动功能---->[typeNav]
在search模块当中,也使用三级联动的功能------->[typeNav]
TypeNav组件业务分析?
// 当鼠标移入时,全部商品分类列表进行展示
enterShow() {
if (this.$route.path != "/home") {
this.show = true;
}
},
// 当鼠标离开的时候,全部商品类别进行影藏
leaveShow() {
if (this.$route.path != "/home") {
this.show = false;
}
4)过渡效果
HTML:<transition name="sort"> 相应的节点和组件</transition>
CSS:// 过渡动画的样式
// 开始进入状态
.sort-enter {
height: 0;
}
// 结束状态
.sort-enter-to {
height: 461px;
}
// 定义动画的时间和速率
.sort-enter-active {
transition: all 0.5s linear;
}
进入搜索页面的时候需要传递各种的参数,从而才能向服务器发请求获得相应的数据
1.开发的三级联动业务,当你点击a标签的时候,会进行路由的跳转,将产品的名字与id传递给search模块----(query)
2.点击搜索按钮的时候,用户输入进来的关键字,点击按钮的时候会通过params参数传递给search模块-----(params)
3.路由跳转(home->search),两个地方,三级联动(typeNav)、Header组件(搜索按钮)
// 路由跳转前要合并参数
// 1.判断路由中是否有params参数,有则进行合并
if (this.$route.params) {
// 动态的给location添加params属性
location.params = this.$route.params;
// 动态的给location添加query属性
location.query = query;
}
this.$router.push(location);
}
接口没有写好,前端人员可以mock一些数据【前端程序员自己模拟的一些假的接口】,当中工作中项目上线,需要把mock数据变为后台给的接口数据替换。
props:父子
插槽:父子
自定义事件:子父
全局事件总线$bus:万能
pubsub:万能
Vuex:万能
$ref:父子通信
开始:放在mouted生命周期钩子里面,只会请求一次
解决办法:watch和路由的$route方法监听路由的信息是否发生变
// 数据监听,监听组件实例身上的属性值发生变化 从而用户可以重复的根据组件身上的数据去重复的发送请求
watch: {
// 监听路由的信息是否发生变化
$route(newValue,oldValue) {
// 再次向服务器发送请求之前整理数据带给服务器
Object.assign(this.searchParams,this.$route.params,this.$route.query)
// console.log(this.searchParams);
// 再次发送请求 解决只能一次去发送请求
this.getData();
// 每一次请求的时候,应该把相应的123级ID清空,让他接收下一次的相应的123ID
// 分类和关键字不用清理,因为每次路由发生变化的时候,会给他重新赋值
this.searchParams.category1Id = ''
this.searchParams.category2Id = ''
this.searchParams.category3Id = ''
},
},