← 返回目录

第 4 卷

第 4 / 8 卷日期:

24lastTime = Date.now(); //执行后更新上次时间
25timer = null; //清空定时器
26}, interval - (now - lastTime)); //计算剩余延迟时间
27}
28 };

29 30// 取消节流:手动清除定时器

31throttled.cancel = function() {

32if (timer) clearTimeout(timer);
33timer = null;
34lastTime = 0;
35};

36 37return throttled;

38} 39

40// 测试示例 41function handleScroll() {

42console.log(`滚动触发时间:${new Date().toLocaleTimeString()}`);

43} 44

45// 节流函数(间隔1000ms执行一次)

46const throttledScroll = throttle(handleScroll, 1000);

47 48// 模拟频繁滚动(1秒内多次触发,仅1秒执行一次)

49window.addEventListener('scroll', throttledScroll);

50 51// 取消节流(不需要时移除)

52// window.removeEventListener('scroll', throttledScroll);

53// throttledScroll.cancel();

54

八、手写Vue响应式原理的代码实现(简易版)

核心原理(Vue2)

  1. 核心是“数据劫持+依赖收集”:通过Object.defineProperty()劫持数据的getter和setter方法
  2. getter:当数据被访问时,收集依赖(记录使用该数据的组件/函数)
  3. setter:当数据被修改时,触发依赖更新(通知所有使用该数据的组件/函数重新渲染)

实现代码

Code block

1// 1. 依赖管理类:收集依赖、触发更新 2class Dep {

3constructor() { 4this.subs = []; // 存储所有依赖(Watcher实例)

5} 6

7// 添加依赖 8addSub(sub) {

9//确保依赖是Watcher实例,且不重复添加
10if (sub && sub.update && !this.subs.includes(sub)) {
11this.subs.push(sub);
12}
13}

14 15// 触发所有依赖更新

16notify() { 17this.subs.forEach(sub => {

18sub.update(); // 调用Watcher的更新方法 19});

20} 21}

22 23// 2. 观察者类:关联数据和更新函数

24class Watcher { 25/**

26* @param {Object} vm -组件实例(此处简化为响应式数据对象)
27* @param {string} exp -数据属性名(如:'name'、'user.age')
28* @param {Function} cb -数据变化时的更新函数
29*/
30constructor(vm, exp, cb) {
31this.vm = vm;
32this.exp = exp;
33this.cb = cb;
34this.value = this.get(); //初始化时获取数据值,触发getter收集依赖
35}
37//获取数据值,触发getter以收集依赖
38get() {
39Dep.target = this; //标记当前Watcher为待收集的依赖
45//解析属性路径,获取数据值(支持嵌套属性,如'user.age')
46getVal(vm, exp) {
47return exp.split('.').reduce((data, key) => {
48return data[key];
49}, vm);
50}

51 52// 数据变化时执行的更新方法

53update() {

54const newValue = this.getVal(this.vm, this.exp);
55const oldValue = this.value;
56if (newValue !== oldValue) {
57this.value = newValue;
58this.cb(newValue, oldValue); //执行更新回调(如重新渲染视图)
59}
60}
61 }

62 63// 3. 响应式处理类:递归劫持对象属性

64class Observer { 65constructor(data) {

66this.observe(data); // 开始劫持数据 67}

68 69// 劫持数据主方法

70observe(data) { 71// 只处理对象/数组(基本类型无需劫持)

72if (!data || typeof data !== 'object') return;

73 74// 遍历对象所有属性,进行劫持

75Object.keys(data).forEach(key => {
76this.defineReactive(data, key, data[key]);
77});
78}

79 80// 定义响应式属性(核心:Object.defineProperty)

81defineReactive(obj, key, value) {

82const dep = new Dep(); //每个属性对应一个Dep实例
83this.observe(value); //递归劫持子属性(支持嵌套对象)
85Object.defineProperty(obj, key, {
86enumerable: true, //可枚举
全站分卷索引 · 8 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