javascript面试总结
谈谈你对MVVM开发模式的理解
MVVM分为Model、View、ViewModel三者。
Model 代表数据模型,数据和业务逻辑都在Model层中定义;
View 代表UI视图,负责数据的展示;
ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;
Model 和 View 并无直接关联,而是通过 ViewModel 来进行联系的,Model 和 ViewModel 之间有着双向数据绑定的联系。因此当 Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步。
这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。
具有以下优点:
1. 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2. 可重用性:你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3. 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
4. 可测试:界面素来是比较难于测试的,测试可以针对ViewModel来写。
Vue 有哪些指令?
v-html:输出真正的HTML
v-pre:跳过大量没有指令的节点加快编译
v-cloak:这个指令是用来保持在元素上直到关联实例结束时进行编译
v-once:v-once关联的实例,只会渲染一次
v-if:v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素
v-else:v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用
v-else-if:v-else-if充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句
v-text:v-text主要用来更新textContent,可以等同于JS的text属性
v-show:也是用于根据条件展示元素。和v-if不同的是,如果v-if的值是false,则这个元素被销毁,不在dom中。但是v-show的元素会始终被渲染并保存在dom中,它只是简单的切换css的dispaly属性
v-for:用v-for指令根据遍历数组来进行渲染
v-bind(简写冒号【 :】):动态的绑定一个或者多个特性
v-model:这个指令用于在表单上创建双向数据绑定。v-model会忽略所有表单元素的value、checked、selected特性的初始值。因为它选择Vue实例数据做为具体的值;
v-model修饰符
.lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。
.number 自动将用户的输入值转化为数值类型
.trim 自动过滤用户输入的首尾空格
v-on(简写【 @ 】):v-on主要用来监听dom事件,以便执行一些代码块。表达式可以是一个方法名;
事件修饰符
.stop 阻止事件继续传播
.prevent 事件不再重载页面
.capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件将只会触发一次
.passive 告诉浏览器你不想阻止事件的默认行为
简述Vue的响应式原理
Vue 的响应式原理是核心是通过 ES5 的保护对象的 Object.defindeProperty 中的访问器属性中的 get 和 set 方法,data 中声明的属性都被添加了访问器属性,当读取 data 中的数据时自动调用 get 方法,当修改 data 中的数据时,自动调用 set 方法,检测到数据的变化,会通知观察者 Wacher,观察者 Wacher自动触发重新render 当前组件(子组件不会重新渲染),生成新的虚拟 DOM 树,Vue 框架会遍历并对比新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实 DOM 树上。
Vue中如何在组件内部实现一个双向数据绑定
父组件通过 props 传值给子组件,子组件通过 $emit 来通知父组件修改相应的props值
Vue中如何监控某个属性值的变化
可以通过watch 和计算属性computed
Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决
属性会添加进去但是不能形成双向绑定,可以用this.$set(this.obj, 'b', 'obj.b') 来动态添加属性并实现双向绑定
delete和Vue.delete删除数组的区别
delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。Vue.delete直接删除了数组 改变了数组的键值。
如何优化SPA应用的首屏加载速度慢的问题
将公用的JS库通过script标签外部引入,减小chunk-vendors.js的大小,让浏览器并行下载资源文件,提高下载速度;在配置 路由时,页面和组件使用懒加载的方式引入,在调用某个组件时再加载对应的js文件;文件传输采用压缩传输;加一个首屏 loading 图,提升用户体验;最后实在不行可以采用服务器渲染
前端如何优化网站性能
1.减少HTTP请求:图标合并,js合并,css合并等
2.使用CDN
3.添加Expires头(即利用浏览器缓存)
4.压缩传输
5.css文件放到文件头部
6.js文件放到文件尾部
7.减少DNS查找:建议将组件放到至少两个但不多于4个主机名下,减少DNS查找的同时也允许高度并行下载。
8.精简并压缩js和css
9.避免重定向
10.http和ajax的 get请求可以被缓存,尽量采用get
网页从输入网址到渲染完成经历了哪些过程
大致可以分为如下7步:
输入网址;
发送到DNS服务器,并获取域名对应的web服务器对应的ip地址;
与web服务器建立TCP连接;
浏览器向web服务器发送http请求;
web服务器响应请求,并返回指定url的数据(或错误信息,或重定向的新的url地址);
浏览器下载web服务器返回的数据及解析html源文件;
生成DOM树,解析css和js,渲染页面,直至显示完成;
jQuery获取的dom对象和原生的dom对象有何区别
js原生获取的dom是一个对象,jQuery对象就是一个数组对象,其实就是选择出来的元素的数组集合,所以说他们两者是不同的对象类型不等价。
jQuery如何扩展自定义方法
(jQuery.fn.myMethod=function () {
alert('myMethod');
})
// 或者:
(function ($) {
$.fn.extend({
myMethod : function () {
alert('myMethod');
}
})
})(jQuery)
使用:
$("#div").myMethod();
计算属性和 watch 的区别
计算属性是自动监听依赖值的变化,从而动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情。
所以区别来源于用法,只是需要动态值,那就用计算属性;需要知道值的改变后执行业务逻辑,才用 watch,用反或混用虽然可行,但都是不正确的用法。
说出一下区别会加分
computed 是一个对象时,它有哪些选项?
computed 和 methods 有什么区别?
computed 是否能依赖其它组件的数据?
watch 是一个对象时,它有哪些选项?
有get和set两个选项
methods是一个方法,它可以接受参数,而computed不能,computed是可以缓存的,methods不会。
computed可以依赖其他computed,甚至是其他组件的data
watch 配置
handler
deep 是否深度
immeditate 是否立即执行
总结
当有一些数据需要随着另外一些数据变化时,建议使用computed。
当有一个通用的响应数据变化的时候,要执行一些业务逻辑或异步操作的时候建议使用watcher
组件中 data 为什么是函数(为什么组件中的 data 必须是一个函数,然后 return 一个对象,而 new Vue 实例里,data 可以直接是一个对象?)
因为组件是用来复用的,JS 里对象是引用关系,这样作用域没有隔离,而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。
keep-alive的应用场景和特点
特点:
有时候我们不希望组件被重新渲染影响使用体验;或者处于性能考虑,避免多次重复渲染降低性能。而是希望组件可以缓存下来,维持当前的状态。这时候就可以用到keep-alive组件。
场景:
商品列表页点击商品跳转到商品详情,返回后仍显示原有信息订单
列表跳转到订单详情,返回,等等场景。
生命周期:
初次进入时:created > mounted > activated;退出后触发 deactivated再次进入:会触发 activated;事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中
语法糖 v-model 是怎样实现的
v-model本质上就是语法糖,即利用v-model绑定数据后,其实就是既绑定了数据,又添加了一个input事件监听:
`` 等价于``
怎样理解单向数据流
这个概念出现在组件通信。父组件是通过 prop 把数据传递到子组件的,但是这个 prop 只能由父组件修改,子组件不能修改,否则会报错。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
vue的生命周期
beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
create:data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作
beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
beforeUpdate: 当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
updated:页面显示的数据和data中的数据已经保持同步了,都是最新的
beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
destroyed: 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
简述一下provide/inject
provider/inject:简单的来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。prop只能用于父子组件间通信, 如果层次更深,就可使用provide/inject
组件间的通信
父子 props/event children ref provide/inject
兄弟 bus vuex
跨级 bus vuex provide.inject
路由的跳转方式
router-link标签会渲染为标签,咋填template中的跳转都是这种;
另一种是编程是导航 也就是通过js跳转 比如 router.push('/home')
route的区别
router为VueRouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象,例如history对象。。。经常用的跳转链接就可以用this.$router.push,和router-link跳转一样
route相当于当前正在跳转的路由对象。。可以从里面获取name,path,params,query等
谈谈slot插槽
slot简介
vue路由的钩子函数
第一种:全局导航钩子
router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
第二种:组件内的钩子;
beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave
第三种:单独路由独享组件。
beforeEnter
每个钩子方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
聊聊你对Vue.js的template编译的理解?
compile是从mount后开始进行中, 整体逻辑分为三个部分
解析器(parse) - 将 模板字符串 转换成 element ASTs
优化器(optimize) - 对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化
代码生成器(generate) - 使用 element ASTs 生成 render 函数代码字符串
vue-router实现原理?
前端路由简介以及vue-router实现原理
vuex有哪几种属性?
分别是 State、 Getter、Mutation 、Action、 Module
vuex的State特性
一、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data
二、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
三、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
vuex的Getter特性
一、getters 可以对State进行计算操作,它就是Store的计算属性
二、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
三、 如果一个状态只在一个组件内使用,是可以不用getters
vuex的Mutation特性
一、Action 类似于 mutation,不同在于:
二、Action 提交的是 mutation,而不是直接变更状态。
三、Action 可以包含任意异步操作
自定义指令(v-check、v-focus)的方法有哪些?它有哪些钩子函数?还有哪些钩子函数参数
全局定义指令:在vue对象的directive方法里面有两个参数,一个是指令名称,另外一个是函数。组件内定义指令:directives
钩子函数:bind(绑定事件触发)、inserted(节点插入的时候触发)、update(组件内相关更新)
钩子函数参数:el、binding
v-for为什么使用key?
需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点。
作用主要是为了高效的更新虚拟DOM。
v-on绑定多个方法
点击
vue常用的修饰符
.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);
.capture:与事件冒泡的方向相反,事件捕获由外到内;
.self:只会触发自己范围内的事件,不包含子元素;
.once:只会触发一次。
vue-router的params和query的区别
用法:query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.name和this.$route.params.name。
url地址显示:query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示
注意点:query刷新不会丢失query里面的数据
params刷新 会 丢失 params里面的数据。