传送门 → vue 常见面试题 (二)
1、Vue中key值的作用?
vue中列表循环需加:key="唯一标识"
。唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用 主要是为了高效的更新虚拟DOM 。
key可以管理可复用的元素,减少不必要的元素的重新渲染,也要让必要的元素能够重新渲染。
有相同父元素的子元素必须有独特的key。重复的key会造成渲染错误。
2、Vue单页面应用及其优缺点?
概念:
单页面应用(SPA)
通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。
多页面(MPA)
就是指一个应用中有多个页面,页面跳转时是整页刷新。
单页面优缺点:
优点:
1、用户体验好,快,内容的改变不需要重新加载整个页面,对服务器压力较小。
2、前后端分离,比如vue项目
3、完全的前端组件化,前端开发不再以页面为单位,更多地采用组件化的思想,代码结构和组织方式更加规范化,便于修改和调整;
缺点:
1、首次加载页面的时候需要加载大量的静态资源,这个加载时间相对比较长。
2、不利于 SEO优化,单页页面,数据在前端渲染,就意味着没有 SEO。
3、页面导航不可用,如果一定要导航需要自行实现前进、后退。
3、对于v-show和v-if指令的理解?
相同点:
v-if与v-show均能控制元素的显示和隐藏
不同点:
1.本质: v-show本质就是通过设置css中的display属性来控制
元素的显示与隐藏,v-if是在DOM树上进行动态的添加、删除元素
2. 编译区别 :v-show是对css样式的修改。v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件。
3. 编译条件: v-show都会编译,初始值为false,只是将display设为none,但它也编译了。v-if是惰性的,当初始值为false,就不会编译了。
4. 性能:v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。
总结:如果要频繁切换某节点时,使用v-show(无论true或者false初始都会进行渲染,此后通过css来控制显示隐藏,因此切换开销比较小,初始开销较大),如果不需要频繁切换某节点时,使用v-if(因为懒加载,初始为false时,不会渲染,但是因为它是通过添加和删除dom元素来控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)
4、Vue组件传参
传送门,我自己写的一篇博客 → 组件传参
- 使用props和$emit
- 使用ref
- 使用eventBus
- 使用状态管理Vuex
5、Vuex是什么?说一下你对vuex的理解?
这是一篇关于 Vuex 的一篇博文,推荐大家去看一下。
Vuex是vue的状态管理模式。
变状态的方式是提交mutations。
state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
类似vue的计算属性,主要用来过滤一些数据。
action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
modules
项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
6、Vue的生命周期
beforeCreate(创建前) 在数据观测和初始化事件还未开始
created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来。 此时是最早可进行发送ajax请求的生命周期,也可进行服务端渲染
beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
7、Vue实现数据双向绑定的原理
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式。
Object.defineProperty()
来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
8、Vue的路由实现:hash模式 和 history模式
关于vue的路由,我写过一篇博客,详细的解释了底层的原理 传送门 → vue-router 底层原理
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致
9、vue路由的钩子函数
首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。
beforeEach主要有3个参数to,from,next:
to:route即将进入的目标路由对象,
from:route当前导航正要离开的路由
next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。
10、对keep-alive 的了解?
这是一篇关于 keep-alive 的博客,可以去看一下
keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。
参数解释
include
- 字符串或正则表达式,只有名称匹配的组件会被缓存
exclude
- 字符串或正则表达式,任何名称匹配的组件都不会被缓存
include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用v-bind 。
11、Vue中引入组件的步骤?
1.采用ES6的import … from …语法
或
CommonJS的require()方法引入组件
2.对组件进行注册,代码如下
注册
Vue.component('my-component',
{ template: '<div>A custom component!</div>'})
3.使用组件
<my-component></my-component>
12、在Vue中使用插件的步骤
1.
import Vue from 'vue'
2.
import 组件 from '组件包名'
3.
Vue.use(组件)
13、vue watch的高级用法–监听对象的属性变化
1.监听对象需要深度监听 ,如下代码可以监听整个msg对象的变化
watch: {
msg: {
handler(newValue, oldValue) {
console.log(newValue)
},
deep: true
}
}
2.监听对象里面某个属性的变化,通过computed做中间层实现
computed: {
channel() {
return this.msg.channel
}
},
watch:{
channel(newValue, oldValue) {
console.log('new: %s, old: %s', newval, oldVal)
//这里面可以执行一旦监听的值发生变化你想做的操作
}
}
14、active-class是哪个组件的属性?
active-class是vue-router模块的router-link
组件中的属性,用来做选中样式的切换;
使用方法:
<router-link to="/" active-class="active">首页</router-link>
需要注意的是,active-class选择样式时根据路由中的路径
去匹配,然后显示,例如在my页面中,路由为 ,那么to="/”和to="/my"都可以匹配到,所有都会激活选中样式,要解决问题方式,通过加入一个exact属性
<router-link to="/" active-class="active" exact>首页</router-link>