一些vue你不太知道的知识(2) | 8月更文挑战

341 阅读5分钟

这是我参与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更高效了。