1.看过哪些框架或者类库的源码,有什么收获?
看过 vue 框架源码,对 vue 有了初步的认识,包括对 Object.defineProperty、虚拟 DOM 有一定了解,
其中的收获了有,大致明白 vue 大体可以分两个部分:
1.采用 Object.defineProperty 进行数据的双向绑定;
2.采用虚拟 DOM 技术进行视图渲染;
####2.介绍 Vue 中的常用的指令
1.v-text
指令:用于更新标签包含的文本,它的作用跟双大括号效果是一样的。
<div v-text="name"></div>
<!--等同于-->
<div>{{name}}</div>
2.v-html
:元素的 innerHTML
作用
:向指定节点中渲染包含 html 结构的内容。
与插值语法的区别
:
(1).v-html 会替换掉节点中所有的内容,则不会。
(2).v-html 可以识别 html 结构。
严重注意
:v-html 有安全性问题!
(1).在网站上动态渲染任意 HTML 是非常危险的,容易导致 XSS 攻击。
(2).一定要在可信的内容上使用 v-html,永不要用在用户提交的内容上!
3.v-if
:v-if 指令判断是否插入这个元素,相当于对元素的销毁和创建,取值为 true/false,控制元素是否需要被渲染,
4.v-show
指令:指令的取值为 true/false,分别对应着显示/隐藏
注
:v-show 和 v-if 的区别:如果需要频繁切换显示/隐藏的可以用 v-show;如果运行后不太可能需要切换显示/隐藏的可以用 v-if;
5.v-for
指令:遍历 data 中存放的数组数据,实现列表的渲染。(v-for 指令除了可以迭代数组,还可以迭代对象和整数)
6.v-on
指令:可以绑定事件的监听器。用于处理自定义原生事件的,给按钮添加 click 并让使用变量的样式改变。
普通使用 v-on:事件名=”表达式||函数名”
简写方式@事件名="表达式"
7.v-bind
指令:用于动态绑定 DOM 元素的属性;例如<a>
标签的href
属性,<img>
标签的src
属性等。v-bind 可以简写成":"
给元素的属性赋值
语法在元素上 v-bind:属性名=”常量||变量名”
简写形式:属性名="变量名"
<div v-bind:原属性名="变量"></div >
<!--等同于-->
<div:属性名="变量"></div>
8.v-model
指令:用于表单输入,实现表单控件和数据的双向绑定
。只要给 input 控件添加 v-model 指令,并指定关联的数据 content,就可以轻松把用户输入的内容绑定在 content 上。
巧记:双向数据流(绑定)
页面改变影响内存(js)
内存(js)改变影响页面
补充
:v-bind 和 v-model 的区别?
input v-model="name"
双向数据绑定页面对于 input 的 value 改变,能影响内存中 name 变量
内存 js 改变 name 的值,会影响页面重新渲染最新值
input :value="name"
单向数据绑定内存改变影响页面改变
v-model:其的改变影响其他
v-bind:其的改变不影响其他
v-bind 就是对属性的简单赋值,当内存中值改变,还是会触发重新渲染
9.v-once
指令:只渲染一次,后面元素中的数据再更新变化,都不会重新渲染。
####3、vue 中常用的事件修饰符
1..stop
:等同于 JavaScript 中的 event.stopPropagation(),防止事件冒泡
2..prevent
:等同于 JavaScript 中的 event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播)
3..capture
:与事件冒泡的方向相反,事件捕获由外到内
4..self
:只会触发自己范围内的事件,不包含子元素
5..once
:只会触发一次
4.谈谈你对 MVVM 开发模式的理解
MVVM 分别是:ModelViewViewModal
该开发模式主要体现在 vue.js 中
M 层:模型
V 层:视图
VM 层:视图模型 VM 是 MVVM 思想的核心,因为 VM 是 V 和 M 的调度者。
//VM层
var vm=new Vue({
el:'#app',
data:{//M层
msg:'你好,vue.js'
}
})
//V层
<div id='app'>
<p>{{msg}}</p>
</div>
Model:代表数据模型,数据和业务逻辑都在 Model 中定义。
View:代表 UI 视图,负责数据的展示
ViewModel:负责监听 Model 中数据的改变并且控制视图的更新。
5、v-if 和 v-show 有什么区别
(1)、v-if 和 v-show 用于视图层显示和隐藏
(2)、v-if 的原理是根据判断条件来动态的进行增删 DOM 元素,v-show 是根据判断条件来动态的进行显示和隐藏元素,频繁的进行增删 DOM 操作会影响页面加载速度和性能,由此我们可以得出结论:
当您的项目程序不是很大的时候,v-if 和 v-show 都可以用来进行判断展示和隐藏(这种场景使用 v-if 只是影响不大,并不是没有影响);
当您的项目程序比较大的时候,不推荐使用 v-if 来进行判断展示和隐藏,推荐使用 v-show;
(3)、只有 v-if 能和 v-else 连用进行分支判断,v-show 是不能和 v-else 连用的,如果出现多种条件场景的情况下,可以使用 v-if 来进行判断
6.请详细说下你对 vue 生命周期的理解?
答:总共分为 8 个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后:
在 beforeCreated 阶段,vue 实例的挂载元素 el 和 ∗∗ 数据对象 ∗∗data 都为 undefined,还未初始化。
在 created 阶段,vue 实例的数据对象 data 有了,el 还没有。
载入前/后:
在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的 dom 节点,data.message 还未替换。
在 mounted 阶段,vue 实例挂载完成,data.message 成功渲染。
更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。
销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 vue 实例已经解除了事件监听以及和 dom 的绑定,但是 dom 结构依然存在。
7、计算属性及和 watch 、methods 的区别
1、computed 必须 return 一个值,主要当做属性来使用,存在缓存;
另外 computed 属性,在 vue 里面用来触发 setter 和 getter 方法。setter 方法在设置值时触发,getter 方法在获取值时触发
methods 表示一个方法,是函数调用,主要书写业务逻辑;
watch 监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,可以看作是 computed 和 methods 的结合体
2、watch 相比于 methods 虽然有时候显得更繁琐,但是在监听非 DOM 元素时,显示出优势
当页面内部使用了复杂的逻辑表达式,首选使用计算属性,methods 方法虽然能实现,但是会增大开销,计算属性基于缓存,具有更优性。当需要在数据变化时执行异步或者开销较大的操作时,则优先考虑 watch 属性
8.跨域问题底层
同源策略的限制,跨域问题出现在浏览器端
跨域出现的原因
:(三不同)
(1)协议不同。(http 和 https)
(2)域名不同。(test 和 tests ,或者是直接请求 IP 的不同)
(3)端口号不同。(8080 和 8081)
以上三种条件都相同,就是同域,可以正常读写域内资源,有一个条件不同,请求方与响应方都属于跨域,无法进行资源访问。
这就叫做同源策略
解决方法
(跨域资源共享)cors:目前最常用的一种解决办法,通过设置后端允许跨域实现。
jsonp:由于<script></script>
,<img>
中的src
不受同源策略的限制,利用这一点,就有了 jsonp 这种非正式传输协议,所以 jsonp 解决跨域的原理是 script 标签可以跨域请求资源,将回调函数作为参数拼接在 url 中。后端收到请求,调用该回调函数,并将数据作为参数返回去,注意设置响应头返回文档类型,应该设置成 javascript。
代理和反向代理
在响应头里添加特殊请求头 Access-Control-Allow-Origin 信息。
9.你做过哪些性能的优化
1. 减少 HTTP 请求
- HTML 优化:
使用语义化标签
减少 iframe
避免重定向
- CSS 优化:
布局代码写前面
删除空样式
不滥用浮动、字体,需要加载的网络字体根据需求添加
选择器性能优化
避免使用表达式
避免用 id 写样式
压缩代码
- JS 优化
压缩代码
减少重复代码
- 图片优化
使用 webP
图片合并,CSS sprite 技术 - 雪碧图
移动端响应式图片 - @media(max-width:320px){}
2. 减少 DOM 操作
缓存已经访问过的元素
离线更新节点,再将他们添加到树中
避免使用 js 输出页面布局
3. 使用 JSON 格式进行数据交换
4. 使用 CDN 加速
5. 使用 HTTP 缓存:添加 Expires 或者 Cache-Control 信息头
6. 使用 DNS 预解析
- 用 meta 信息来告知浏览器,当前页面要做 DNS 预解析:
<meta http-equiv="x-dns-prefetch-control" content="on" />
- 在页面 header 中使用 link 标签来强制对 DNS 预解析:
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
10. vue-router 路由有几种模式?说说它们的区别?
vue-router 路由有一共有两种模式,分别是 hash 模式,history 模式
hash模式
1、 url 路径会出现 # 字符
2、hash 值不包括在 HTTP 请求中,它是交由前端路由处理,所以改变 hash 值时不会刷新页面,也不会向服务器发送请求
3、hash 值的改变会触发 hashchange 事件
history模式
1、整个地址重新加载,可以保存历史记录,方便前进后退
2、使用 HTML5 API(旧浏览器不支持)和 HTTP 服务端配置,没有后台配置的话,页面刷新时会出现 404
补充
:如果 vue-router 使用 history 模式,部署时要注意什么?
HTTP 服务端需要进行配置,将页面请求全部重定向到 index.html。参考官方文档
nginx 配置:
location / {
try_files $uri $uri/ /index.html;
}
11.说一下你对同步和异步的理解
答:同步即 sync,形象的说就是代码一行行执行,前面代码和请求没有执行完,后面的代码和请求就不会被执行,
缺点:容易导致代码阻塞
优点:程序员容易理解(因为代码从上往下一行行执行,强调顺序)
异步:即 async,形象的说就是代码可以在当前程序没有执行完,也可以执行后面的代码
缺点:程序员不易理解(因为不是按顺序执行的)
优点:可以解决代码阻塞问题,提升代码执行效率和性能
异步解决方案主要有三个:
回调函数
promise(重点掌握)
generator(了解)
async 和 await(重点掌握)
12.promise 是同步还是异步的?
1.promise 本身是同步的
let oP = new Promise((res, rej) => {
console.log(1);
});
console.log(2);
执行的结果先打印出 1 再打印出 2,如果 promise 是异步的应该先打印出 2,所以 promise 本身是同步
2.Promise 本身是同步的,他的 then 方法的回调函数和 catch 方法的回调函数是异步的
let oP = new Promise((res, rej) => {
console.log(1);
res(3)
});
oP.then((res) => {
console.log(res);
});
console.log(2);
})
执行的结果 1,2,3,因为 then 是异步的,所以先打印了 2,最后再执行回调打印出 3
补充:Promise 作用是解决异步回调的问题的方案
13.本地存储方式及区别
一、cookie
cookie 算是比较早的技术,最初是为了记录 http 的状态,提高访问速度。cookie 是服务器”种植”在客户端的 key-value 形式文本文件。但同时客户端也能操作 cookie。
特点:
大小:cookie的大小限制在4k。每个域名下cookie的个数现在在20个。
在客户端请求服务器端和服务器响应时,cookie始终被携带在http请求中,即使不需要(造成流量浪费)。这也是限制cookie大小的原因。
客户端可以通过document.cookie操作cookie,并不安全。
cookie可以设置过期时间、路径、域和httpOnly等字段。如果设置了过期时间,cookie会保存在硬盘里,知道到了设定的过期时间才会失效。若未设置过期时间,在浏览器窗口关闭时,cookie就失效了。路径和域两个字段限制了cookie的作用范围。httpOnly设置为true,则js不能通过document.cookie操作cookie。
二、localStorage
它也是采用 key-value 的形式存储数据,但是它与 cookie 有很大的区别
特点:
对比着来,localStorage能保存更大的数据,标准浏览器是5Mb。
localStorage保存在客户端,不随着请求发送给服务器,避免了流量的浪费。
客户端可以通过:setItem、getItem方法访问localStorage。
并且,localStorage没有过期时间,如果不手动清除,数据就永远不会过期,一直保存在浏览器当中。
存储的信息在同一域中是共享的。
//key,value 都必须是字符串,storage 的api 只能操作字符串
//设置
window.localStorage.setItem(key, value);
//获取
window.localStorage.getItem(key);
//删除某个数据
window.localStorage.removeItem(key);
//清除所有数据
window.localStorage.clear();
//获取某个索引的key
window.localStorage.key(index);
三、sessionStorage
特点:
与localStorage不同的是,sessionStorage并不持久化,在窗口关闭那一刻,sessionStorage会被清除。
存储的信息是会话级别的,同域也是不能共享的。关闭当前标签页,sessionStorage即失效。
//存储
sessionStorage.setItem("key","value")
//按key获取值
sessionStorage.getItem(key)
//按key 删除单个值
sessionStorage.removeItems(key)
//清除所有数据
sessionStorage.clear()
//获取数据的数量
sessionStorage.length
//获取全部值
sessionStorage.valueOf()
//sessionStorage也可存储Json对象:存储时,通过JSON.stringify()将对象转换为文本格式;读取时,通过JSON.parse()将文本转换回对象。
var userEntity = {
name: 'tom',
age: 22
};
// 存储值:将对象转换为Json字符串
sessionStorage.setItem('user', JSON.stringify(userEntity));
// 取值时:把获取到的Json字符串转换回对象
var userJsonStr = sessionStorage.getItem('user');
userEntity = JSON.parse(userJsonStr);
console.log(userEntity.name); // => tom
浏览器本地存储统称为 webStorage,包括了 localStorage 和 sessionStorage
四、session(附加)
上面提到了 cookie,顺带提一下 session。客户端第一次访问服务器,服务器种植一个 cookie,保存唯一的 sessionId。后面客户端再次访问,会读取此 sessionId,随即能在服务端读取到此 id 保存的会话对象。
特点:
session 是基于 cookie 的,由于 session 在客户端不可被修改,相对于 cookie 来说安全,所以可存放一些重要数据。
数据保存在服务器端,客户端通过 sessionId,读取到相对应的数据。
14.undfind 和 null 的区别
JavaScript 的最初版本是这样区分的:null 是一个表示”无”的对象(空对象指针),转为数值时为 0;undefined 是一个表示”无”的原始值,转为数值时为 NaN。
15.什么是作用域和作用域链
作用域(Scope)
1. 什么是作用域
作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,作用域决定了代码区块中变量和其他资源的可见性。可能这两句话并不好理解,我们先来看个例子:
function outFun2() {
var inVariable = "内层变量2";
}
outFun2(); //要先执行这个函数,否则根本不知道里面是啥
console.log(inVariable); // Uncaught ReferenceError: inVariable is not defined
从上面的例子可以体会到作用域的概念,变量 inVariable 在全局作用域没有声明,所以在全局作用域下取值会报错。我们可以这样理解:
1.作用域就是一个独立的地盘,让变量不会外泄、暴露出去。
2 . 作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行。
3.变量的作用域无非就是两种:全局变量和局部变量。
ES6 之前 JavaScript 没有块级作用域,只有全局作用域和函数作用域。ES6 的到来,为我们提供了‘块级作用域’,可通过新增命令 let 和 const 来体现。
2. 什么是作用域链
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问。
如果父级也没呢?再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是 作用域链 。
16.箭头函数带来的一些问题
1. this 指向问题
在普通函数中,this 指向根据其使用场景不同改变。而箭头函数中的 this 始终指向其父级作用域
箭头函数与普通函数对 this 的指向不同,ES6 定义时 this 指向谁执行的时候 this 就指向谁。
2. 箭头函数没有原型属性
var a = () => {};
console.log(a.prototype); // undefined
3.
箭头函数通过 apply 和 bind 调用,不会改变 this 指向,只会传入参数
4.
call、apply、bind 无法改变箭头函数中的 this。
17.函数柯里化
函数柯里化的定义:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
通过上面的定义可以看出,柯里化是一个函数返回另一个函数,这是一个典型的闭包,它封装了一部分不变的内容,然后去处理其他可变的数据
举个官网的例子:
var abc = function (a, b, c) {
return [a, b, c];
};
var curried = _.curry(abc);
curried(1)(2)(3);
// => [1, 2, 3]
curried(1, 2)(3);
// => [1, 2, 3]
curried(1, 2, 3);
// => [1, 2, 3]
18.JS 异步编程都有哪些方案
总结起来无外乎有这几种:回调函数、事件监听、Promise、Generator、async/await,这几种 JS 的编程方式都是异步编程。回调函数方式是最早的 JS 异步编程的方式,后随着 ES 标准的发展,Promise、Generator 和 async/await 接连出现。
19.关于 Vue 和 React 区别的一些笔记
- 监听数据变化的实现原理不同
Vue 通过 getter/setter 以及一些函数的劫持,能精确知道数据变化。
React 默认是通过比较引用的方式(diff)进行的
- 数据流的不同
vue 组件与 DOM 之间可以通过 v-model 双向绑定。
React 一直不支持双向绑定,提倡的是单向数据流,称之为 onChange/setState()模式。
- 框架本质不同
Vue 本质是 MVVM 框架,由 MVC 发展而来;
React 是前端组件化框架,由后端组件化发展而来。
- Vuex 和 Redux 的区别
Redux 使用的是不可变数据,而 Vuex 的数据是可变的,因此,Redux 每次都是用新 state 替换旧 state,而 Vuex 是直接修改。