(1)computed 是计算一个新的属性,并将该属性挂载到 Vue 实例上,而 watch 是监听已经存在且已挂载到 Vue 实例上的数据,所以用 watch 同样可以监听 computed 计算属性的变化。
(2)computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值。而 watch 则是当数据发生变化便会调用执行函数。
(3)从使用场景上说,computed 适用一个数据被多个数据影响,而 watch 适用一个数据影响多个数据。
(4)methods在重新渲染的时候每次都会被重新的调用;
hash 路由模式的实现主要是基于下面几个特性:
URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 puted配合watch实现单个属性的深度监听
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
浏览器中的事件循环 eventLoop,分为同步执行栈和异步队列,首先会执行同步的任务,当同步任务执行完之后会从异步队列中取异步任务拿到同步执行栈中进行执行。
在取异步队列时,还会有一个区分,就是区分微任务和宏任务。
macrotask:宏任务,优先级低,先定义的先执行。包括:ajax,setTimeout,setInterval,事件绑定,postMessage,MessageChannel(用于消息通讯)因为微任务的优先级较高,所以会先将微任务的异步任务取出来进行执行,当微任务的任务都执行完毕之后,会将宏任务中的任务取出来执行。
我们这次来看一下上面的题,promise 中是同步任务,promise 的 .then 中是异步任务,并且是微任务。使用 setTimeout 是宏任务,即使是延时为 0,也是宏任务。
加到异步队列中微任务池中,再执行同步任务console.log(2),当同步任务都执行完之后,去微任务中的任务,执行console.log(3),微任务执行完之后取宏任务,执行console.log(4)。所以顺序就是:1,2,3,4。
将这道面试题进行一些改造:
64.vue中是否可以监控到数组下标的变化
无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。所以vue才设置了7个变异数组(push、pop、shift、unshift、splice、sort、reverse)的 hack 方法来解决问题。
65.Vue项目中实现用户登录及token验证
在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下:
1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码
2、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token
4、前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面
5、每次调后端接口,都要在请求头中加token
6、后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401
7、如果前端拿到状态码为401,就清除token信息并跳转到登录页面
一、调登录接口成功,在回调函数中将token存储到localStorage和vuex中
三、请求头加token
// 添加请求拦截器,在请求头中加token
四、如果前端拿到状态码为401,就清除token信息并跳转到登录页面
67.请说出vue.cli项目中src目录每个文件夹和文件的用法assets文件夹是放静态资源;
router是定义路由相关的配置;
app.vue是一个应用主组件;
69.组件中写name选项有什么作用项目使用keep-alive时,可搭配组件的name进行缓存过滤。
DOM做递归组件时需要调用自身name
vue-devtools调试工具里显示的组件名称是由vue中组件name决定的
//对响应数据做点什么
//对错误响应做点什么
//在发送请求之前做些什么
//对请求错误做些什么
组件支持用户在具有路由功能的应用中 (点击) 导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 标签,可以通过配置 tag 属性生成别的标签.。
通过router-link进行跳转不会跳转到新的页面,也不会重新渲染,它会选择路由所指的组件进行渲染,避免了重复渲染的“无用功”。
总结:对比,router-link组件避免了不必要的重渲染,它只更新变化的部分从而减少DOM性能消耗
你知道vue中key的作用和工作原理吗?说说你对它的理解。开课吧web开发团队精心录制课程,key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
模型:组件中的data属性
视图:组件中的template
一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。
二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。
在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信。
使用MVC的目的就是将M和V的代码分离。‘MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。
MVVM其实是MVC的改进版,两者没有很大的区别,只是MVVM实现了双向数据绑定,MVC是单向通信的。
mvc是比较早的偏后端开发的模式,而且各做各的事,互不干扰,想做双向绑定就只能dom模拟,但是mvvm是实现了响应式的双向数据绑定的,而且还是基于mvc模式演变出来的,你能做的我也能做,你没实现的我却能实现,所以mvvm模式更受前端市场的欢迎
jquery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:$("lable").val(),
它还是依赖DOM元素的值。
Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM。
1.父组件向子组件通信:props。在子组件中定义props属性
2.子组件向父组件通信:emit。在子组件中使用emit发射事件,然后在父组件中定义方法实现这个事件
3.$emit和$on也可以实现任何组件之间的通信。包括父子、兄弟、跨级。不过它得有个中间桥梁来传输数据。这个桥梁一般是个空对象 new Vue()
ref、children可以实现父组件直接获取子组件的实例,通过实例可以直接使用子组件中的方法活或者属性。两者的不同点:children 是个按子组件位置存放子组件实例,ref 可以通过定义属性直接去获取指定的实例
parent 相反是提供给子组件访问父组件实例的方法
(1)vuex是什么?怎么使用?哪种功能场景使用它?
vue框架中状态管理。在main.js引入store,注入。新建一个目录store,…… export 。场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
(2)vuex有哪几种属性?
A、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data
B、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
A、getters 可以对State进行计算操作,它就是Store的计算属性
B、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
C、 如果一个状态只在一个组件内使用,是可以不用getters
两者都是用来对元素做显示隐藏的
v-if 是直接通过销毁和重建dom来实现的。
v-show 是通过元素的css属性来通知显示和隐藏的
性能上来讲的话 v-show或更高效。如果是要频繁切换的话建议使用 v-show
7、vue 如何让css只在自己的文件上生效
<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
把需要缓存的组件包裹在这个组件中。主要用于保留组件状态或避免重新渲染。
9、脚手架自定义组件的过程
第四步:在template视图view中使用,
10、路由组件的懒加载
computed 通过计算结果得到的属性,其本身就是个属性,只是这个属性是经过计算得到的,用法和属性的用法是一模一样的,只是定义的位置不同。
watch 做数据监听,只要监听的属性发生变化,定义的方法就会执行
计算属性具有缓存机制。如果某个值重复的调用而且没有改变,methods的话会重复的执行使用,计算属性是会把缓存中的数据直接取出来使用。只有计算属性中依赖的属性发生变化的时候,值才会重新计算
13、v-if的使用注意事项
2、为同一类的组件做显示隐藏的时候,最好加上 key 属性来做标识,被标识的组件就会重新渲染了
14、vue 生命周期函数相关面试题
组件实例从创建到销毁的过程,叫做生命周期。开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期
2、vue生命周期的作用是什么
生命周期中有多个函数(钩子函数),这些钩子函数可以让我们在特定的时刻执行特殊的事件,形成更好的逻辑。
3、第一次页面加载会触发的函数
4、DOM 渲染在 哪个周期中就已经完成
5、生命周期函数和使用场景
完成了 data 数据的初始化,el没有 |
vue实例的$el和data都初始化了,但还是虚拟的dom节点,就是说还没有挂载 |
配合路由钩子使用,可以在这里发送异步事件请求 |
数据更新时,做一些处理(此处也可以用watch进行观测) |
组件销毁时触发,vue实例解除了事件监听以及和dom的绑定(无响应了),但DOM节点依旧存在 |
15、同级元素为什么要使用key
同级相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,高效更新虚拟dom,否则 Vue 为了效率只会替换相同标签内部的内容。
16、后期添加属性的方法
17、vue响应式原理
4、Dep 发布订阅者,添加观察者者以及在数据发生改变的时候通知观察者
3、Watcher 观察者,对数据进行观察以及保存数据修改需要触发的回调
2、Compiler 模板编译器,对HTML模板进行编译,提取其中的变量并转化为数据。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
对模板进行编译的时候,收集跟变量有关的数据。
在使用getter方法时,总会通知wather实例对view层渲染页面。.
同样的,在使用setter方法时,总会在变更值的同时,通知wather实例对view层进行更新。
vue是结合数据劫持和发布订阅者模式来实现双向数据绑定的,当要读取数据的时候会自动触发方法,并且会被赋值
使用了ES6中的proxy对数据进行代理。
对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改。
而使用返回对象的函数,由于每次返回的都是一个新对(Object的实例),引用地址不同,则不会出现这个问题。
19、vue路由的几种模式
hash模式下路径有个 # 号
20、v-if和v-for一起使用的弊端以及解决办法
由于v-for的优先级比v-if高,所以导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
解决方案:在v-for的外层或内层包裹一个元素来使用v-if
21、vue父组件和子组件生命周期的顺序
22、vue中事件修饰符有哪些
.stop: 阻止事件冒泡
.once: 事件只执行一次
.self:将事件绑定在自身身上,相当于阻止事件冒泡
23、vue中如何解决页面不重新渲染问题
this(Vue).$forceUpdate() 这个方法可以迫使Vue 实例重新渲染。它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
24、vue-router有哪些导航钩子(导航守卫)?
全局前置守卫:可以一次定义多个守卫,当一个导航触发时,全局前置守卫按照创建顺序执行。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
全局解析守卫:router.beforeResolve
注册一个全局解析守卫。在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
全局后置守卫:这个守卫没有 next 方法
路由独享守卫:beforeEnter直接定义在路由里面去
路由组件内直接定义以下路由导航守卫:(直接定义在组件内部,定义在跟data同级)
不过,你可以通过传一个回调给 next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
完整的导航调用顺序:
动态路由使用 path 传参。动态路由path参数变化的时候,组件不会重新渲染而是会复用,所以生命周期函数不会再次执行,不过可以使用 watch 进行监听
参数不会显示在路径上
浏览器强制刷新参数会被清空
参数会显示在路径上,刷新不会被清空
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。