实现vue的双向绑定v-model(简易版)

Vue.js的双向数据绑定主要是通过v-model指令来实现的。但直接手写一个简易的双向绑定系统来模拟Vue的这一特性,可以帮助理解其背后的机制。以下是一个简化的实现思路,包括定义一个简单的观察者模式(Observer)和发布订阅模式(Pub/Sub)来实现数据变化的监听与更新。

1. 数据监听器(Observer)

首先,我们需要创建一个数据监听器,用于监听数据对象属性的变化,并在属性值改变时通知订阅者。

function observe(data) {
  if (!data || typeof data !== 'object') {
    return;
  }

  // 遍历所有属性
  Object.keys(data).forEach(key => {
    defineReactive(data, key, data[key]);
  });
}

function defineReactive(data, key, val) {
  observe(val); // 递归解决嵌套对象

  const dep = new Dep(); // 创建一个依赖收集器

  Object.defineProperty(data, key, {
    get() {
      Dep.target && dep.addDep(Dep.target); // 收集依赖
      return val;
    },
    set(newVal) {
      if (newVal === val) {
        return;
      }
      val = newVal;
      dep.notify(); // 通知所有订阅者
    }
  });
}

2. 依赖收集器(Dep)

依赖收集器用来收集哪些地方用到了被观察的数据,以便在数据变化时通知它们更新。

class Dep {
  constructor() {
    this.deps = []; // 存储所有依赖
  }

  addDep(dep) {
    this.deps.push(dep);
  }

  notify() {
    this.deps.forEach(dep => dep.update());
  }
}

// 在全局设置一个静态属性,作为当前的Watcher实例
Dep.target = null;

3. 订阅者(Watcher)

订阅者是连接观察者和视图的桥梁,当数据变化时,它负责执行相应的更新操作。

class Watcher {
  constructor(vm, expr, cb) {
    this.vm = vm;
    this.expr = expr;
    this.cb = cb;

    // 触发getter,添加依赖
    this.value = this.get();
  }

  get() {
    Dep.target = this; // 将当前watcher实例设为target
    const value = this.vm[this.expr];
    Dep.target = null; // 重置target
    return value;
  }

  update() {
    this.run();
  }

  run() {
    const value = this.vm[this.expr];
    const oldVal = this.value;
    if (value !== oldVal) {
      this.value = value;
      this.cb.call(this.vm, value, oldVal);
    }
  }
}

4. Vue简易实现

最后,我们可以基于上述组件实现一个非常简化的Vue双向绑定框架。

class Vue {
  constructor(options) {
    this.data = options.data;
    observe(this.data);

    // 简化版的模板渲染,这里仅示意
    new Watcher(this, 'msg', () => {
      console.log('updated:', this.msg);
    });

    // 模拟Vue的初始化渲染
    this.msg = this.data.msg;
  }
}

// 使用示例
const app = new Vue({
  data: {
    msg: 'Hello Vue!'
  }
});

app.msg = 'Hello World!'; // 触发更新

这个例子展示了如何使用JavaScript原生API实现一个简化版的Vue双向绑定机制。实际的Vue框架中,还涉及到虚拟DOM、指令解析、组件系统等复杂功能,远比这个示例要复杂得多。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue中动态绑定v-model,有几种方法可以实现。其中一种方法是使用一个数组来存储动态生成的input的值,并使用v-model绑定到数组的每个元素上。 首先,创建一个空的数组,比如selectVal: []。然后,使用v-model绑定到每个input上,如v-model="selectVal[index].value"。接下来,使用循环或其他方式动态生成需要绑定v-model的input的数量,比如使用for循环生成10个input。 示例代码如下: ``` data() { return { selectVal: [] // 创建一个空的数组 } }, mounted() { var len = 10; for (var i = 0; i < len; i++) { var item = { value: '' }; // 创建一个对象,用来存储input的值 this.selectVal.push(item); // 将对象添加到数组中 } } ``` 在上述代码中,通过循环生成了10个需要绑定v-model的input,将每个input的值存储在selectVal数组中的对应元素的value属性中。 通过这种方式,可以实现动态绑定v-model,并且根据接口返回的数据动态生成相应数量的input。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [在 vue.js 中动态绑定 v-model](https://blog.csdn.net/qq_30944053/article/details/88634779)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [vue v-model动态生成详解](https://download.csdn.net/download/weixin_38696336/14904156)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值