手把手实现简易版vue(二)组件类解析

news2025/1/11 19:51:34

1、构造器

  constructor(propsArgus = {}) {
    const {
      data = () => {},
      methods = {},
      watch = {},
      computed = {}, // 待实现
      props = {}, // 待实现
      created = () => {}, // created钩子函数
      mounted = () => {}, // mounted钩子函数
      destroyed = () => {} // destroyed钩子函数
    } = propsArgus
    this.$watch = watch // watch方法集合
    this.$watchers = {} // 收集器集合
    this.$methods = methods // 执行方法集合
    this.$data = data() || {} // 数据定义集合
    this.$computed = computed // 计算属性集合 待开发
    this.$props = props // 传递属性集合
    this.$created = created // created生命周期注入
    this.$mounted = mounted // mounted生命周期注入
    this.$destroyed = destroyed // destroyed生命周期注入
    bindProperties(this, this.$data)
    this.observe(this)
    bindProperties(this, this.$methods)
    this.$created() // created钩子执行 在dom挂载之前执行
  }

2、属性方法讲解及示例

1、data

写法是不是跟vue2一样啊,都是函数返回对象形式

      data: () => {
            return {
                article: {
                    title: '前标题',
                    text: {
                        word: '文字'
                    }
                },
                author: '前林大大哟'
            };
        }

2、methods

方法对象,跟vue2写法一致

        methods: {
            onButtonClick() {
                this.article.title = "标题"
                this.author = '林大大哟'
            },
            itemClick(item, type) {
                console.log(item, type);
            }
        }

3、watch

监听引用类型和基本类型,但写法都是一致的,和vue2不同的是并没有对对象内部单个值进行监听

    watch: {
            author(value) {
                console.log("watch 监听author:", value);
            },
            article(value){
                console.log("watch 监听 article.title:", value);
            }
        }

4、created, mounted, destroyed

这三个生命周期都和vue2用法一致,内部核心如下,这一点我倒是没有参考任何东西,根据自己想法写的~

3、核心源码讲解

数据响应式,是mvvm架构核心,vue2用的是Object.defineProperty,vue用的是Proxy,那我将这两者结合起来用,引用类型我用Proxy监测,基本类型我用Object.defineProperty监测

源码如下,都是遍历data中的数据,当发现是基本类型时候,用Object.defineProperty转换成响应式类型,而updateWatcher方法,就是被动触发页面结构中包含这数据的dom,然后让他进行更新(这部分vue源码中清除解释了,将同一数据的dom都放进收集器中,当此数据需要更新时,则通知收集器中的各个dom进行依赖更新),而watch对象中有监听这数据的话,就主动的去触发watch中的方法:data.$watch[key].call(data, val)。

  /**
   * 转换观测模式
   * @param {*} data 当前作用指针
   * @returns 
   */
  observe (data) {
    if (!data || getDataType(data) !== 'object') { // 按顺序写一般都不会进入这一步 用于初始化
      return
    }
    const arrayMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'reverse', 'sort']
    const keys = Object.keys(this.$data)
    for (let key of keys) {
      let value = data[key]
      if (getDataType(value) === 'object' ||
          getDataType(value) === 'array' ||
          getDataType(value) === 'null'
        ) {
        value = getDataType(value) === 'null' ? {} : value // Proxy不能传入不是对象的类型,所以在这里转一下
        data[key] = this.deepProxy(key, value)
      } else {
        Object.defineProperty(data, key, {
          configurable: false,
          enumerable: true,
          set(val) {
            value = val
            updateWatcher(this.$watchers[key], val) // 数据改变 watcher触发修改对应界面上的值
            if (data.$watch[key]) {
              data.$watch[key].call(data, val) // 主动触发watch对象的方法
            } 
          },
          get() {
            return value
          }
        })
      }
    }
  }

 当发现是引用类型时候,就用Proxy转换此引用类型,当然至于LveProxy类是啥样,这个我下篇再来写,核心其实就是Proxy和Reflect

  /**
   * 深度遍历并转换为自定义Proxy代理
   * @param {*} obj 
   * @returns
   */
  deepProxy(key, obj) {
    if (getDataType(obj) === 'array') { // 数组深度遍历
      obj.forEach((v, i) => {
        if (getDataType(obj) === 'object') {
          obj[i] = this.deepProxy(v)
        }
      })
    } else  { // 对象深度遍历
      if (Object.keys(obj).length === 0) return
      Object.keys(obj).forEach(v => {
        if (getDataType(obj[v]) === 'object') {
          obj[v] = this.deepProxy(key, obj[v])
        }
      });
    }
    const proxy = new LveProxy(this, obj).init(key) // proxy代理
    return proxy
  }

