做外贸推广的网站有哪些,wordpress页面编辑,外管局网站收汇如何做延期,做网站 需要什么商标1.命令式和声明式框架
命令式框架关注过程
声明式框架关注结果#xff08;底层对命令式的DOM获取和修改进行了封装#xff09;
2.vue2 Object.defineProperty()双向绑定的实现
bodydiv idappinput typetext /h1…1.命令式和声明式框架
命令式框架关注过程
声明式框架关注结果底层对命令式的DOM获取和修改进行了封装
2.vue2 Object.defineProperty()双向绑定的实现
bodydiv idappinput typetext /h1/h1button按钮/button /div
/body
script// vue2实现双绑const input document.getElementsByTagName(input)[0]const h1 document.getElementsByTagName(h1)[0]const btn document.getElementsByTagName(button)[0]let data { text: }// input框输入数据h1数据和text一致实现点击按钮时h1 标签数据和input框数据同时更改Object.defineProperty(data, text, {get() {return data[text];},set(value) {// 获取到值后将h1后的内容设置为texth1.innerText value;input.value value;return true;}});input.oninput function (e) {data.text e.target.value;}btn.onclick function () {data.text 你好}
/script
3.同样页面Vu3实现 new Proxy() // vue3实现双绑const input document.getElementsByTagName(input)[0]const h1 document.getElementsByTagName(h1)[0]const btn document.getElementsByTagName(button)[0]let data { text: }let obj new Proxy(data, {get(target, property) {return target[property]},set(target, property, value) {h1.innerText value;input.value value;return true;}})input.oninput function (e) {obj.text e.target.value;}btn.onclick function () {obj.text 你好}
4.响应式数据的基本实现
响应式数据的关键是拦截对象属性的设置和读取操作
const data { text: }
function effect () {document.body.innerText data.text
}
5. vue2与vue3响应式数据实现区别
vue2的实现当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项Vue 将遍历此对象所有的 property并使用Object.defineProperty() 把这些 property 全部转为 getter/setter。vue3的实现当我们从一个组件的 data 函数中返回一个普通的 JavaScript 对象时Vue 会将该对象包裹在一个带有 get 和 set 处理程序的Proxy 中
6.vue3 proxy的简单实现响应式数据拦截
// 初始数据
const data { text: }
// 存储副作用函数的桶
const bucket new Set()
// 对数据进行代理
const obj new Proxy(data, {get(target, key) {bucket.add(effect)return target[key]},set(target, key, newVal) {target[key] newValbucket.forEach(fn fn())return true}
})function effect () {document.body.innerText obj.text
}effect()setTimeout(() {obj.text 你好
}, 1000)
7.简单实现中出现的问题
思考一下 这一段代码的问题。
1. 副作用函数的名称被写死2. 没有建立副作用函数和目标字段之前明确的关系
副作用函数的名称被写死——解决
名称写死问题真实情况下副作用函数不可能只有一个那如果有多个函数时每个函数执行都会调用一个副作用函数。比如设置obj.a 2,同样会调用set方法中的bucket.forEach(fn fn())方法。
通用一个副作用作用函数将执行DOM修改的函数以闭包形式回调函数传入副作用函数这样每次返回的都不是同一个函数
let activeEffectfunction effect(fn) {activeEffect fnfn()
}effect(() {document.body.innerText obj.text
})const obj new Proxy(data, {get(target, key) {if (activeEffect) {bucket.add(activeEffect)}return target[key]},set(target, key, newVal) {target[key] newValbucket.forEach(fn fn())return true}
})
没有建立副作用函数和目标字段之前明确的关系——解决
以上代码对每个属性都绑定了同一个副作用函数实际上真实需要的时修改text时调用他自己的函数修改a时又调用a对应的函数
解决
使用Map键值数据结构分两层进行存储副作用函数将每个数据对象对应一个map的键一个数据对象下不同属性又存储到一个Map数据下这个map的值则存储的副作用函数Set形式存使用时通过获取对象的map数据对象下的对应属性key每个对象的key的值的set数据针对每个属性操作的副作用函数并进行遍历执行即可 const obj new Proxy(data, {get(target, key) {console.log(activeEffect, activeEffect)// 没有副作用函数容错处理 直接returnif (!activeEffect) return target[key]// 判断桶中是否已经存在key与target的关联关系let depsMap bucket.get(target)// 创建一个新的Map结构与 target 关联if (!depsMap) {bucket.set(target, (depsMap new Map()))}// 判断当前Map数据中是否存在key与effect的关联关系let deps depsMap.get(key)// 不存在的话 则新建一个Set 与 key关联if (!deps) {depsMap.set(key, (deps new Set()))}// 最后将当前激活的副作用函数添加到bucket中deps.add(activeEffect)return target[key]},set (target, key, newVal) {target[key] newVal// 获取bucket下对应的数据const depsMap bucket.get(target)if (!depsMap) return// 根据key 获取副作用的执行函数const effects depsMap.get(key)// 执行副作用函数effects effects.forEach(fn fn())}
})effect(() {document.body.innerText obj.text
})
effect(() {document.title obj.a
})
8.完全实现——我的测试 const data { text: 这是obj.title, a:vue响应式数据的实现原理 }// 存储副作用函数的桶const bucket new Map()// 存储副作用函数的变量let activeEffect;// 对数据进行代理const obj new Proxy(data, {get(target, key) {// 设置副作用函数到map数据的桶中// 判断不存在activeEffect直接返回if (!activeEffect) return target[key];// 存在activeEffect时将副作用函数设置到桶中let targetMap bucket.get(target); //target对象存在才能判断key是否存在(targetMap既是bucket的值targetMap new Map()又是keyMap的键的定义)if (!targetMap) {bucket.set(target, (targetMap new Map()));}let keyMap targetMap.get(key); // keyMap既是targetMap的值又是if (!keyMap) {targetMap.set(key, (keyMap new Set()))}keyMap.add(activeEffect); //副作用函数最终是存在Set结构里面的return target[key]},set(target, key, newVal) {target[key] newVal;//获取桶里面的对象Map的key的map集合的值即所有的副作用函数进行循环执行let targetMap bucket.get(target);if (!targetMap) return;let effects targetMap.get(key);effects.forEach(fn fn())return true}})function effect(fn) {// 将函数赋值给activeEffect数据劫持到activeEffect有值时会将其设置到bucket存储副作用的桶中当拦截到数据更改时再获取对应函数并执行activeEffect fn;fn();}// 副作用函数执行一次effect(() {document.body.innerText obj.text})effect(() {document.title obj.a})