vue2.x数据响应式的实现

简介: vue2.x数据响应式的实现

1.响应式的实现(Object.defineProperty)


在javascript中实现数据响应式一般有两种方案, 正好也对应了vue2.x和vue3.x使用的方式


1.对象属性拦截(vue2.x)=> Object.defineProperty


2.对象整体代理(vue3.x) => Proxy


  • 对象属性拦截的实现是通过Object.defineProperty定义对象,通过get,set方法实现的


// 栗子
let data = {
  name: '我是栗子'
  age: 18
}
// 遍历每个属性
// Object.keys()将对象转化为数组形式
Object.keys(data).forEach((key) => {
  defineReactive(data, key, data[key])
})
//响应式转化
// 使用闭包特性, 使value变量不被销毁
function defineReactive(data, name, value) {
  Object.defineProperty(data, name, {
    get() {
      return value
    }
    set(newVal) {
      value = newVal
    }
  })
}


2.指令的实现(v-model)


<div>
  <input v-model="name"></input>
</div>
<script>
  let data = {
    name: '栗子',
    age: 18
  }
  Object.keys(data).forEach((key) => {
    defineReactive(data, key, data[key])
  })
  function defineReactive(data, key, value ) {
    Object.defineProperty(data, key, {
      get() {
        return value
      },
      set(newVal) {
        if(newVal === value) {
          return
        }
        value = newVal
        // 直接全部执行存在问题,会导致没有发生更改得数据也进行执行, 可以通过发布订阅模式(自定义事件)进行优化
        compile()
      }
    })
  }
  function compile() {
    let app = document.getElementById('app')
    // 拿到app的所有子元素
    const nodes = app.childNodes
    // 遍历所有子元素
    nodes.forEach(node => {
      if(node.nodeType === 1) {
        // node.attributes找到标签的属性
        const attrs = node.attributes
        Array.from(attrs).forEach(attr => {
          const dirName = attr.nodeName
          const dataProp = attr.nodeValue
          // v-model
          if(dirName === 'v-model') {
            // M->V
            node.value = data[dataProp]
            // V->M
            node.addEventListener('input', (e) => {
              data[dataProp] = e.target.value
            })
          }
          // v-text
          if(dirName === 'v-text') {
            node.innerText = data[dataProp]
          }
        })
      }
    })
  }
  // 首次渲染
  compile()
</script>


3.简单实现发布订阅模式


简单版发布订阅模式


// dep对象
const dep = {
  // map事件对象存在里面
  map: Object.create(null),
  // 收集事件
  collect(dataProp, updateFn) {
    // 判断map中是否存在该事件
    if(!this.map[dataProp]) {
      this.map[dataProp] = []
    }
    this.map[dataProp].push(updateFn)
  },
  // 触发事件
  trigger(dataProp) {
    this.map[dataProp] && this.map[dataProp].forEach(updateFn => {
      updateFn()
    })
  }
}


  • 优化指令实现


进行收集事件


function compile() {
  let app = document.getElementById('app')
  const nodes = app.childNodes
  nodes.forEach(node => {
    if(node.nodeType === 1) {
      const attrs = node.attributes
      Array.from(attrs).forEach(attr => {
        const dirName = attr.nodeName
        const dateProp = attr.nodeValue
        if(dirName === 'v-text') {
          // 第一次赋值
          node.innerText = data[dataProp]
          // 收集跟新函数
          dep.collect(dateProp, () => {
            node.innerText = data[dataProp]
          })
        }
      })
    }
  })
} 


触发收集函数


function defineReactive(data, key, value) {
  Object.defineProperty(data, key, {
    get() {
      return value  
    },
    set(newVal) {
      if(newValue === value) return
      value = newValue
      // 触发对应事件即可
      dep.trigger(key)
    }
  })
}
相关文章
|
3天前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
19 1
|
3天前
|
JavaScript 开发者
在 Vue 3 中使用 Proxy 实现数据的双向绑定
【10月更文挑战第23天】Vue 3利用 `Proxy` 实现了数据的双向绑定,无论是使用内置的指令如 `v-model`,还是通过自定义事件或自定义指令,都能够方便地实现数据与视图之间的双向交互,满足不同场景下的开发需求。
21 1
|
10天前
|
API
vue3知识点:响应式数据的判断
vue3知识点:响应式数据的判断
19 3
|
12天前
|
存储 缓存 JavaScript
vue表单案例练习:vue表单创建一行数据及删除数据的实现与理解
vue表单案例练习:vue表单创建一行数据及删除数据的实现与理解
29 2
|
14天前
|
缓存 JavaScript UED
优化Vue的响应式性能
【10月更文挑战第13天】优化 Vue 的响应式性能是一个持续的过程,需要不断地探索和实践,以适应不断变化的应用需求和性能挑战。
20 2
|
18天前
|
JavaScript 前端开发
Vue 2 和 Vue 3 之间响应式区别
10月更文挑战第7天
29 2
|
22天前
|
JavaScript 前端开发 网络架构
如何使用Vue.js构建响应式Web应用
【10月更文挑战第9天】如何使用Vue.js构建响应式Web应用
|
22天前
|
JavaScript 前端开发
如何使用Vue.js构建响应式Web应用程序
【10月更文挑战第9天】如何使用Vue.js构建响应式Web应用程序
|
28天前
|
JavaScript
vue3,使用watch监听props中的数据
【10月更文挑战第3天】
776 2
|
30天前
|
JavaScript 前端开发 数据安全/隐私保护
前端技术分享:使用Vue.js构建响应式表单
【10月更文挑战第1天】前端技术分享:使用Vue.js构建响应式表单