所以组件类的大体逻辑出来了,通过构造器将data,watch等这些传进去,然后mount到dom后,逻辑层和视图层就有了关联,逻辑层中数据以data中的为主,在dom中有关于data中的数据,都会被加入对应的收集器中(依赖收集),当data有数据更改,会将收集器中的依赖进行统一更新(依赖更新),至此MVVM框架的核心也就出来了,当然至于Proxy和模板如何转换的,那我将在下一篇博客中讲解~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1128207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL云数据库5.5导入到自建MySQL数据库5.7

有一个MySQL云数据库,版本比较老,是5.5. 需要在线下搭建一个测试环境,所以需要将数据还原到一个自建MySQL数据库内。 5.5已经很难找到了,所以安装了一个5.7. 云数据库设置的备份,使用的是全复制文件方法。 还原数据…

电源效率测试标准你知道多少?纳米软件带您了解

电源效率是衡量电源能源利用率和电源质量的重要指标,是电源模块测试的一个重要测试项目。对于电源效率各个国家都有自己的标准,以此来判断能量转换效率,促进提升能源利用率。 什么是电源效率标准? 电源效率标准是衡量电源能量转换率的指标&a…

Spark-Core

Spark简介 Spark-Core核心算子 Spark-Core 文章目录 一、RDD 编程1、RDD序列化1.2 Kryo序列化框架 2、RDD依赖关系2.1 查看血缘关系2.2 查看依赖关系2.3 窄依赖2.4 宽依赖2.5 Stage任务划分 3、RDD 持久化3.1 Cache缓存3.2 CheckPoint检查点3.3 缓存和检查点区别3.4 检查点存储…

天锐绿盾加密软件——企业数据透明加密、防泄露系统

天锐绿盾是一种企业级数据透明加密、防泄密系统,旨在保护企业的核心数据,防止数据泄露和恶意攻击。它采用内核级透明加密技术,可以在不影响员工正常工作的前提下,对需要保护的数据进行加密操作。 PC访问地址: https:/…

基于springboot基于会员制医疗预约服务管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot基于会员制医疗预约服务管理系统演示 摘要 会员制医疗预约服务管理信息系统是针对会员制医疗预约服务管理方面必不可少的一个部分。在会员制医疗预约服务管理的整个过程中,会员制医疗预约服务管理系统担负着最重要的角色。为满足如今日益复杂的管理需…

公司新品上市,如何做好新品发布会宣传

公司新品上市不仅展现了公司的生命力与活力,还代表了公司与时俱进的创新力,积极听取用户反馈的服务精神,而公司新品上市时都会举办新品发布会,今天媒介盒子就来和大家分享,公司如何做好新品发布会的宣传。 一、 撰写活…

2023年中国潜水电机行业现状及前景分析[图]

潜水电机是一种特殊设计的电动机,通常用于水下应用。它们被设计成能够在液体环境中工作,通常是在水中或其他液体中,而且能够在潜水的情况下继续正常运行。潜水电机通常具有防水性能和耐腐蚀性,以适应恶劣的水下环境。 潜水电机行…

