• 从零到一手写迷你版Vue


    Vue响应式设计思路

    Vue响应式主要包含:

    • 数据响应式
    • 监听数据变化,并在视图中更新
    • Vue2使用Object.defineProperty实现数据劫持
    • Vu3使用Proxy实现数据劫持
    • 模板引擎
    • 提供描述视图的模板语法
    • 插值表达式{ {}}
    • 指令 v-bind, v-on, v-model, v-for,v-if
    • 渲染
    • 将模板转换为html
    • 解析模板,生成vdom,把vdom渲染为普通dom

    数据响应式原理

    在这里插入图片描述

    数据变化时能自动更新视图,就是数据响应式
    Vue2使用Object.defineProperty实现数据变化的检测

    原理解析
    • new Vue()⾸先执⾏初始化,对data执⾏响应化处理,这个过程发⽣在Observer
    • 同时对模板执⾏编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发⽣在 Compile
    • 同时定义⼀个更新函数和Watcher实例,将来对应数据变化时,Watcher会调⽤更新函数
    • 由于data的某个key在⼀个视图中可能出现多次,所以每个key都需要⼀个管家Dep来管理多个 Watcher
    • 将来data中数据⼀旦发⽣变化,会⾸先找到对应的Dep,通知所有Watcher执⾏更新函数

    在这里插入图片描述

    一些关键类说明

    CVue:自定义Vue类 Observer:执⾏数据响应化(分辨数据是对象还是数组) Compile:编译模板,初始化视图,收集依赖(更新函数、 watcher创建) Watcher:执⾏更新函数(更新dom) Dep:管理多个Watcher实例,批量更新

    参考 前端手写面试题详细解答

    涉及关键方法说明

    observe: 遍历vm.data的所有属性,对其所有属性做响应式,会做简易判断,创建Observer实例进行真正响应式处理

    html页面
    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>cvuetitle>
      <script src="./cvue.js">script>
    head>
    <body>
      <div id="app">
        <p>{
      { count }}p>
      div>
    
      <script>
        const app = new CVue({
               el: '#app',      data: {
                 count: 0
          }    })    setInterval(() => {
               app.count +=1
        }, 1000);  script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    CVue

    • 创建基本CVue构造函数:
    • 执⾏初始化,对data执⾏响应化处理
    // 自定义Vue类
    class CVue {
       
      constructor(options) {
       
        this.$options = options
        this.$data = options.data
    
        // 响应化处理
        observe(this.$data)
      }
    }
    
    // 数据响应式, 修改对象的getter,setter
    function defineReactive(obj, key, val) {
       
      // 递归处理,处理val是嵌套对象情况
      observe(val)
      Object.defineProperty(obj, key, {
       
        get() {
       
          return val
        },
        set(newVal) {
       
          if(val !== newVal) {
       
            console.log(`set ${
         key}:${
         newVal}, old is ${
         val}`)
    
            val = newVal
            // 继续进行响应式处理,处理newVal是对象情况
            observe(val)
          }
        }
      })
    }
    
    // 遍历obj,对其所有属性做响应式
    function observe(obj) {
       
      // 只处理对象类型的
      if(typeof obj !== 'object' || obj == null) {
       
        return
      }
      // 实例化Observe实例
      new Observe(obj)
    }
    
    // 根据传入value的类型做相应的响应式处理
    class Observe {
       
      constructor(obj) {
       
        if(Array.isArray(obj
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
  • 相关阅读:
    Jsp基础了解(二)
    如何在不恢复出厂设置的情况下解锁 Android 手机密码?
    项目沟通管理案例题
    小白优化Oracle的利器”sqltrpt.sql”脚本
    在命令窗口便捷快速复制输出结果到剪贴板
    世界前沿技术发展报告2023《世界信息技术发展报告》(四)电子信息技术
    零时科技 || Victor the Fortune攻击事件分析
    K8s安装部署-----二进制安装部署
    高可用架构实现流量治理的策略
    说说mvc和mvvm的区别和联系
  • 原文地址:https://blog.csdn.net/helloworld1024fd/article/details/127682481