1.说说vue的双向数据绑定实现原理
通过Object.definerProperty来劫持各个数据的属性的setter和getter,在数据变化时,发布消息给依赖收集器,通知观察者去执行回调函数,达到视图更新的效果。(但是使用Object.definerProperty实现监听时是有一些痛点的,比如,①无法监测数组下标变化,导致数组删除或者插入元素时,数组的变化无法实时响应;②只能对对象的属性进行监测,当对象深度比较深时,只能遍历每个属性来实现监听
2.vue如何在组件之间进行传值
props、emit、vuex、路由传参、通过本地存储传参、vue-bus(事件巴士)、 children、$parent
3.vuex和vue的双向数据绑定有什么冲突
在严格模式下vuex中的state对象中的属性是不能随意更改的,但是在表单处理时使用v-model时用户可以随意更改数据,如果vuex中的state中的属性直接绑在v-model中时会抛出一个错误 解决方法: 在严格模式中,由于这个修改不是在 mutation 函数中执行的, 所以直接拆分v-model为value和方法 这样就可以在页面赋值执行方法而不会报错
4.vue-router中的history模式和hash模式的区别
hash模式和history模式的不同 最直观的区别就是在url中 hash 带了一个很丑的 # 而history是没有#的
对于vue这类渐进式前端开发框架,为了构建 SPA(单页面应用),需要引入前端路由系统,这也就是 Vue-Router 存在的意义。前端路由的核心,就在于 —— 改变视图的同时不会向后端发出请求。 为了达到这一目的,浏览器当前提供了以下两种支持
hash : #号后面的值 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
history : 使用pushState() 或 replaceState()方法也不会向后端发送请求 即不会重新加载页面(vue使用history不会重新加载就是在路由用了这两个) 当使用 back、forward、go时,它们提供了对历史记录进行修改的功能, 也不会重新加载页面
5.说一下vue的生命周期(回答的时候,顺便说一下哪个钩子函数实现了什么功能) beforeCreate:初始化事件,进行数据观测。
created:data数据进行绑定。
beforeMount:虚拟DOM替换真实DOM。
mounted:将DOM元素挂载到页面。
beforeUpdate: data数据更新之前。
updated: data数据更新完成之后。
activated keep-alive 组件激活时调用。
deactivated keep-alive 组件停用时调用。
beforeDestroy:在实例销毁之前调用,所有实例仍可以调用。
destroyed:在实例销毁之后调用,所有实例被销毁。
6.全局自定一个v-fouce组件 自动聚焦input (一种自定义思路)
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素 el.focus()
}
})
7.谈谈你对keep-alive的了解
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。
用法: 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 相似, 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。 当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。 主要用于保留组件状态或避免重新渲染。比如A页面现在滚动的位置是1/2,然后切换到B页面,再切换回来的时候页面的滚动位置还会保留。
8.导航钩子
a、全局的钩子 beforeEach(to,from,next) afterEach(to,from,next)
b、组件内的导航钩子主要有这三种:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
用法:methods: {}, beforeRouteLeave (to, from, next) {}
需要注意是: beforeRouteEnter 不能获取组件实例 this,因为当守卫执行前,组件实例被没有被创建出来。可以用vm获取,剩下两个钩子则可以正常获取组件实例 this
9.有用过axios吗?axios是如何设置拦截器的?
Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get、post请求。 Axios特性 a、可以在浏览器中发送 XMLHttpRequests
b、可以在 node.js 发送 http 请求
c、支持 Promise API
d、拦截请求和响应
e、转换请求数据和响应数据
f、能够取消请求
g、自动转换 JSON 数据
h、客户端支持保护安全免受 XSRF 攻击 axios.interceptors.request.use(()=> {}) 请求拦截 axios.interceptors.response.use(()=> {}) 响应拦截
10.箭头函数的作用是什么
1. 箭头函数使表达更加简洁,隐式返回值 // 正常函数写法 [1,2,3].map(function (x) { return x * x; }); // 箭头函数写法 [1,2,3].map(x => x * x); //[1,4,9]
2. 没有自己的this 箭头函数中的this实际是外层函数的this(箭头函数的this对象是定义时所在的对象,而不是使用时的对象)
3. 箭头函数不能当作构造函数使用、没有prototype、没有自己的this指向、不可以使用arguments、自然不可以new
4. 不能使用argumetns,取而代之用rest参数...解决 let C = (...c) => { console.log(c); } C(1,2,3,3)
5.箭头函数没有原型对象
11.typeof与instanceof的区别
typeof 是判断参数是什么类型的实例
instanceof是用来判断一个对象在其原型链中是否存在一个构造函数的prototype属性
12.js中区分object和array方法
Array.isArray([]) //true
Array.isArray({}) //false
[] instanceof Array //true
{} instanceof Array //false
{}.constructor //返回object
[].constructor //返回Array
13.闭包是什么?
闭包(closure)就是能够读取其他函数内部变量的函数
→ 优点:
1.保护函数内的变量安全
2.在内存中维持一个变量(用的太多就变成了缺点,占内存) ;
3. 逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
4. 方便调用上下文的局部变量。
5. 加强封装性,可以达到对变量的保护作用。
→ 缺点:
1.常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
2.还有有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生。
→ 特性:
1. 函数嵌套函数
2. 内部函数可以访问外部函数的变量
3. 参数和变量不会被回收 闭包的用途 闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在调用后被自动清除。
14.如何解决跨域
1. 使用JSONP 利用动态脚本的src属性变相地发送了一个get请求
2. 利用$.ajax方法,只要指定dataType为jsonp
3. postMessage跨域
4. document.domain + iframe跨域 (主域相同)
5. window.name + iframe跨域(主域相同)
6. webpack的proxy进行代理域名
15.视频直播流程
采集视频音频 —>处理(加滤镜 logo等)—>编码和封装(压缩大小和添加视频格式avi等)—>推流到服务器—>服务器流分发—>播放器流播放
16.localStorage、sessionStorage和cookie的区别
cookie机制:如果设置的cookie未过期,关闭浏览器时会保存在硬盘,再次打开浏览器可继续使用,每次HTTP请求都会将Cookie自动发送到服务器
cookie只能保存字符串类型,以文本的方式,;session能支持任何类型的对象(session中可含有多个对象)
存储的大小:cookie:单个cookie保存的数据不能超过4kb;session大小没有限制 sessionStorage为临时保存,而localStorage为永久保存
存储大小:localStorage和sessionStorage的存储数据大小一般都是:5MB
应用场景:localStoragese:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。sessionStorage:敏感账号一次性登录
17.js栈和堆的区别
栈(stack)会自动分配内存空间,会自动释放,一般用于储存基础类型。
堆(heap)动态分配的内存,大小不定也不会自动释放,一般用于储存引用类型。
传值和传址(传内存地址而不是对象本身)的区别
栈(stack)先进后出,会把新添加的元素推入栈顶
堆是一种无序的key-value存储方式,不遵循先进先出或后进先出的原则。堆的存取方式与顺序无关,数据可以从任意一端插入和取出
18.说说你对 SPA 单页面的理解
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。
优点
用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
基于上面一点,SPA 相对对服务器压力小;
前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
SEO 难度较大
19.你有对 Vue 项目进行哪些优化
1)代码层面的优化 v-if 和 v-show 区分使用场景
computed 和 watch 区分使用场景
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if 长列表性能优化
事件的销毁
图片资源懒加载
路由懒加载
第三方插件的按需引入
优化无限列表性能
服务端渲染 SSR or 预渲染
2)Webpack 层面的优化
Webpack 对图片进行压缩
减少 ES6 转为 ES5 的冗余代码
提取公共代码
模板预编译
提取组件的 CSS
优化 SourceMap
构建结果输出分析
Vue 项目的编译优化
20.原型链
原型链是JavaScript中实现对象继承的一种机制
function Father() { let colors = [1,2,3]; return colors; }
const instance = new Father(); // 实例
const prototype = Father.prototype; // 原型
因此看得出三者的关系:
实例.__proto__===原型
原型.constructor === 构造函数
构造函数.prototype === 原型
实例.constructor === 构造函数
21.new操作符实现原理
新生成一个对象
链接到原型
绑定this
返回新对象(如果构造函数有自己 retrun 时,则返回该值)
22. vuex实现原理
Vue.use(vuex)会调用vuex的install方法 在beforeCreate钩子前混入vuexInit方法,vuexInit方法实现了store注入vue组件实例,并注册了 vuex store的引用属性$store
Vuex的state状态是响应式,是借助vue的data是响应式,将state存入vue实例组件的data中
Vuex的getters则是借助vue的计算属性computed实现数据实时监听
mutations 和 actions 都要在组件的methods中使用 ,而state和getters都是在组件中的computed中使用
commit: 用来提交当前模块的mutations
dispatch: 用来提交当前模块的actions(actions可以提交mutations,可以进行异步操作)
commit 有些做不到的可以用 dispatch 进行提交 commit: 同步操作 存储 this.store.state.changeValue
dispatch: 异步操作 存储 this.store.getters.getlists
1、state => 基本数据(数据源存放地)
2、getters => 从基本数据派生出来的数据
3、mutations => 提交更改数据的方法,同步
4、actions => 像一个装饰器,包裹mutations,使之可以异步。 如果mutation支持异步操作,就没有办法知道状态是何时更新的
vuex的缺点
刷新浏览器,vuex中的state会重新变为初始状态。 可以用插件vuex-persistedstate解决
23. less、sass 的区别
1.编译环境不一样 Sass是在服务端处理的 而Less是需要引入less.js来处理
2.变量符不一样,Less是@,而Scss是$ 3.Sass支持条件语句,可以使用if{}else{},for{}循环等等。而Less不支持。
24. 常见的兼容性问题及解决办法
-
不同浏览器存在默认间距, 解决:设置间距为0
-
IE6、7和遨游里这个标签的高度不受控制,超出自己设置的高度。解决:设置overflow:hidden
-
IE6的间距比超过设置的间距。 解决:在display:block;后面加入display:inline;display:table;
-
图片有间距。解决:浮动或者flex
-
根据内核兼容样式。例: -webkit-opacity:0.5;
25. 懒加载的实现
使用懒加载时,我们的src的值默认是”正在加载中“的GIF,data-lazyload是自定义属性,用于存放图片真实路径。对于用户来说,看得到的地方才需要加载,看不到的地方加载了也是白白浪费资源。所以我们知道,在可视区域中,我们才需要加载图片。
26. js通讯方式
通信的方式有很多例如websocket,Ajax,postMessage,发布订阅模式等等
27. OSI七层模型与TCP/IP五层模型
OSI定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层)
TCP/IP五层协议:物理层、数据链路层、网络层、传输层、应用层
28. http1.0和2.0的区别
http1.0连接可以复用,节省了多次打开TCP连接加载网页文档资源的时间。 1.增加流水线操作,允许在第一个应答被完全发送之前就发送第二个请求,以降低通信延迟。 2.支持响应分块。 3.引入额外的缓存控制机制。 4.引入内容协商机制。 5.Host头,能够使不同域名配置在同一个IP地址的服务器上。
在1.1版本允许同时发送多个请求,服务器按照顺序处理请求,等A响应后再处理B请求,由此产生了我们所说的线头阻塞 所以2.0版本可以分优先级处理响应,不会出现线头阻塞。同时引入了服务器推送(socket)增加了客户端与服务器双向通信的能力。
29. http和websocket的区别
http协议是短链接,因为请求之后,都会关闭连接,下次重新请求数据,需要再次打开连接。 WebSocket协议是一种长连接,只需要通过一次请求来初始化链接,然后所有的请求和响应都是通过这个TCP链接进行通信
原理:WebSocket协议是一种长连接,初始化链接之后,客户端和服务端一直保持着通信,服务端就可以主动推送信息给客户端。它属于应用层的协议,它基于TCP传输协议,并复用HTTP的握手通道
30. WebSocket的简单操作
const ws = new WebSocket('ws://localhost:8080/')
ws.onopen=()=>{ } // 连接socket
ws.onmessage=(msg)=>{ } //监听接受来自服务端的信息
ws.onclose=()=>{ } // 关闭socket
ws.send('nihao你好啊') //向服务端发送信息
31.sync修饰符
sync修饰符是一个语法糖,类似v-model,它主要是解决了父子组件的双向绑定问题。
做了两步动作:
1、声明传的数据visible
2、声明@update:visible事件
sync和v-model的区别
1、父组件传给子组件value
2、子组件通过触发input事件来修改value
因此,子组件必须有input标签才行。
而sync不限制标签,因此子组件在修改数据时,就必须约定使用@update:xxx
32. Vue里面的data为什么必须是函数
1、每个组件都是 Vue 的实例。
2、当 data 的值是同一个引用类型的值时,它就会共用一个内存地址,改变其中一个组件的值会影响全部使用该组件的值。
3、当我们组件中的data写成一个函数时,数据是以函数返回值形式定义的,这样每复用一次data,都会返回一份新的data,拥有自己的作用域,不会产生数据污染。
33. 封装子组件的核心或注意点
低耦合,高兼容
低耦合:子组件低耦合,尽量把业务和共享状态都放在父组件处理
高兼容: 使用父传子和插槽的方式,多兼容其他使用的页面
34. js作用域
什么是作用域:作用域是变量、函数和对象的可访问性。
作用域又分为全局作用域,局部作用域,块级作用域
块级作用域:如if 和 switch条件语句 for循环语句,在ES6及之后的版本,这些块语句也会创建一个新的作用域,块级作用域可通过新增命令let和const声明,所声明的变量在指定块的作用域外无法被访问
35. 构造函数与普通函数的区别
1.this指向不一样 构造函数内部this指向新创建的对象实例 通函数this指向window(非严格模式)或者undefined(严格模式)
2.定义 构造函数默认使用首字母大写的形式去定义,通常都是面向对象 (定义物种 比如 :鸟) 普通函数面向是过程 (定义动作 比如 :飞行)
3.return 普通函数return后面 有值正常返回 构造函数一般不需要使用return返回基本类型值。 如果返回值是引用类型时,会直接返回引用类型本身
4.箭头函数不能用作构造器,和 new一起用会抛出错误
36.怎么处理web-view的缓存
造成web-view无法刷新的原因:
1.浏览器缓存;
2.url地址被缓存
解决方法:
1.针对url地址没刷新的问题,可以在webview组件的src里面添加一个时间戳
2.在index.html的head头部添加不缓存的配置
3.在webpack打包的时候加上 hash配置。
原理:打包的资源文件路径里自动带有一串随机字 符串,称为 hash。每次 build 都会生成不同的 hash,所以每次编译部署,都不会有缓存问题
37.观察者模式和发布订阅模式的区别
观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心
观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰,在调度中心可以做一些权限控制和节流之类的操作
双向绑定属于发布订阅模式,dep订阅收集器就是他的调度中心
文章只是作为一个知识点的记录
入门前端人员,如果理论有错,欢迎各位大佬纠正
如果是描述不够详细,那是因为我还理解不到那么深奥的地方(理直气壮)