前端面试题——Vue高频问题
1.Vue的生命周期
Vue的生命周期主要分为几个简单,数据初始化,dom挂载,数据更新,组件卸载,在一个就是开启了组件缓存的时候,会有组件启用和组件停用阶段,每个阶段都去前后两个钩子除了缓存的那俩
数据初始化阶段
beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created:实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
dom挂载阶段
beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted:el 被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
数据跟新阶段
beforeUpdate:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉 updated:
缓存启用的时候会有下面两个钩子
activated:keep-alive 组件激活时调用。
deactivated:keep-alive 组件停用时调用。
组件卸载的时候:
beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
vue.png
2.Vue实现数据双向绑定的原理
vue实现数据双向绑定主要是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。具体话其实就是通过Obeject.defineProperty() 中的setter和getter来监听属性变动实现Observer进行数据的监听然后就是通知订阅者,那么订阅者其实就是简单的一个数组,这个数组中的内容就是我门使用了的一个数据的集合,使用了的数据可以通过getter得到,其实就是在调用的时候给数组里面添加一个订阅者这样就是实现了一个Watcher(需要监听的数据的集合),然后在实现一个Compile其作用就是解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图,其实vue的数据双向绑定就是MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
3.Vue路由的实现原理
在vue中路由主要有 hash与History interface两种方式实现前端路由,单页路由的特点就是采用前端路由系统,通过改变URL,在不重新请求页面的情况下,更新页面视图。目前在浏览器环境中这一功能的实现主要有两种方式:hash和History interface,这两种模式的实现分别是
先说hash,在浏览器的url中hash(“#”)符号的本来作用是加在URL中指示网页中的位置:#符号本身以及它后面的字符称之为hash,可通过window.location.hash属性读取。它具几个特点就是:hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新加载页面,并且可以为hash的改变添加hashchange监听事件,在一个就是每一次改变hash(window.location.hash),都会在浏览器的访问历史中增加一个记录,我就可以通过他的这几个特点实现一个hash模式的单页路由,通过对location.hash的修改实现push方法(跳转页面),通过对location.href的修改实现replace()方法,通过对hashchange事件的监听实现页面跳转后的数据更新
而History模式则是完全采用了h5的新特性,从HTML5开始,History interface提供了两个新的方法:pushState(), replaceState()使得我们可以对浏览器历史记录栈进行修改,以及popState事件可以监听到状态的变更
不过history模式有一个问题就是
对于单页应用来讲,理想的使用场景是仅在进入应用时加载index.html,后续在的网络操作通过Ajax完成,不会根据URL重新请求页面,但是如果用户直接在地址栏中输入并回车,浏览器重启重新加载的时候history模式则会将URL修改得就和正常请求后端的URL一样,在此情况下重新向后端发送请求,如后端没有配置对应 的路由处理,则会返回404错误。这种问题的解决,一般情况下我们都是在后端进行配置,将所有的路由请求都指向index.html文件
4.Vue组建的通讯
1.父组件传子组件
单项数据流props
使用refs访问子组件
使用$parent访问父组件
使用$children访问子组件
使用$root访问当前组件树的根 Vue 实例
在template元素使用scope 可以访问到子组件中slot元素的属性值 要13k
2.子组件传递数据给父组件:
子组件通过事件给父组件传数据,子组件通过$emit(eventName)触发事件,父组件通过$on监听事件
3.兄弟组件间通信
①用事件发布订阅 var bus=new vue();bus.$emit("id-selected",1);bus.$on("id-selected",function(id){})
②用vuex来实现
5.VueX是做什么的
Vuex 是适用于 Vue.js 应用的状态管理库,为应用中的所有组件提供集中式的状态存储与操作,保证了所有状态以可预测的方式进行修改;
state: state 定义了应用状态的数据结构,同样可以在这里设置默认的初始状态。
actions:Actions 即是定义提交触发更改信息的描述,常见的例子有从服务端获取数据,在数据获取完成后会调用store.commit()来调用更改 Store 中的状态。可以在组件中使用dispatch来发出 Actions。
mutations: 调用 mutations 是唯一允许更新应用状态的地方。
getters: Getters 允许组件从 Store 中获取数据,譬如我们可以从 Store 中的 projectList 中筛选出已完成的项目列表
modules: modules 对象允许将单一的 Store 拆分为多个 Store 的同时保存在单一的状态树中。随着应用复杂度的增加,这种拆分能够更好地组织代码
但是vuex也有缺点就是,vuex中保存的数据是和网页的生命周期同步的,当执行页面刷新的时候vuex中所有数据都会消失复位到初始状态,所以不太适合做有分享页面的数据交互(在这种项目中vuex只适合数据的集中管理,不适合数据的存储,这种情况一般是使用路由传递参数会好一些),适合后台管理系统多一些,后台管理系统一般都是公司内部使用;
6.Vue的路由如何传参?
发表评论 (审核通过后显示评论):