Vue2指令原理手写

文件结构

index.js

/*
 * @Author: RealRoad
 * @Date: 2024-10-31 17:13:50
 * @LastEditors: Do not edit
 * @LastEditTime: 2024-10-31 17:15:57
 * @Description: 
 * @FilePath: \project_10_08\vite-project\src\testVue\index.js
 */
import Vue from './Vue.js'
window.Vue=Vue

Vue.js

import Compile from './Compile.js'
import observe from './observe.js'
export default class Vue{
    constructor(options){
        //把参数options对象存为$options
        this.$options = options ||{}
        //数据
        this._data=options.data || undefined;
        Observe(this._data)
        //数据要变为响应式的


        //模板编译
        new Compile(options.el,this)
    }
}

Compile.js

/*
 * @Author: RealRoad
 * @Date: 2024-10-31 16:25:34
 * @LastEditors: Do not edit
 * @LastEditTime: 2024-10-31 16:28:44
 * @Description: 
 * @FilePath: \project_10_08\vite-project\src\testVue\Compile.js
 */
export default class Compile{
    constructor(el,vue){
        //vue实例
        this.$vue=vue;
        //挂载点
        this.$el=document.querySelector(el)
        if(this.$el){
            //调用函数,让节点变为fragment,类似与mustache中的tokens。
            //实际上用的是AST,这里就是轻量级的,fragment
           let $fragment= this.node2Fragment(this.$el);
            //编译
            this.compile($fragment);


    }
}
    node2Fragment(el){
        var fragment=document.createDocumentFragment();
        var child;
        //el为第一个子元素,循环添加到fragment中

        //让所有dom节点都添加到fragment中
        while(child=el.firstChild){
            fragment.appendChild(child);
        }

        return fragment
    }
    compile(el){
        //获取所有子节点
        var childNodes=el.childNodes;
        var self=this
        //遍历所有子节点
        for(let i=0,len=childNodes.length;i<len;i++){
            let node=childNodes[i];
            //判断是否是元素节点
            if(node.nodeType===1){
                self.compileElement(node);
            }else if(node.nodeType===3){
                self.compileText(node);
        }}

     }
     compileElement(node){
        //获取所有属性节点
        var attributes=node.attributes;
       
        //类数组变为数组
        [].slice.call(attributes).forEach(attr=>{
            if(attr.name==="v-model"){
                //获取属性值
                var value=attr.value;
                node.addEventListener("input",()=>{
                    this.$vue[value]=node.value
                })
            }else if(attr.name==="v-text"){
                node.textContent=this.$vue[attr.value]
            }
            else if(attr.name==="v-html"){
                node.innerHTML=this.$vue[attr.value]

             }
             else if(attr.name==="v-bind"){
                node.setAttribute(attr.value,this.$vue[attr.value])
            }
            else if(attr.name==="v-on"){
                node.addEventListener(attr.value,()=>{

             })}else if(attr.name==="v-show"){
                node.style.display=this.$vue[attr.value]===true?"":"none"

              }else if(attr.name==="v-if"){
                node.style.display=this.$vue[attr.value]===true?"":"none"}
                

        })
    }
    compileText(){

    }
}

 

 

 

Vue 2中,Vue基于Object.defineProperty来实现Vue的响应式更新。当我们创建一个Vue实例时,通过将data对象中的属性转化为getter和setter,当属性被访问或修改时,Vue能够捕获到,并触发相应的更新操作。具体而言,Vue在响应式对象中创建了一个Dep(依赖)实例,每个属性都有一个对应的Dep实例,用来存储依赖于该属性的Watcher(观察者)实例。当属性被访问时,会将对应的Watcher实例添加到Dep的依赖列表中,当属性被修改时,会通知Dep实例,进而触发Watcher实例的更新。 要手写Vue 2的响应式原理,可以参考以下步骤: 1. 创建一个Observer类,用来将data对象转化为响应式对象。在Observer类的构造函数中,遍历data对象的所有属性,使用Object.defineProperty将每个属性转化为getter和setter。 2. 在getter中,收集依赖,将当前的Watcher实例添加到Dep实例的依赖列表中。 3. 在setter中,触发依赖更新,通知Dep实例的所有Watcher实例进行更新。 4. 创建一个Dep类,用来管理依赖列表。Dep类具有添加依赖、移除依赖和通知依赖更新的功能。 5. 创建一个Watcher类,用来表示一个观察者。Watcher类具有update方法,当被观察的属性发生改变时,将被观察者的update方法添加到异步更新队列中。 6. 创建一个Compile类,用来编译模板。Compile类中的compile方法可以将模板中的指令解析成对应的更新函数,并创建Watcher实例。 7. 创建一个Vue类,作为整个框架的入口。在Vue类的构造函数中,将data对象转化为响应式对象,并创建Compile实例进行模板编译。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mez_Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值