admin管理员组文章数量:1547450
常问—面试宝典
1.双向绑定原理
采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()
来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
MVVM 作为数据绑定的入口,整合Observer、Compile 和 Watcher三者,通过Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变(input) -> 数据 model变更的双向绑定效果
2.跨域
由于浏览器的同源策略,防止他人恶意攻击网站
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
1、jsonp的原理: ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。
//1.创建一个script标签
var os=document.createElement("script")
//2.给script一个src,src就是地址,cb=回调函数
os.src="http://suggestion.baidu/su?cb=qwer&wd=123"
//3.将script插入到页面
document.body.appendChild(os)
//4.回调函数处理数据
function qwer(d){
//d就是后端返回的数据
}
缺点:只能发起get请求,不能发起post请求
2、 CORS:设置后端。服务端在HTTP返回头上加上AccessControll-Allow-Origin:*
,浏览器将会允许跨域请求
3、配置代理 :在vue.config.js中的devServer下的proxy中的api下的target配置跨域请求的地址,并设置changeOrigin: true
module.exports={
// hash模式,publicPath 配置为"";history模式。,需要配置为"/"
publicPath:"",
outputDir:"dist",
assetsDir:"public",
indexPath:"index.html",
//配置代理
devServer:{
proxy:{
"/api":{//拦截以/api开头的接口
target:"http://localhost:3000",//要跨域的域名
ws:true,//
changeOrigin:true // 是否开启跨域
}
}
}
}
3.防抖节流
函数防抖:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。最后一次操作能被触发
function throttle(callback, delay = 1000){
let timer = null;
function f(){
if(!timer){
timer = setTimeout(() => {
callback && callback.call(this);
clearTimeout(timer);
timer = null;
}, delay);
}
}
return f;
}
应用:搜索里面每输入一个字符就发起请求优化为以最后一次输入后为准
函数节流:当持续触发事件时,保证一定时间段内只调用一次事件处理函数节流。使得一定时间内只触发一次函数。
function debounce(callback, delay = 1000) {
let timer = null;
function f() {
clearTimeout(timer);
timer = setTimeout(() => {
callback && callback.call(this);
}, delay);
}
return f;
}
应用:页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次,Ajax 求,而不是在用户停下滚动页面操作时才去请求数据
4.vue生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程就是生命周期
Vue 实例从创建到销毁的过程,一共分为11个
beforeCreate(){} //创建之前,什么都没有
created(){} //创建之后,数据初始化完成,但是el还是undefined
//作用:二次修改初始值
beforeMount(){} //2.挂载期:如果有el或者$mount(),才自动触发
//挂在之前:找到了要解析的模板,但是{{}} v-指令都还没有解析
mounted(){} //挂载完成:页面完成解析,DOM节点加载完成
//作用:获取dom,添加动画,开启计时器,给window或者document绑定事件
beforeUpdate(){} //3.更新期。数据变化了,但是页面准备重新渲染之前,注意,此时取到 的数据是新值
updated(){} //页面更新完成
beforeDestroy(){} //4.销毁期。作用:善后工作:1.清除计时器;2.清除window|document上的事件
destroyed(){} //销毁完成
activated
:keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用
deactivated
:keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用
errorCaptured
(2.5.0+ 新增) 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生 错误的组件实例以及一个包含错误来源信息的字符串,此钩子可以返回 false 以阻止该错误继续 向上传播
5.如何进行前端性能优化
- 代码压缩合并
- 启用Gzip压缩
- 函数防抖实现搜索优化,减少http请求
- 使用CDN资源代替本地资源
- 使用精灵图代替小图标
- 图片很多的时候使用懒加载
6.闭包及优缺点
闭包:在一个函数中存放另外一个函数,在其内部生成一个局部作用域。在函数的外部可以直接访问这个函数中的变量。
应用场景:要获取某函数内部的局部变量
闭包的优点:1.能够读取函数内部的变量,延长作用域链2.让这些变量一直存在于内存中,不会在调用结束后,被垃圾回收机制回收
闭包的缺点:由于闭包会使函数中的变量保存在内存中,内存消耗很大,所以不能滥用闭包,解决办法是,退出函数之前,将不使用的局部变量删除。
7.ES6的新增方法
1、新增声明命令 let 和 const
2、模板字符串(Template String):用一对反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串
3、函数的扩展:箭头函数
4、对象的扩展:属性名和属性值相同时可以简写
5、Promise 对象:解决异步编程,,将异步操作以同步操作的流程表达出来。即解决异步处理回调地狱
6、解构赋值:数组和对象都可以用
7、…展开运算符可以将数组或对象里面的值展开;还可以将多个值收集为一个变量
8、async、await
Object.getOwnPropertySymbols()
8.let/var/const区别
- var 声明变量可以重复声明,而 let 不可以重复声明
- var 是不受限于块级的,而 let 是受限于块级
- var 会与 window 相映射(会挂一个属性),而 let 不与 window 相映射
- var 可以在声明变量之前访问变量,而 let 有暂时死区,在声明之前访问变量会报错
- const 声明之后必须赋值,否则会报错
- const 定义不可变的量,改变了就会报错
- const 和 let 一样不会与 window 相映射、支持块级作用域、在声明的上面访问变量会报错
9.H5 C3新特性
H5 新特性
1、拖拽释放(Drap and drop) API ondrop
拖放是一种常见的特性,即抓取对象以后拖到另一个位置 ,在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放
2、自定义属性 data-id
3、语义化更好的内容标签(header,nav,footer ,aside, article, section)
4、音频 ,视频(audio, video) 如果浏览器不支持自动播放怎么办?在属性中添加 autoplay
5、画布 Canvas image 是通过对象的形式描述图片的,canvas 通过专门的 API 将图片绘制在画布上.
6: 地理(Geolocation) API
7、 本地离线存储 localStorage 长期存储数据 浏览器关闭后数据不丢失
8、 sessionStorage 的数据在浏览器关闭后自动删除
9、 表单控件 :calendar , date , time , email , url , search , tel , file , number
10、新的技术 webworker, websocket , Geolocation
CSS3 新特性
1、颜色: 新增 RGBA , HSLA 模式
2、文字阴影(text-shadow)
3、边框: 圆角(border-radius) 边框阴影 : box-shadow
4、盒子模型: box-sizing
5、背景:background-size 、background-origin 、background-clip
6、渐变: linear-gradient , radial-gradient
7、过渡 : transition 可实现动画
8、自定义动画 animate :@keyfrom
9、媒体查询 多栏布局 @media screen and (width:800px) {…}
10、border-image
11、2D 转换;transform: translate(x,y) rotate(x,y) skew(x,y) scale(x,y)
12、3D 转换
13、字体图标 font-face
14、弹性布局 flex
10.Vue的基本原理,vue路由,vue组件传值
Vue的基本原理:Vue的数据驱动是通过MVVM模式来实现的;
Vue 的路由实现模式:hash 模式和 history 模式(必会)
hash http://baidu/#/login
- 前进 后退 刷新 都ok
- #/login 是hash值,hash值是不会影响请求
- 采用的是window.οnhashchange=()=>{} 原理实现,是可以兼容IE678的
history http://baidu/login
- 前进 后退 ok。刷新:如果后端有这个路由,就会直接展示后端数据到页面;如果后端没有这个路由,404.
- /login 是会影响请求
- HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法
- 如果想使用history模式,需要后端配合。
vue组件传值
父传子 :在父组件引用的子组件上绑定一个自定义属性并把数据绑定在自定义属性上,在子组件添加参数 props 接收即可
子传父 :子组件通过this.$emit
进行触发自定义事件并且可以携带参数,父组件监听使用@(v-on) 进行监听,然后进行方法处理
兄弟组件:eventBus也就是创建一个事件总线当作中间站
- 创建一个
eventBus = new Vue
- 触发eventBus自定义事件
eventBus.$emit("事件名",参数)
- 监听eventBus自定义事件
eventBus.$on("事件名",fun(参数))
- 取消监听
eventBus.$off("事件名")
11.v-show 和 v-if 指令的共同点和不同点
-
相同点: v-show 和 v-if 都能控制元素的显示和隐藏。
-
不同点:
-
实现本质方法不同
v-show 本质就是通过设置 css 中的 display 设置为 none,控制隐藏
v-if 是动态的向 DOM 树内添加或者删除 DOM 元素
-
编译的区别
v-show 其实就是在控制 css
v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
-
编译的条件
v-show 都会编译,初始值为 false,只是将 display 设为 none,但它也编译了
v-if 初始值为 false,就不会编译了
-
性能比较
v-show 只编译一次,后面其实就是控制 css,而 v-if 不停的销毁和创建,故 v-show 性能更好。
因为 v-show 实际是操作 display:" "或者 none,当 css 本身有 display:none 时,v-show 无法让显示
-
生命周期比较
v-show不会引起生命周期的变化
v-if如果用于普通元素则会会触发父组件的
beforeUpdate
和updated
钩子函数;如果用于组件则会触发父元素的更新之外还会触发子元素的生命周期
-
总结(适用场景):
如果要频繁切换某节点时,使用 v-show(无论 true 或者 false 初始都会进行渲染,此 后通过 css 来控制显示隐藏,因此切换开销比较小,初始开销较大),
如果不需要频繁切换某节 点时,使用 v-if(因为懒加载,初始为false 时,不会渲染,但是因为它是通过添加和删除 dom 元素来控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)
12.深拷贝和浅拷贝、原型链
1.拷贝
**浅拷贝:**只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块堆内存。 因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
**深拷贝:**会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。深拷贝相比于浅拷贝速度较慢并且花销较大。
深拷贝的方法
JSON.parse(JSON.stringify())
将一个对象先转为json字符串,然后再转回来,这样可以实现深拷贝。但是这个方法有个缺陷,可以实现对象或数组的深拷贝,但是不能处理函数,函数经过这样处理后会变成null- es6使用展开运算符
...
- 用递归实现完全深拷贝
2.原型
JavaScript 原型: 每个对象都会在其内部初始化一个属性,就是 prototype(原型)
原型链概念: 是一种查找机制,当前实例用到某个属性或方法,当前实例自己有先用私有的,私有的没有,那么他就会去 prototype 里找这个属性,这个 prototype又会有自己的 prototype,于是就这样一直找下去,直到为null
13.localstorage、sessionStorage、cookie 的区别
-
**共同点:**都是保存在浏览器端、且同源的
-
区别:
1、cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器和服务器间来回传递,
而 sessionStorage 和 localStorage 不会自动把数据发送给服务器,仅在本地保存。
cookie 数据还有路径(path)的概念,可以限制 cookie 只属于某个路径下
2、存储大小限制也不同,cookie 数据不能超过 4K,同时因为每次 http 请求都会携带 cookie、 所以 cookie 只适合保存很小的数据,如会话标识。
sessionStorage 和 localStorage 虽然也有存 储大小的限制,但比 cookie 大得多,可以达到 5M 或更大
3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;
localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
cookie:只在设置的 cookie 过期时间之前有效,即使窗口关闭或浏览器关闭
4、作用域不同,sessionStorage 不在不同的浏览器窗口中共享,即使是同一个页面;
localstorage 和cookie是在所有同源窗口中都是共享的
5、web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者
6、web Storage 的 api 接口使用更方便
14.Vuex 的 5 个核心属性
分别是 State、 Getter、Mutation 、Action、 Module
Vuex使用单一状态树,即用一个对象就包含了全部的状态数据。
- state定义了所有我们需要的基本状态参数。
- getter导出数据
- mutation更改 store 中 state状态。
内容
方法名(state,形参) { state.数据 = 形参}
使用:
storemit('方法',实参)
- action 异步操作。
一般用于做逻辑操作,调用mutation中的方法修改state
内容:
方法名(context,形参) {}
使用:
store.dispatch("方法",实参)
- module 解决了当 state 中很复杂臃肿的时候,module 可以将 store 分割成模块,每个模块中拥有自己的 state、mutation、action 和 getter。子模块导出时要开启命名空间
namespaced: true
集体调用
import { mapGetters, mapActions } from "vuex";
export default {
computed:{
...mapGetters({
banner:"home/banner",
})
},
methods:{
...mapActions({
reqBanner:"home/reqBanner",
})
},
}
15.JS 执行机制(事件循环)
js执行流程
- 同步
process.nextTick(fun())
- 微任务(Promise.then,then后面的才是微任务,前面是同步)
- 宏任务(setTimeout,setInterval)
setImmediate(fun())
js执行机制
同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入任务队列。主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。
16.一个页面从输入 URL 到页面加载显示完成过程中都发生了什么(高薪常问)
-
浏览器地址栏输入url
-
浏览器会先查看浏览器缓存–系统缓存–路由缓存,如有存在缓存,就直接显示。如果没有,接着第三步
-
域名解析(DNS)获取相应的ip
-
浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手
-
握手成功,浏览器向服务器发送http请求,请求数据包
-
服务器请求数据,将数据返回到浏览器
-
浏览器接收响应,读取页面内容,解析html源码,生成DOm树
-
解析css样式、浏览器渲染,js交互绑定多个域名,数量不限;
三次握手(建立连接)
- 主机向服务器发送一个建立连接的请求(您好,我想认识您);
- 服务器接到请求后发送同意连接的信号(好的,很高兴认识您);
- 主机接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您)
自此,主机与服务器两者建立了连接。
TCP 协议
三次握手的过程采用 TCP 协议,其可以保证信息传输的可靠性,三次握手过程中,若一方收不到确认信号,协议会要求重新发送信号。
四次挥手(断开连接)
- 主机向服务器发送一个断开连接的请求(不早了,我该走了);
- 服务器接到请求后发送确认收到请求的信号(知道了);
- 服务器向主机发送断开通知(我也该走了);
- 主机接到断开通知后断开连接并反馈一个确认信号(嗯,好的),服务器收到确认信号后断开连接;
17.Javascript 垃圾回收机制
一般来说没有被引用的对象就是垃圾,就是要被清除, 有个例外如果几个对象引用形成一个环,互相引用,但根本访问不到它们,这几个对象也是垃圾,也要被清除。 垃圾回收的方法主要有两种:一种是标记清除,即用完之后的变量 赋值成null,另一种 是引用计数,将使用完的对象的引用计数,如果为0则回收
18.Vue 常用的修饰符都有哪些
.prevent
取消默认事件
.stop:
阻止单击事件冒泡;
.self
当事件发生在该元素本身而不是子元素的时候会触发;
.capture:
捕获
阻止冒泡
e.stopPropagation()
ie浏览器e.cancelBubble = true
取消默认事件
e.preventDefault()
ie浏览器e.returnValue = false
19.webpack???
-
定义:wbpack 是一个打包模块化 javascript 的工具,在 webpack 里一切文件皆模块,通过 loader
转换文件,通过 plugin 注入钩子,最后输出由多个模块组合成的文件,webpack 专注构建模块化
项目,webpack 可以看做是模块打包机:它做的事情是,分析你的项目结构,找到 JavaScript 模
块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript 等),并将其打包为合适
的格式以供浏览器使用。
-
优点:1、专注于处理模块化的项目,能做到开箱即用,一步到位
2、通过 plugin 扩展,完整好用又不失灵活
3、使用场景不局限于 web 开发
4、社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源 扩展
5、提供了更好的开发体验
-
Loader 和 Plugin 的不同:
-
1,1)Loader 直译为"加载器"。webpack 将一切文件视为模块,但是 webpack 原生是只能 解析 js 文件,如果想将其他文件也打包的话,就会用到 loader。 所以 Loader 的作用是让 webpack 拥有了加载和解析非 JavaScript 文件的能力。
-
1,2)Plugin 直译为"插件",Plugin 可以扩展 webpack 的功能,让 webpack 具有更多的灵
活性。 在 webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的
时机通过 webpack 提供的 API 改变输出结果
-
20.数组去重的方法
1.新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。
function unique(arr) {
var array = [];
for (var i = 0; i < arr.length; i++) {
if (array .indexOf(arr[i]) === -1) {
array .push(arr[i])
}
}
return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}没有去重
2.双重for循环。双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //第一个等同于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}] //NaN和{}没有去重,两个null直接消失了
3.利用 filter
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item) === index;
});
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
4.使用es6语法中的Set()
方法
function unique (arr) {
return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
map和Set的区别
- map返回数组,Set返回类数组集合。
- map以键值对存储
21.git的作用和流程???
-
项目开始执行流程
- 连接远程仓库
git remote add origin https://gitee/hao-liuting/u_back.git
- 克隆代码
git clone "地址"
- 拉取线上最新代码
git pull origin master
- 开发
- 将所有文件提交到缓存区
git add .
- 提交自己的代码到本地仓库
git commit -m "存自己"
- 拉取远程代码,如果你的同事今天有人推送过,一定要拉取
git pull
git add .
git commit -m "说明"
git push
- 连接远程仓库
-
git 的作用
- 在工作目录中修改某些文件
- 对修改后的文件进行快照,然后保存到暂存区域
- 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中
22.git 中产生冲突的原因及解决办法???
- 原因:和别人同时修改同一个文件,他提交后我再提交就会报冲突的错误。
- 解决:
- 在 IDE 里面一般都是对比本地文件和远程分支的文件,然后把远程分支上文 件的内容手工修改到本地文件,然后再提交冲突的文件使其保证与远程分支的文件一致, 这样才会消除冲突,然后再提交自己修改的部分。
- 也可以使用命令
- 通过 git stash 命令,把工作区的修改提交到栈区,目的是保存工作区的修改;
- 通过 git pull 命令,拉取远程分支上的代码并合并到本地分支,目的是消除冲突;
- 通过 git stash pop 命令,把保存在栈区的修改部分合并到最新的工作空间中;
23.promise的方法
const fun = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
fun().then((a)=>{}).catch((b)=>{})
实例的方法
.then((value)=>{})
,取到的是 成功之后的结果,可以实现异步的深层嵌套.catch((errior)=>{})
取到失败的结果是.then(null, rejection)
的别名.finnaly(()=>{})
成功和失败最后都会执行这个方法
静态方法 (挂载到构造函数上面的 )
.all([]).then
用于将多个 Promise 实例,包装成一个新的 Promise 实例,数组里面所有的promise全部成功,才执行.then()
,有一个失败则失败.race([]).then()
与all类似,只要有一个成功就执行成功(.then()
)
24.css3动画
1.帧动画
animation-name:设置动画名字(自定义);
animation-duration:动画持续时间;
animation-timing-function:动画运动形式;
@keyframes 动画名称{0%{...}100%{...}}
2.3D转换
- 产生一个3D空间
transform-style: preserve-3d;
- 景深
perspective:像素;
transfrom:scale3d() translate3d() rotate3d();
25.key的作用
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,为了确保它们在每个索引位置正确渲染,提高更新虚拟DOM的效率,给每个元素提供一个唯一的key用于跟踪每一个节点的身份。
26.单页面应用SPA
SPA:多个url—>1个html
[优点:用户体验好 缺点:首屏加载速度慢,不利于SEO优化]
MPA:多个url–>多个HTML文件 多页面应用
[优点:有利于SEO优化,缺点:会出现白屏,用户体验度不好]
27.v-if和v-for的优先级
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,这意味着 v-if 将分别重复运行于每个 v-for 循环中。所以,不推荐v-if和v-for同时使用。
28.watch和computed
浅监听watch:{监听的数据(newVal,oldVal){}}
深度监听:添加deep:true
watch:{
监听的数据:{
handler(newVal,oldVal){
//逻辑
},
deep:true
}
}
不建议使用深度监听,会造成卡顿,使用事件代替
watch:
- 一个数据影响多个数据的改变
- 没有调用,自动执行
- 可以操作异步
computed:
- 多个数据影响一个数据
- 手动调用,当做属性调用
- 做同步
- 可以有缓存
29.动画
1.<transition></transition>
将内容包裹
2.设置name属性
3.安装npm i animate.css
30.自定义组件
<template>
<div></div>
</template>
<script>
export default {
}
</script>
<style>
</style>
31.动态组件
<div :is="showCom"></div>
32.插槽
- 匿名插槽
- 具名插槽
- 作用域插槽。当子组件做循环显示列表 或 某一部分由外部传递进来 时,则使用 作用域插槽
<div class="box">
<!-- 具名插槽 -->
<slot name="top"></slot>
<h3>this is two</h3>
<slot name="bottom"></slot>
</div>
33.混入mixins
import 名称 from "地址"export default { mixins:[名称]}
34.路由跳转(导航)
声明式导航
<router-link to="/index">前往首页</router-link>
编程式导航
this.$router.push("/search")
是添加了新的历史记录this.$router.replace("/search")
是使用新的记录替换当前记录
35.路由懒加载
{path:"/menu",component:()=>import ("")}
()=>Promise.resolve(import(""))
36.守卫(路由的钩子函数)
全局守卫【router/index.js】
router.beforeEach((to,from,next)=>{next()})
rotuer.afterEach((to,from,next)=>{next()})
路由独享守卫【router/index.js】与路由地址一级
beforeEnter(to,from,next){next()}
组件内部守卫:【在vue组件中】
beforeRouteEnter(to,from,next){next()}
beforeRouteUpdate(to,from,next){next()}
beforeRouteLeave(to,from,next){next()}
37.axios api封装
-
判断开发环境
process.env.NODE_ENV === "development"
-
判断生产环境
process.env.NODE_ENV === "production"
-
请求拦截,添加请求头
axios.interceptors.request.use(config => {return config})
-
响应拦截
axios.interceptors.response.use(res => {return res})
-
导出get请求
-
导出post请求
-
有文件
params=new FormData(); for(let i in data){ params.append(i,data[i]) }
-
无文件
params=qs.stringify(data)
-
案例
// 1.引入依赖包
import axios from "axios"
import Vue from "vue"
import qs from "querystring"
// 2.环境配置
//开发环境
if (process.env.NODE_ENV === "development") {
Vue.prototype.$pre = "http://localhost:3000"
}
//生产环境(上线)
if (process.env.NODE_ENV === "production") {
Vue.prototype.$pre = ""
}
// 3.请求拦截
axios.interceptors.request.use(config => {
//加请求头
return config;
})
// 4.响应拦截
axios.interceptors.response.use(res => {
//打印
console.log("本次请求地址:" + res.config.url);
console.log(res);
//失败处理
if (res.data.code !== 200) {
alert(res.data.msg)
}
return res;
})
/**
* eg:get("/api/getCate",{}).then(res)
*
* @param {*} url 请求地址
* @param {*} [params={}] 请求参数集合
*/
export function get(url,params={}) {
return axios({
url,
method: "get",
params
})
}
/**
* eg:post("/login",{phone:"123"}).then(res=>{})
*
* @param {*} url 请求地址
* @param {*} [data={}] 请求参数集合,默认是{}
* @param {boolean} [isFile=false] 用来判断是否有文件,有就传true;没有不需要传参
* @returns
*/
export function post(url,data={},isFile=false){
let params=null;
//有文件
if(isFile){
params=new FormData();
for(let i in data){
params.append(i,data[i])
}
}else{//无文件
params=qs.stringify(data)
}
return axios({
url,
method:"post",
data:params
})
}
38.路由传参
- secarch(?)传参:
this.$route.query.
- 动态路由(:)传参:
this.$route.params.
route:当前路由信息
router:路由对象
39.call、apply、bind、
都是用来改变this指向
fun.call()
第一个参数为this,后面参数接着写,会直接调用函数fun.apply()
第一个为this,后面的参数为数组,会直接调用函数fun.bind()
第一个参数为this,后面参数接着写,不会直接调用函数
40.事件流和事件委托
事件流一般分三个阶段:1、捕获阶段(由外向内) 2、目标阶段 (执行阶段) 3、冒泡阶段(由内向外)
事件代理,又称之为事件委托。“事件代理”是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。e.target.nodeName.toLowerCase() == 'li'
41.rem与em的区别
rem相对于根元素,em相对于父元素。
42.promise和await/async 、generator
generator是微任务
async…await是Generator函数的语法糖,将*改成async,将yield换成await。是对Generator函数的改进, 返回promise。 异步写法同步化,遇到await先返回,执行完异步再执行接下来的. 内置执行器, 无需next()
- 都是解决异步回调,避免出现回调地狱
- async/await是基于Promise实现的,可以说是Promise的改良版
- async/await与Promise一样,是非阻塞的。
- async/await使得异步代码看起来像同步代码
- Async/Await让try/catch可以同时处理同步和异步错误
43.defineproperty与proxy的区别
-
defineproperty只能监听某个属性不能全对象监听;proxy不用设置具体属性
-
proxy不需要借助外部value
-
proxy去代理了ob,他会返回一个新的代理对象不会对原对象ob进行改动,而defineproperty是去修改原对象,修改原对象的属性,而proxy只是对原对象进行代理并给出一个新的代理对象
44.ajax与axios的区别
axios是通过Promise实现对ajax技术的一种封装,axios支持Promise语法,axios有请求拦截响应拦截
45.mvvm 和 mvc 的区别
- mvc 是比较直观的架构模式,用户操作->view(负责接收用户的输入操作)->controller(肯初栏儿)(业务逻辑处理)->model(数据持久化)->view(将结构反馈给 view)
- mvvm 是将数据模型数据双向绑定的思想作为核心,因此在 view 和 model 之间没有联系,通过 viewModel 进行交互,而且 Model 和 ViewModel 之间的交互式双向的,因此使徒的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到 view 上
46.清除浮动的方法
-
外层添加一个标签,设置
clear:both;
-
父元素添加
overflow:hidden
-
设置after伪元素清除浮动
.clearfix:after{
content: "";
display: block;
clear:both;
}
47.元素居中
绝对定位
.child {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
flex布局
.father {
display: flex;
justify-content: center;
align-items: center;
}```
### margin:auto
```css
.child {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
48.外边距塌陷问题
给父元素添加 overflow:hidden;
设置边框
49.重绘和重排
重排也叫回流,当元素因为规模尺寸,布局,隐藏等改变而需要重新构建时则成为重排。
重绘:一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局则叫重绘。
重绘不一定重排,但是重排一定重绘。
50.创建一个三角形
.triangle{
width: 0;
height: 0;
border: 100px solid transparent;
border-left-color: red;
}
51.如何检测数据类型
typeof 能够检测:数字、字符串、布尔、undefined、symbol、function
instanceof 能够检测:数组
Array.isArray([])
Object.prototype.toString.call(数据)
万能法
52.new操作符都做了哪些事情
新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。
53.$nextTick是干什么的
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
this.$nextTick(()=>{})
可以在mounted之前的生命周期中操作dom
54.vue性能优化
长列表性能优化:可以通过Object.freeze()
方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
项目要点
1.项目中遇到的问题和解决方式
-
vue项目中用v-for 循环本地图片, 图片不显示,解决办法:使用
require()
动态引入图片 -
不同组件样式相互影响,即样式污染。 解决:在当前组件中的style中,加scoped标识
-
首页白屏:由于浏览器在渲染出页面之前,需要先加载和解析相应的html,css和js文件,为此会有一段白屏的时间。解决办法:添加路由懒加载,组件异步加载 ,减少http请求,添加一个loading动画
-
页面刷新vuex被清空
- 一种方法就是用localStorage。
- 也可需要某些数据之前先判断一下数据是否存在,如果不存在重新获取
-
错误处理
由于我的请求是使用axios 单独写在了一个js,可以对其进行响应拦截。一旦失败,或者后台报错,就进行响应的错误处理以及友好提示,也避免了重复的代码,提高可维护性
2.token存储在哪里
项目中使用的token , 由于涉及到鉴权 ,需要在多个地方使用token这里把token存储到本地存储和 vuex 中【vuex刷新重置】
3.请求拦截器
axios.interceptors.request.use(config => { if (config.url !== "/api/login" && config.url !== "/api/register") { config.headers.authorization = JSON.parse(localStorage.getItem("user")).token } return config;})
4.响应拦截器
axios.interceptors.response.use(res => { //打印 console.log("本次请求地址:" + res.config.url); console.log(res); //失败处理 if (res.data.code !== 200) { Toast(res.data.msg) } return res;})
5.通过这个项目收获到了那些
- 每个步骤环环相扣,每个职位都需要和其前后的人沟通协调。
- 必要的注释,方便自己方便他人。
- 变量、常量初始化、全局函数尽量放在最上层。
- 整体把控、注重命名和重用,出现觉得不合理的和需要重用的就应该优化。
本文标签:
版权声明:本文标题:面试总结啊 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1727192323a1101559.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论