Vue2源码分析-day1

news2024/11/25 5:01:59

初始化数据

vue中最核心的我们都知道那就是响应式数据,数据的变化视图自动更新。那么我们来new一个我们自己的vue

index.html文件下加入如下代码,这也是vue最常见的基本结构。data已经有了下面我们来获取data的数据

 <script src="./vue.js"></script>
 <script>
    const vm=new MVue({
         data(){
             return{
                 name:"zhangsan",
                 age:"16"
             }
         }
    })
 </script>

首先我们在src/main.js文件下加入如下代码

// 创建MVue构造函数
function MVue(options) {      // options就是我们接受到用户的选项,选项式api
    
}

// 将构造函数导出
export default MVue

为了更能的扩展功能和方便维护,我们需要一个专门做初始化的方法。所以我们在src下创建init.js文件加入如下代码

export function init(MVue){
    // 给MVue原型对象上挂载_init()方法
    MVue.prototype._init = function(options){

    }
}

main.js文件下如果这个方法,并且调用

import { init } from "./init"

// 创建MVue构造函数
function MVue(options) {      // options就是我们接受到用户的选项,选项式api
    // 当vue被new的时候调用_init()方法
    this._init(options)
}

init(MVue)

// 将构造函数导出
export default MVue

下面我们就可以写我们的初始化方法了,init.js文件下加入如下代码。可能你会好奇这个init_state()方法是那里的。由于用户选项有很多比如data,watch,computed…所以我们最好创建一个文件统一管理。在src文件下创建state.js文件

import { init_state } from "./state"

export function init(MVue){
    // 给MVue原型对象上挂载_init()方法
    MVue.prototype._init = function(options){

        // 在用户选项挂载到实例上
        const vm=this
        vm.$options=options

        // 初始化状态
        init_state(vm)
    }
}

state.js文件下加入如下代码

export function init_state(vm){
    // 获取实例上挂载的选项
    const opts=vm.$options;

    // 选项上如果存在data初始化data
    if(opts.data){
        init_data(vm);
    }
}
function init_data(vm){
    let data=vm.$options.data;

    // 判断data是对象还是函数并且重新赋值
    data=typeof data==='function'?data.call(vm):data;

    console.log(data);
}

到这里,输入打包命令打开index.html如果在游览器下看到如下图所示,我们就成功获取到了data里面的数据

pnpm run build

在这里插入图片描述


实现对象的响应式原理

下面我们首先来实现只有一层对象的数据劫持。state.js文件下加入如下代码

import { observe } from "./observe/index";

export function init_state(vm){
    // 获取实例上挂载的选项
    const opts=vm.$options;

    // 选项上如果存在data初始化data
    if(opts.data){
        init_data(vm);
    }
}
function init_data(vm){
    let data=vm.$options.data;

    // 判断data是对象还是函数并且重新赋值
    data=typeof data==='function'?data.call(vm):data;

    // 将data劫持重新定义data
    observe(data)
}

src文件下创建observe/index.js文件并且加入如下代码

class Observer {
    constructor(data) {
        /* 
            这里注意,Object.defineProperty只能劫持已经存在的属性,新增或删除的无法劫持
            这也是为什么vue2中新增了,$set和$delete方法这类方法的原因
        */
        this.walk(data)
    }
    walk(data) {
        // 循环对象keys依次劫持,重新定义属性
        Object.keys(data).forEach(key => {
            define_reactive(data, key, data[key])
        })
        
        // 这里重新定义data后我们打印看下data是否都加入了get和set方法
        console.log(data);
    }

}

// 这里会存在一个闭包,get和set方法存放了函数外部的变量value
export function define_reactive(data, key, value) {
    Object.defineProperty(data, key, {
        get() {
            return value
        },
        set(newValue){
            if(value!=newValue){
                value=newValue
            }
        }
    })
}


export function observe(data) {

    // 对对象劫持
    if (typeof data !== 'object' || data === null) {
        return;
    }

    // 如果一个对象被劫持过就不需要再次劫持,我们可以通过一个观察类判断是否被劫持过
    return new Observer(data)
}

如果你的游览器打印了如下图所示,那么恭喜你只有一层对象的data你重新定义完成了

在这里插入图片描述
说起data,vue2中一直有个属性_data属性。这上面挂载了我们所有在data中定义的属性。下面我们来实现它

state.js文件下修改如下代码。没错就是这么简单要加入vm._data=data这行代码就完成了。由于这是引用值。所有对data的修改也会影响到_data

function init_data(vm){
    let data=vm.$options.data;

    // 判断data是对象还是函数并且重新赋值
    data=typeof data==='function'?data.call(vm):data;

    // 实例上挂载_data
    vm._data=data

    // 将data劫持重新定义data
    observe(data)
}

下面我们在index.html下打印vm看看是否有我们的_data属性

在这里插入图片描述

到这里,其实我们的_data属性并不完美,你通过vm获取属性的时候发现每次都要加上_data,
vm._data.name。但是vue2中并不是这样的而是直接vm.name就可以获取并且修改。下面我们来解决这个问题

