vue双向绑定的理解 您所在的位置:网站首页 数据的双向绑定原理是什么意思 vue双向绑定的理解

vue双向绑定的理解

2024-02-24 23:56| 来源: 网络整理| 查看: 265

什么是双向绑定

把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。在单向绑定的基础上,用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定 如: 双向绑定 当用户填写表单时,View的状态就被更新了,如果此时可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定关系图如下 双向绑定

vue2双向绑定原理: 数据层(Model):应用的数据及业务逻辑视图层(View):应用的展示效果,各类UI组件业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来

ViewModel 主要职责: 数据变化后更新视图 视图变化后更新数据 当然,它还有两个主要部分组成 监听器(Observer):对所有数据的属性进行监听 解析器(Compiler):对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。通过Object.defineProperty()来实现数据劫持的。

流程图如下:

new Vue()首先执行初始化,对data执行响应化处理,这个过程发生Observe中同时对模板执行编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发生在Compile中同时定义⼀个更新函数和Watcher,将来对应数据变化时Watcher会调用更新函数由于data的某个key在⼀个视图中可能出现多次,所以每个key都需要⼀个管家Dep来管理多个Watcher将来data中数据⼀旦发生变化,会首先找到对应的Dep,通知所有Watcher执行更新函数 双向绑定,发布订阅者模式

1.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。(link:v-model) 双向绑定 依赖收集: 双向绑定

2.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。 (Object.defineProperty(),该方法有get()和set()方法,set方法,set方法可以劫持到具体更新的那个数据,从而在所有订阅者中找出现在要更新的某一个订阅者 3.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数(watcher),从而更新视图。

class Vue { constructor(options) { //options.beforeCreate.call(this) //生命周期:创建前 this.obj = {}; this.$data = options.data; //$data接收数据 this.proxyData(); //将this.$data数据暴露给vue //双向绑定第一步:劫持并监听所有属性 this.observer() //options.created.bind(this)() ///生命周期:创建后 this.$el = document.querySelector(options.el); //绑定,挂载vue根节点 //options.beforeMount.bind(this)() //生命周期:挂载前 this.compile(this.$el);//负责模板解析编译,初始化 ==》view [视图] //options.mounted.bind(this)() //生命周期:挂载后 console.log(this) } proxyData() { Object.keys(this.$data).forEach(key => { //this,当前的,需要暴露 Object.defineProperty(this, key, { get() { //第一次给值,触发改变,那么给监听$data的值就行 return this.$data[key]; }, set() { } }) }) } observer() { //监听所有$data的属性 let vueThis = this; Object.keys(this.$data).forEach(key => { let item = this.$data[key]; Object.defineProperty(this.$data, key, { get() { return item; }, set(val) { //当该属性发生变化,this.obj[key]就是那个修改了变化 //那一个发生变化,触发这个函数 //双向绑定第三步:从所有订阅者中,筛选出要更新的订阅者。 item = val;//数据发生改变值,再给get,允许改变 // new Watcher(this, key, nodes[i], "textContent"); vueThis.obj[key].forEach(itemWatcher => { itemWatcher.update(); }) } }) }) } compile(parent) { let nodes = parent.childNodes//获取所有的$el内的节点 for (let i = 0; i //元素节点类型是1 //判断元素节点上,有没有是双向绑定v-model. if (nodes[i].hasAttribute("v-model")) { let key = nodes[i].getAttribute("v-model"); nodes[i].value = this[key];//第一次放值 nodes[i].addEventListener('input', () => { //改数据 this.$data[key] = nodes[i].value; this[key] = nodes[i].value; }) } this.compile(nodes[i])//元素节点里面,可能也有订阅者 } if (nodes[i].nodeType == 3) {//文本节点类型是3 let text = nodes[i].textContent; let newText = text.replace(/{{(.*)}}/g, (firstStr, regStr) => { /* 依赖收集: 视图中会用到data中某key,这称为依赖。同⼀个key可能出现多次,每次都需要收集出来用⼀个Watcher来维护它们,此过程称为依赖收集多个Watcher需要⼀个Dep来管理,需要更新时由Dep统⼀通知 双向绑定第二步:添加所有订阅者 所有的订阅者:obj格式为 { str:[{},{},{}],//订阅者,在页面3次 a:[{}], b:[{}] } */ let key = regStr.trim(), watcher = new Watcher(this, key, nodes[i], "textContent"); //判断订阅者,是否多次出现页面 if (this.obj[key]) { //有订阅者 this.obj[key].push(watcher) } else { //没有订阅者 this.obj[key] = [] this.obj[key].push(watcher) } return this[key]; }) nodes[i].textContent = newText; // ==》view [视图] } } } beforeCreate() { } created() { } beforeMount() { } mounted() { } } class Watcher { // new Watcher(this, key, nodes[i], "textContent"); constructor(vm, key, node, attr) { this.vm = vm;//当前vue this.key = key;//vue哪个属性 this.node = node;//哪个节点 this.attr = attr;//对节点,哪个属性操作 } update() { //更新视图 // new Watcher(this, key, nodes[i], "textContent"); this.node[this.attr] = this.vm[this.key]; } }

vue2 的双向数据绑定是利用ES5 的一个 API Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。 vue3 中使用了 es6 的 ProxyAPI 对数据代理。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有