Vue 03 | 响应式原理

响应式原理的介绍

Vue 最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。Vue是声明式框架,

手写一个双向绑定的实现
<input id="input"/>
<p><span>输入框的内容:</span><span id="inputText"></span></p>
<button id="btn">重置数据</button>

js部分

// 获取input button span标签
const input = document.getElementById('input')
const inputText = document.getElementById('inputText')
const btn = document.getElementById('btn')

// 给input绑定input事件
input.addEvevtListener('input',function(e){
    // 1当用户在input输入框中输入,需要对数据进行修改
    data.inputText = e.target.value
    // 2通过e.target.value获取输入值,赋值给data的inputText属性
    
    
})
// 给button绑定click事件
btn.addEventListener('click',function(){

    
})
// 响应式数据
const data = {}

let it = data.inputText// 5定义变量存储属性值
// 给data添加一个'inputText'属性
// 第二个参数:想要监听的属性
// 第三个参数是相关配置项
Object.defineProperty(data,'inputText'{
	get(){// 当用户在input输入框中输入,需要对数据进行修改
    	// 6不能直接返回data.inputText,返回时会调用get,陷入死循环
    	return it
	}
	set(val){// 3修改后需要在span中显示
        // 4数据进行修改后会引起此处set的响应
        inputText.innerText = val// 用原生js实现
        it = val// 7对it赋值
    }
})
  • 响应式数据定义在后面,在修改数据时会影响页面的显示,在页面输入时也会影响数据的显示,这样才是响应式处理
  • 响应式数据核心:数据获取于数据修改时,能够监听到变化
  • Object.defineProperty(),会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象;参数:1、obj:要定义的属性对象;2、prop:要定义或修改的属性名或Symbol;3、descriptor:要定义或修改的属性描述符;返回值:被传递给函数的对象
  • 使用Object.defineProperty()方法定义(绑定)的属性,与直接在对象中声明的属性不同,它无法被Object.keys方法枚举出来。如果想要其能够被枚举出来,可以在第三参数的配置项中添加一个属性enumerable,值置为true。此时有以上方法绑定来的属性就可以被枚举出来
  • 第三参数配置项,可以自定义设置get、set方法
  • 第一部分的逻辑:在input中输入数据,修改data下的inputText属性,这会被其中的set监听到,然后进行set中的赋值操作,当要获取数据时,就可以直接获取到get中it这个变量

点击按钮时,可以修改数据,通过修改数据影响输入框的内容

// 获取input button span标签
const input = document.getElementById('input')
const inputText = document.getElementById('inputText')
const btn = document.getElementById('btn')

// 给input绑定input事件
input.addEvevtListener('input',function(e){
    // 当用户在input输入框中输入,需要对数据进行修改
    data.inputText = e.target.value
    // 通过e.target.value获取输入值,赋值给data的inputText属性
    
    
})
// 给button绑定click事件
btn.addEventListener('click',function(){
	data.inputText = '重置数据'// 1点击按钮时修改data下的数据
    
})
// 响应式数据
const data = {}

let it = data.inputText// 定义变量存储属性值
// 给data添加一个'inputText'属性
// 第二个参数:想要监听的属性
// 第三个参数是相关配置项
Object.defineProperty(data,'inputText'{
	get(){// 当用户在input输入框中输入,需要对数据进行修改
    	// 不能直接返回data.inputText,返回时会调用get,陷入死循环
    	return it
	}
	set(val){// 修改后需要在span中显示
        // 数据进行修改后会引起此处set的响应
        inputText.innerText = val// 用原生js实现
        it = val// 对it赋值
        // 在前面修改属性时会触发此处的set
        // 在set中修改输入框的内容
        input.value = val// 找到input的dom,直接赋值
    }
})

上面的代码基本完成了需求,但是其中在全局定义了一个变量it,这会造成全局的污染,需要优化

除了避免全局污染,还得要能观察到data的数据

// 获取input button span标签
const input = document.getElementById('input')
const inputText = document.getElementById('inputText')
const btn = document.getElementById('btn')

// 给input绑定input事件
input.addEvevtListener('input',function(e){
    // 当用户在input输入框中输入,需要对数据进行修改
    data.inputText = e.target.value
    // 通过e.target.value获取输入值,赋值给data的inputText属性
    
    
})
// 给button绑定click事件
btn.addEventListener('click',function(){
	data.inputText = '重置数据'// 1点击按钮时修改data下的数据
    
})
// 响应式数据
const data = {
    inputText:''
}

// 在把data数据转变为getter和setter时,应该遍历对象的每一个属性
// 所以对于data,应该先枚举出其所有的键,并遍历,同时对数据与键进行处理
Object.keys(data).forEach(// 2当响应式数据定义完后,需要对这里的函数进行调用
    key=>defineReactive(data,key,data[key])
)

// 1定义响应式处理的函数
function defineReactive(data,key,value){
    /*
    data:当前对象
    key:当前键
    value:当前值
    */
    // 获取后进行拦截
    Object.defineProperty(data,key,{
        get(){// 之前用全局变量接收
            // 这里就可以直接用value来代替,因为value拿到的就是对应的值
            return value
        },
        set(val){
            inputText.innerText = val
            value = val
            input.value = val
        }
    })
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值