state.js文件下加入如下代码。我们将将vm._data代理给vm就可以解决这个问题

function proxy(vm,source,key){
    Object.defineProperty(vm,key,{
        get(){
            return vm[source][key]
        },
        set(newValue){
            if(vm[source][key]!=newValue){
                vm[source][key]=newValue;
            }
        }
    })
}

function init_data(vm){
    let data=vm.$options.data;

    // 判断data是对象还是函数并且重新赋值
    data=typeof data==='function'?data.call(vm):data;

    // 实例上挂载_data
    vm._data=data

    // 将data劫持重新定义data
    observe(data)

    // 将vm._data代理给vm
    for(let key in data){
        proxy(vm,'_data',key)
    }
}

下面我们在看我们的vm实例会发现多了name和age属性。并且可以通过vm访问到和修改

在这里插入图片描述
到这里不知你们还记得我们最早说过的,这只是一个只有一层对象的数据劫持。如果多层就代理不到了
我们修改index.html代码如下

       const vm=new MVue({
            data(){
                return{
                    name:"zhangsan",
                    age:"16",
                    address:{
                        city:"地球村    "
                    }
                }
            }
       })
       console.log(vm);

在游览器上。我们会看到address并且没有get和set方法。下面我们来解决这个问题

在这里插入图片描述

observe/index.js文件下修改如下代码

// 这里会存在一个闭包,get和set方法存放了函数外部的变量value
export function define_reactive(data, key, value) {
    observe(value)		// 递归调用我们的observe方法

    Object.defineProperty(data, key, {
        get() {
            return value
        },
        set(newValue){
            if(value!=newValue){
                value=newValue
            }
        }
    })
}

再次看我们的address就会发现get和set方法已经出现了。这说明我们的多级对象代理已经完成了

在这里插入图片描述

用户可能会存在这样的赋值,现在我们是没办法办法代理到的

const vm = new MVue({
    data() {
        return {
            name: "zhangsan",
            age: "16",
           
        }
    }
})
vm.address = {
    city: "地球村"
}

所以我们在observe/index.js文件下define_reactive方法中的set修改如下。如果直接通过vm赋值对象,给这些属性同样代理

set(newValue){
    if(value!=newValue){
        observe(newValue)
        value=newValue
    }
}

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

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

相关文章

怎么快速搭建BI?奥威BI系统做出了表率

搭建BI系统有两大关键&#xff0c;分别是环境搭建和数仓建设。这两点不管是哪一个都相当地费时费力&#xff0c;那要怎么才能快速搭建BI平台&#xff0c;顺利实现全企业数字化运营决策&#xff1f;奥威BI系统方案&#xff0c;你值得拥有&#xff01; 奥威BI系统方案&#xff0…

VS+Qt环境下解决中文乱码问题

目录 原因解决方案总结 原因 使用VSQt出现中文乱码的情况一般都是给控件添加中文文本时出现&#xff0c;而控件需要的字符串类型是QString&#xff0c;默认是utf-8。在 Visual Studio 中&#xff0c;源代码文件的默认执行字符集可能是 Windows 默认的 ANSI 字符集&#xff0c;…

0基础学习VR全景平台篇 第79篇:全景相机-泰科易如何直播推流

泰科易科技是中国的一家研发全景相机的高科技公司&#xff0c;前不久&#xff0c;在2020世界VR产业大会上发布了新一代5G VR直播影像采集终端--360starlight。以其出色的夜景成像效果和一“部”到位的直播方案重新定义了VR慢直播相机&#xff0c;对行业具有高度借鉴意义。 本文…

吸取图片指定点的颜色-微信小程序

“远看色,近看形,细看质”&#xff0c;我不是设计师&#xff0c;所以彩色那么美&#xff0c;却总也不会用&#xff0c;就想要是有一款颜色的工具可以帮助使用颜色&#xff0c;那不挺好&#xff1f;网上找了一些&#xff0c;要不就不是自己想要的&#xff0c;要不就是收费的&…

【HCIP】OSPF综合实验

题目&#xff1a; 配置&#xff1a; R1 //ip分配 [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 172.16.0.1 27 [r1-GigabitEthernet0/0/0]q [r1]int lo [r1]int LoopBack 0 [r1-LoopBack0]ip add 172.16.1.1 24//配置缺省 [r1]ip route-static 0.0.0.0 0 172.16.0.3 //启动…

PHP8的循环控制语句-PHP8知识详解

我们在上一节讲的是条件控制语句&#xff0c;本节课程我们讲解循环控制语句。循环控制语句中&#xff0c;主要有for循环、while循环、do...while循环和foreach循环。 在编写代码时&#xff0c;经常需要反复运行同一代码块。我们可以使用循环来执行这样的任务&#xff0c;而不是…

Data analysis|Tableau基本介绍及可基础可实现功能

