常见vue选题

把你了解的vue响应式的原理阐述一下?

vue中有三个核心类

首先了解vue中的三个核心类

  1. Observer: 用来给对象的属性添加getter和setter,用来***依赖收集***和***派发更新***。
  2. Dep:用来收集当前响应式对象的依赖关系,每一个响应式对象都有一个dep实例,dep.subs = watcher[].是一个watcher数组。当数据发生变更的时候,会通知dep.notify()通知各个watcher。
  3. Watcher:观察者对象, render watcher 渲染,computed watcher 计算, user watcher监听
  • 依赖收集
  1. initState,初始化vue组件实例的时候,对computed属性初始化时,会触发computed watcher 依赖收集。
  2. initState,对监听属性初始化的时候,触发的user watcher依赖收集。
  3. render,渲染的过程,触发render watcher依赖收集。
  • 派发更新

Object.defineProperty

  1. 组件中对相应的数据进行了修改,或触发setter逻辑。
  2. dep.notify()
  3. 遍历所有subs,调用每一个watcher的update方法(更新视图)。

总结原理:

当创建vue实例的时候,vue先遍历data里面的属性。data初始化属性。Object.definProperty.为属性添加getter和setter对数据的读取进行劫持。

getter:依赖收集
setter:派发更新

每一个组件实例都会有对应的watcher实例。

计算属性的实现原理

data 是属性

computed : {  //  都是一个个的方法,重新调用求值
	test() {
	
	{
}

computed watcher,计算属性的监听器。

computed watcher 持有一个dep实例,通过dirty属性编辑属性是否需要重新求值。

当computed的依赖值改变后,就会通知订阅的wathcer进行更新,对于computed watcher 会将 dirty 属性设置 true,并且进行计算属性方法的调用。

  1. computed 所谓的缓存指的是什么?

计算属性是基于他的响应式依赖进行缓存的,只有雨来大声改变时才会重新求值。

  1. 实际应用中怎么用的?真实项目中使用过吗?那computed缓存存在的意义是什么?或者你经常在什么时候使用?

比如计算属性的方发内部操作非常的耗时,遍历一个极大的数组,计算一次需要一秒或者更多。

const largeArray = [
	{ ... },
	{ ... },
	{ ... }
] // 10w 条

data: {
	id: 1
}

computed: {
	currentItem: function() {
		return largeArray.find(item => item.id === this.id);
	},
	stringId: function () {
		return String(this.id);
	}
}
  1. 一下情况,computed 可以监听到数据的变化吗?(比如 : 格式化转化,有缓存)

watcher 没有缓存,变化之后接下来做什么动作,调用什么函数
computed 简单的转换操作,有缓存

template

    {{ storageMsg }}

computed: {
    storageMsg: function(){
        return sessionStorage.getItem('xxx'); // 获取不到数据,没有响应的更新上去就不会计算
    },
   time: function(){
        return Date.now(); // 也不可以,没有响应的更新上去就不会计算
   }
}

created() {
    sessionStorage.setItem('xxx', 1111)
}

onClick() {
   sessionStorage.setItem('xxx', Math.random())
}

vue.nextTick()

Vue.nextTick(() => {

})

await Vue.nextTick();

vue 是异步执行 dom 更新的,一旦观察到数据的变化,不会立即执行,开启异步队列,把同一个event loop 中观察数据变化的watcher推送到这个队列中。去除掉重复的事件操作。

在下一次事件循环时,vue清空异步队列,进行dom更新。

怎么样开启异步队列?

Promise.then > MutationObserver -> setImmediate > setTimeout …

vm.someData = ’ new value ’ dom 并不会立即更新,而是在异步队列被清空时才会更新dom。

里面的函数在下一轮事件队列中执行

红任务 -> 微任务队列 -> ui render(只有浏览器把元素渲染到页面,之前已经拿到新的dom,只是没有展现到浏览器上)

什么时候用到nextTick?

  1. 在数据变化后,要执行某个操作,而这个依赖因数据改变而改变的dom,这个操作就应该被放到vue.nextTick回调中。
<template>
   <div v-if="loaded" ref="test"></div>
</template>

async showDiv() {
    this.loaded = true;
    // this.$refs.test // 同步获取不到test
   
    await Vue.nextTick(); // 这个操作之后,才可以获取到test
    this.$refs.test.xxx();
}

手写一个vue,实现响应式的更新。

上一篇:Vue中$nextTick()用法


下一篇:uniapp 刷新video和live-player组件,实现刷新效果