Java实现连接SQL Server解决方案及代码

下面展示了连接SQL Server数据库的整个流程: 加载数据库驱动建立数据库连接执行SQL语句处理结果关闭连接 在连接之前,前提是确保数据库成功的下载,创建,配置好账号密码。 运行成功的代码: import java.sql.*;publi…

点集合的三角剖分

点集合的三角剖分是指如何将一些离散的点集合组合成不均匀的三角形网格,使得每个点成为三角网中三角面的顶点。这个算法的用处很多,一个典型的意义在于可以通过一堆离散点构建的TIN实现对整个构网区域的线性控制,比如用带高程的离散点构建的T…

Windows网络监视工具

对于任何规模的企业来说,网络管理在信息技术中都起着至关重要的作用。管理、监控和密切关注网络基础设施对任何组织都至关重要。在Windows网络中,桌面,服务器,虚拟服务器和虚拟机(如Hyper-V)在Windows操作系…

医院电力系统智能能效监控平台的应用

0引言 随着社会和科学技术的发展,配电系统的智能化已经成为一种发展趋势。医院建设电力智能监控平台,可对供电系统进行集中管理和调度、实时控制和数据采集,监控供电系统设备的运行情况,及时掌握和处理供电系统的各种事故、报警事…

Day07 Stream流递归Map集合Collections可变参数

Stream 也叫Stream流,是Jdk8开始新增的一套API (java.util.stream.*),可以用于操作集合或者数组的数据。 Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作 public class Demo1 {public stati…

【机器学习合集】标准化与池化合集 ->(个人学习记录笔记)

文章目录 标准化与池化1. 标准化/归一化1.1 归一化归一化的作用 1.2 标准化批标准化方法 Batch Normailzation标准化方法的对比自动学习标准化方法 2. 池化2.1 池化的作用2.2 常见的池化方法2.3 池化方法的差异2.4 池化的必要性 标准化与池化 1. 标准化/归一化 1.1 归一化 归…

django建站过程(3)定义模型与管理页

定义模型与管理页 定义模型[models.py]迁移模型向管理注册模型[admin.py]注册模型使用Admin.site.register(模型名)修改Django后台管理的名称定义管理列表页面应用名称修改管理列表添加查询功能 django shell交互式shell会话 认证和授权 定义模型[models.py] 模仿博客形式&…

kali查看wifi破解密码,实测有效

首先需要安装kali系统 这个系统是安装在虚拟机上的 还需要一个无线网卡(最好是kali系统免驱的 否则是无法识别的) 有着两个工具就可以pojie密码了 kali官网:Kali Linux | Penetration Testing and Ethical Hacking Linux Distribution 下载这里大家去比站上或者博客都可以…

某雀服务器崩溃,引发数据安全性讨论,应该选择私有化部署吗?

随着云计算技术的飞速发展,越来越多的企业和个人选择将数据存储于云端。然而,云服务的稳定性和数据安全性问题也成为了用户关注的焦点。昨天下午,语雀服务器崩溃事件引起了广泛关注。这一事件再次凸显了私有化的重要性。又一批人群开始考虑将…

12 结构型模式-桥接模式

1 桥接模式介绍 2 桥接模式原理

跟人一样,手机太烫也会“生病”!如何给太烫的手机降温

高温是你手机最大的敌人。现代智能手机在纤薄的外壳中装有强大的处理器和大容量电池,即使在正常工作条件下(看看你,Galaxy Note 7,也许还有iPhone 15),过热也会成为一个真正的问题。无论是充电、闲置还是执…

【每天学习一点新知识】安全设备IDS、IRS、IPS

IDS:入侵检测系统 对那些异常的、可能是入侵行为的数据进行检测和报警,告知使用者网络中的实时状况,并提供相应的解决、处理方法;是一种侧重于风险管理的安全产品。 IRS:入侵响应系统 深入网络数据内部,查…