一、基础知识介绍 &#xff08;一&#xff09;什么是tableau tableau 成立于 2003 年&#xff0c;是斯坦福大学一个计算机科学项目的成果&#xff0c;该项目旨在改善分析流程并让人们能够通过可视化更轻松地使用数据。Tableau可以帮助用户更好地理解和发现数据中的价值&#x…

Packet Tracer - IPv4 和 IPv6 编址故障排除

Packet Tracer - IPv4 和 IPv6 编址故障排除 地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 IPv6 地址/前缀 R1 G0/0 10.10.1.1 255.255.255.0 N/A G0/1 192.168.0.1 255.255.255.0 N/A 2001:DB8:1:1::1/64 N/A G0/2 2001:DB8:1:2::1/64 N/A S0/0/0 …

汽车用功率电感器

支持车载用被动元件的可靠性认证测试标准“AEC-Q200”的绕线铁氧体功率电感器 LCXH 系列实现商品化&#xff0c;推出了“LCXHF3030QK”等 6 个尺寸的 64 款商品。 这些商品均是用于汽车车身类及信息娱乐等信息类的电源电路用扼流线圈及噪音滤波器的功率电感器。 LCXH 系列与民生…

Xorm开发详细文档

文章目录 介绍特性支持的数据库安装 创建 Engine单引擎日志连接池 引擎组引擎组策略负载策略 定义表结构体各种映射规则前缀映射&#xff0c;后缀映射和缓存映射使用 Table 和 Tag 改变名称映射Column 属性定义Go与字段类型对应表 表结构操作获取数据库信息表操作创建索引和唯一…

MySQL — 存储引擎

文章目录 存储引擎存储引擎类型InnoDBMyISAMMEMORY 存储引擎是数据库的核心&#xff0c;对于mysql来说&#xff0c;存储引擎是以插件的形式运行的。虽然mysql支持种类繁多的存储引擎&#xff0c;但是常用的就那么几种。这篇文章主要是对其进行简单的介绍。 存储引擎 MySQL可插…

Kubernetes关于cpu资源分配的设计

kubernetes资源 在K8s中定义Pod中运行容器有两个维度的限制: 资源需求(Requests):即运行Pod的节点必须满足运行Pod的最基本需求才能运行Pod。如 Pod运行至少需要2G内存,1核CPU。(软限制)资源限额(Limits):即运行Pod期间,可能内存使用量会增加,那最多能使用多少内存,这…

速通《深入理解Java虚拟机》| 第一章 走近Java

第一章 走近Java 1、Java技术体系 2、Java发展史 3、Java虚拟机家族 4、Java技术未来趋势 5、上机实验 主要步骤&#xff1a; 下载OpenJDK12源码并解压到本地安装相关依赖库编译OpenJDK12安装JetBrains的CLionDE&#xff0c;并用该IDE调试JDK源码 上机实验详情请见&#xf…

css-4:元素水平垂直居中的方法有哪些?如果元素不定宽高呢?

1、背景 在开发中&#xff0c;经常遇到这个问题&#xff0c;即让某个元素的内容在水平和垂直方向上都居中&#xff0c;内容不仅限于文字&#xff0c;可能是图片或其他元素。 居中是一个非常基础但又是非常重要的应用场景&#xff0c;实现居中的方法存在很多&#xff0c;可以将这…

《凤凰架构》第一章——服务架构演进史

前言 刚开始决定弄懂文中所提到的所有东西&#xff0c;就像我写ByteByteGo呢几篇文章一样&#xff0c;把每一句话都弄懂。但是对于《凤凰架构》来说&#xff0c;这有点太费时间了&#xff0c;并且没有必要&#xff0c;有些东西可能永远都不会用到&#xff0c;但文章为了全面的…

机器学习——卷积神经网络基础

卷积神经网络&#xff08;Convolutional Neural Network&#xff1a;CNN&#xff09; 卷积神经网络是人工神经网络的一种&#xff0c;是一种前馈神经网络。最早提出时的灵感来源于人类的神经元。 通俗来讲&#xff0c;其主要的操作就是&#xff1a;接受输入层的输入信息&…

EvilBox One靶场笔记

EvilBox: One靶场笔记 信息收集 先fscan找主机192.168.1.102 namp扫端口 开放80,22端口 然后扫目录 └─$ gobuster dir -r -u http://192.168.1.102/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,bak,html在扫secret目录&#xff0c;找…

2023年8月份华为H12-811更新了

801、[单选题]178/832、在系统视图下键入什么命令可以切换到用户视图? A quit B souter C system-view D user-view 试题答案&#xff1a;A 试题解析&#xff1a;在系统视图下键入quit命令退出到用户视图。因此答案选A。 802、[单选题]“网络管理员在三层交换机上创建了V…

鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统 em

​ Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目…

415.字符串相加

一、题目 二、代码 class Solution { public:string addStrings(string num1, string num2) {int end1 num1.size()-1;int end2 num2.size()-1;int next0;//进位string s;while(end1>0 || end2>0){int x1 end1>0?num1[end1]-0:0;int x2 end2>0?num2[end2]-0…