这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
一、vue组件data为什么必须是个函数而vue根实例没有这个限制?
1、函数每次执行都会返回全新的data对象的实例
2、vue组件可能会存在多个实例,如果使用对象形式定义data就会导致很多组件公用同一个data,当data中数据改变就会影响其他组件的展示。
3、原理是vue中data使用函数的方式,在源码initData中作为工厂函数返回全新data对象,可以避免第二条发生在data数据更新影响其他组件的问题。
二、vue中的key的作用和原理是什么?
//html:
<div v-for="item in nums" :key="item">{{item}}</div>
//js:
const app = new Vue({
el:'demo',
data: {
nums: ['a', 'b', 'c', 'd', 'e']
},
mounted() {
setTimeout(()=> {
this.nums.splice(2,0,'f');
},1000);
}
});
在上面这段代码中,需要在初始化的时候在数组中加入一个f的字段,如果可以key的话会产生下面的问题
不使用key
如果你在执行的时候打断点调试,就可以在源码中发现src\core\vdom\patch.js 中updateChildren()方法就是以上的图
1、key的作用主要是为了更快速的更新DOM,原理就是vue源码中的patch过程中key可以准确的判断两个节点是否是同一个,从而避免更新不同元素,减少DOM操作,提高性能
2、不设置key会有warn提醒的bug
3、vue在使用相同元素的DOM过渡切换时,也会用到key,就是为了让vue可以区分他们,否则vue只能替换内部属性,而不会触发过度效果
三、vue-router中的导航钩子有哪些?
1、全局导航钩子
beforeEach(to,from,next)路由改变前触发该方法,可以在用户验证权限的时候使用
to:将要跳转的路由对象
from:当前页面的路由对象
next:路由控制参数,判断一些权限,然后控制:
next()路由正常执行跳转
如果next(false)就会取消导航,
next('/index')当前路由中断,进行一个新的index页面的路由跳转,
next(error)如果一个error实例,则导航会被终止并且该错误会被传递给router.onError(),走到afterEach(to,from)路由改变后的钩子
beforeEach((to,from,next) => {
if(to.fullPath != '/login') {//如果不是登录页面
if(!localStorage.token) {//如果没有token
next('/login');//就进入login页面登录
}else {
next();//正常跳转
}
}else {
next();//正常跳转
}
})
2、组件内的导航钩子
1)beforeRouteEnter(to,from,next);和上面方法类似,但是此实例还没被创建,所以不能获取实例this
2)beforeRouteUpdate(to,from,next);当前路由不改变,但是在组件被复用的时候触发,可以获取实例this
3)beforeRouteLeave(to,from,next);当导航离开组件时触发,可以获取实例this
3、使用watch监听路由$route的变化
四、nextTick的原理
大家都知道,它可以在DOM更新后执行一个回调方法 ,其实内部使用了mutationObserver监听DOM的变化,mutationObserver是H5新增的属性,用于监听DOM修改事件,可以监听到节点的属性,文本等。
//mutationObserver的基本用法:
var observer = new MutationObserver(function() {
console.log('dom修改了');
});
var content = document.querySelector('content');
observer.observer(content);
可以查看源码/src/core/util/env.js,里面用到了事件循环机制,因为可以通过点击,页面渲染,脚本执行,网络请求等方式触发DOM的更新,为了协调这些事件,浏览器使用事件循环机制。
事件循环机制Event Loop
会维护一个或多个队列,以上触发DOM的方法就会在队列中加入任务,有一个持续执行的线程来执行这些任务,执行完一个就移除一个。
所以nextTick里要执行的代码就放到了队列的末尾执行,从而达到DOM更新后执行的效果,也可也理解使用setTimeout延时的时间恰到好处。但是vue的数据响应过程是:数据修改->通知watcher->更新dom。而数据修改我们不知道什么时候会发生,如果在重绘之前就会发生多次渲染,造成性能浪费,更多的还需要去了解event loop的另一个概念:microtask,这里就不多说了,类似于微任务。
总结就是:
1、vue使用异步队列的方法控制DOM的更新和nextTick回调后执行
2、microtask有优先的特性,可以确保队列中的微任务在一次事件循环机制前被执行完
五、vue的设计原则
1、渐进式的javaScript框架
vue被设计为自下而上逐层应用,vue核心只关注视图层,易上手还可以和第三方库整合,可以完全的实现复杂的单页应用提供驱动。
2、易用
vue提供数据响应式,声明式模板语法和基于配置的组件系统等核心,所以我们只需要会js,html,css就可以开发vue
3、灵活
如果一个应用比较小,就可以只需要vue核心功能开发,如果应用比较大,就可以加入路由管理,vuex等方便灵活开发
4、高效
内部更新虚拟dom的快速和使用了diff算法提高了大量的性能,vue3还使用proxy对数据响应式改进和编译器对于静态内容的编译都让vue更高效了。