不用Vue,手搓一个数据双向绑定?教你用原生JS造轮子!

大家好,我是小杨,一个写了6年前端的老码农。今天咱们不聊Vue,来点刺激的------用原生JS实现Vue的数据双向绑定!看完这篇,你会恍然大悟:"原来Vue的黑魔法这么简单?"

1. 先看Vue的双向绑定多香

html 复制代码
<!-- Vue版 -->
<input v-model="message">
<p>{{ message }}</p>

数据一变,视图自动更新,舒服吧?那原生JS咋实现呢?

2. 核心原理拆解

双向绑定其实就是:

  1. 数据变 → 视图变(数据劫持)
  2. 视图变 → 数据变(事件监听)

3. 手把手实现

第一步:数据劫持(Object.defineProperty)

javascript 复制代码
const data = {
  message: '我是初始值'
}

// 劫持数据
function observe(obj) {
  Object.keys(obj).forEach(key => {
    let value = obj[key]
    Object.defineProperty(obj, key, {
      get() {
        console.log(`读取了${key}`)
        return value
      },
      set(newVal) {
        console.log(`${key}被修改为${newVal}`)
        value = newVal
        updateView() // 数据变时更新视图
      }
    })
  })
}

observe(data)

第二步:更新视图

javascript 复制代码
function updateView() {
  document.getElementById('text').innerText = data.message
}

第三步:监听输入(事件绑定)

html 复制代码
<input id="input" type="text">
<p id="text"></p>

<script>
document.getElementById('input').addEventListener('input', (e) => {
  data.message = e.target.value // 视图变时修改数据
})
</script>

4. 效果演示

现在试试:

  1. 在控制台修改 data.message = "新值" → 页面自动更新
  2. 在输入框打字 → data.message 同步变化

这不就是简易版v-model吗!

5. 我踩过的坑

第一次实现时我忘了处理嵌套对象:

javascript 复制代码
const data = {
  user: {
    name: '小杨' // 这个子对象没被劫持!
  }
}

解决方案:递归劫持

javascript 复制代码
function observe(obj) {
  if (typeof obj !== 'object') return
  
  Object.keys(obj).forEach(key => {
    let value = obj[key]
    observe(value) // 递归劫持
    // ...原来的defineProperty逻辑
  })
}

6. 进阶版:用Proxy实现(ES6)

更优雅的现代写法:

javascript 复制代码
const data = new Proxy({ message: '你好' }, {
  set(target, key, value) {
    target[key] = value
    updateView()
    return true
  }
})

// 使用方式完全一样
data.message = '新消息' // 自动触发更新

7. 和Vue的差别在哪?

我们实现的简易版缺少:

  • 虚拟DOM优化
  • 依赖收集(Dep/Watcher)
  • 批量异步更新
  • 数组特殊处理

但核心思想一模一样!

8. 实际应用场景

我曾在老项目中用这个思路:

  • 实现表单联动(A输入框变,B选择框选项变)
  • 低代码平台的数据绑定
  • 简单的状态管理

最后送大家两句话:

  1. "理解原理最好的方式就是自己造轮子"
  2. "框架用着爽,但别忘记原生JS才是基本功"

⭐ 写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

相关推荐
meilindehuzi_a1 小时前
从零理解并实现 RAG:用 LangChain.js 构建语义检索问答系统
开发语言·javascript·langchain
世界哪有真情3 小时前
拿人类意识卡 AI?等于用 bug 验收正式产品
前端·人工智能·后端
鱼樱前端3 小时前
别再自己拼凑了!这款 Vue 3.5+ 严肃产品级组件库,把 AI 对话、工作流和复杂数据全包了!
javascript·vue.js·github
Listen·Rain3 小时前
Vue3:setup详解
前端·javascript·vue.js
Patrick_Wilson4 小时前
修好 bug 只是开始:一次由监控需求反向重构日志结构的复盘
前端·监控·数据可视化
kyriewen5 小时前
面试官让我优化一个卡死的表格,我打开 Claude 五秒重写,他放下咖啡问我要不要来当组长
前端·javascript·面试
小粉粉hhh5 小时前
React(二)——dom、组件间通信、useEffect
前端·javascript·react.js
Csvn5 小时前
🤖 AI 生成前端代码的 5 个典型翻车现场及修复指南
前端
IT_陈寒6 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
索西引擎7 小时前
【React】key 属性:协调算法中的元素标识机制与最佳实践
前端·javascript·react.js