Vue2开发经验(更新中)
遇到版本不兼容添加以下内容
SET NODE_OPTIONS=--openssl-legacy-provider &&
路由组件显示与隐藏
-
判断路由组件上的path信息
-
<!--配置路由后,在路由组件和非路由组件都会出现$route和$router的路由信息--> <Footer v-show="$route.path==='/home || $route.path==='/login'" ></Footer>
-
-
在路由组件上加上meta属性flag
-
{ path:'/home', meta:{show:true} } { path:'/login', meta:{show:false} } -
<Footer v-show="$route.meta.show"></Footer>
-
路由传递参数的三种方式
-
以字符串的形式
-
this.$router.push("/search/"+this.keyworld+"?k="+this.keyworld.toUpperCase())
-
-
以模板字符串的形式
-
this.$router.push(`/search/${this.keyworld}?k=${this.keyworld.toUpperCase()}`)
-
-
以对象的形式来传参
-
this.$router.push({ name: 'search', params: { keyworld: this.keyworld }, query: { k: this.keyworld.toUpperCase() } })
-
-
关于路由的相关的面试题
-
如何指定params可传可不传
-
{ name: 'search', //在params参数的占位符后面加上? path: '/search/:keyworld?' }
-
-
在编程式路由中,使用path和params参数是否可以同时使用: 不能,传递params不许使用name属性指定要跳转的路由,query参数无所谓
-
如何解决params传递空串的时候路径问题
-
this.$router({ name: 'search', params: { //空串后面加上或undefined keyworld: '' || undefined } })
-
-
路由·是否可以传递props参数:可以,且有布尔值,对象式,函数式三种方式
-
编程式路由多次点击爆红的问题解决(声明式导航没有这个问题)
原因分析
vue-router引入了promise,编程时路由会返回一个结果promise
这个使用来捕获路由异常的,如果没有异常回调函数,就会爆红
解决问题方法一(治标不直本)
this.$router.push({},()=>{},(error)=>{})//添加回调函数且不打印错误信息即可解决
解决问题方法二(彻底)(对VueRouter原型上的push进行重写)
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//对原来的push方法备份
let orgine = VueRouter.push
//对push进行改造
VueRouter.prototype.push = function(location,resolve,reject){
if(resolve && reject){
//如果有传递异常回调函数,则传入
orgine.call(this,location,resolve,reject)
}else{
//如果没有,则手动传入
orgine.call(this,location,()=>{},()=>{})
//在这里使用call()来保证使用的是原来的方法
//call()和apply的相同点:都可以调用函数和篡改函数一次
// 不同点:call的参数使用都好隔开,apply参数使用数组
}
}
//相同的也可以对replace进行改造
export default new VueRouter({
routes: [
]
})
对于axios中的二次封装
为什么要进行二次封装
- 可以再请求的时候或者在响应的时候做一些其他的事情
最基础的二次封装
import axios from 'axios'
//配置基础的axios
//通过axios的create方法创建出来axios实例,对其进行二次封装,并暴露出去使用
const requests = axios.create({
//配置基础路径,这样在有代理的情况下,就可以在发送axios的时候不用在url中写/api了
baseURL: '/api',
//配置请求的超时事件为5秒
timeout: 5000
})
//配置请求拦截器,可以在请求发出去之前做一些事情
requests.interceptors.request.use((config)=>{
//config为配置对象,包含一些重要的属性,如请求头,一般直接返回出去即可
return config;
})
//配置响应拦截器,可以在响应后做一些事情
requests.interceptors.response.use((res)=>{
//在这里第一个函数是响应成功的回调函数,一般这边返回响应的数据即可
return res.data;
},(error)=>{
//这是响应失败的回调函数,一般这里处理错误
return Promise.reject(new Error("错误信息"))
})
//配置完基础的axios和请求和响应拦截器后直接返回结果就可以使用封装好的axios了
export default requests;
接口统一管理
-
对于小型项目来说,我们可以不用接口统一管理,可以直接在组件中发送axios请求
-
对于大型项目来说,需要统一管理接口,需要新建一个文件夹来放置发送请求的api
-
//引入二次封装的axios import axios from './requests' //发送第一个axios请求 export const testaxios = ()=> axios({ url: '/api/test', method: 'GET', success(rep){ console.log(rep.data) } }) -
//在组件中使用第一个axios import {testaxios} from './axiosapi' //方法返回的是Promise对象 testaxios() //如果想要直接获得响应的数据,可以用async await async gettestaxios(){ let data = await testaxios(); //此时的data就是响应的数据了 }
-
axios的跨域问题
什么是跨域
- 协议,域名,端口号不同的请求,称之为跨域
解决跨域
- 在webpack中文文档中的配置中有详细的解决方案
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' },
},
},
},
};
vue项目中的进度条
- 使用插件nprogress,引入nprogress和样式
- 在二次封装的axios中的请求拦截器中使用nprogress的start方法,在响应拦截器中使用done方法即可
vuex的模块化开发
- 对于小型项目来说,如果组件不多,数据量也不多的情况下,可以不使用vuex的模块化开发
- 但是对于大型项目来说,如果数据太多的话,就需要进行模块化开发了
防抖与节流技术(闭包和延迟器)(面试频率高)
防抖
-
比如input这种快速触发的事件,用户连续输入文本,就会连续触发input事件,防抖就会忽略掉前面的oninput事件,在规定的时间之内触发最后一次的oninput事件,也就是在用户输入完后才触发事件
-
推荐的防抖函数:lodash库(可以在官网和npm下载),里面的debounce函数可以做到防抖
-
let input = document.querySelector('input') //lodash对外暴露的是_函数 //debounce(事件的回调函数,在规定的时间后执行回调函数,配置文件)函数 input.oninput = _.debounce(function(){ console.log("发送ajax请求") },1000) //在用户输入完后的1s后执行回调函数
-
-
节流
-
在规定的时间范围内不会触发回调,只有大于这个时间间隔才会触发回调,把频繁触发改为少量触发
-
比如计数器,推荐的节流函数也是lodash中的throttle函数
-
let span = document.querySelector('span') let button = document.querySelector('button') let count =0; button.click=_.throttle(function(){ count+=1; span.innerText=count; },1000) //在一秒之内只会触发一次回调函数
-
在vue中引入lodash的节流
-
import throttle from 'lodash/throttle'
vue三级联动的路由跳转问题
-
使用声明式导航
,会出现卡顿现象,是因为在组件加载的时候,会循环很多的routerlink组件,很耗内存,所以出现卡顿现象 -
最好的方法是用事件委派和编程式导航
-
出现的问题:如果利用事件委派,则无法判断触发事件的具体的节点
-
解决问题:在具体的事件触发节点上自定义属性,将参数传递出去,通过event.target获取具体的节点且有自定义属性的触发事件的具体节点,自定义属性可以通过节点的dataset获取
-
//获取自定义属性 let {自定义属性名1,自定义属性名2} = event.target.dataset
-
-
优化性能
对于一些公用的数据请求
- 不用在每一个组件中都发送请求获取数据,而是在App根组件中发送请求,在组件切换的时候,不会重复发送请求
前端模拟数据
- 使用mockjs模拟数据(mockjs可以模拟随机数据,且浏览器会拦截这次请求(network中不会出现请求))
使用规则
-
在脚手架的src目录下新建mock文件夹
-
新建json格式的模拟数据userjson
-
[ { id: "1", username: "clt" }, { id: "2", username: "clt2" } ]
-
-
新建mockServer.js文件
-
import Mock from 'mockjs' import userjson from '@/mock/userjson' //Mock中有一个方法为mock可以模拟数据,第一个参数为请求的地址,第二个参数为数据 Mock.mock("/user/info",{code:200,data:userjson})
-
-
在main.js中引入加载一次
-
import '@/mock/mockServer'
-
前端使用的轮播图插件
- swriper
浙公网安备 33010602011771号