精华内容
下载资源
问答
  • 双向绑定

    2019-06-17 14:47:44
    有单向绑定,就有双向绑定。如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定双向绑定 什么情况下用户可以更新View呢?填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被...

    前言

    单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。

    有单向绑定,就有双向绑定。如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

    双向绑定

    什么情况下用户可以更新View呢?填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定:
    在这里插入图片描述
    在浏览器中,当用户修改了表单的内容时,我们绑定的Model会自动更新:
    在这里插入图片描述

    vue中实现

    在Vue中,使用双向绑定非常容易,我们先创建一个VM实例:

    $(function () {
        var vm = new Vue({
            el: '#vm',
            data: {
                email: '',
                name: ''
            }
        });
        window.vm = vm;
    });
    

    然后,编写一个HTML FORM表单,并用v-model指令把某个和Model的某个属性作双向绑定:

    <form id="vm" action="#">
        <p><input v-model="email"></p>
        <p><input v-model="name"></p>
    </form>
    

    我们可以在表单中输入内容,然后在浏览器console中用window.vm.$data查看Model的内容,也可以用window.vm.name查看Model的name属性,它的值和FORM表单对应的是一致的。

    如果在浏览器console中用JavaScript更新Model,例如,执行window.vm.name=‘Bob’,表单对应的内容就会立刻更新。

    处理事件

    当用户提交表单时,传统的做法是响应onsubmit事件,用jQuery获取表单内容,检查输入是否有效,最后提交表单,或者用AJAX提交表单。

    现在,获取表单内容已经不需要了,因为双向绑定直接让我们获得了表单内容,并且获得了合适的数据类型。

    响应onsubmit事件也可以放到VM中。我们在元素上使用指令:

    <form id="vm" v-on:submit.prevent="register">
    

    其中,v-on:submit="register"指令就会自动监听表单的submit事件,并调用register方法处理该事件。使用.prevent表示阻止事件冒泡,这样,浏览器不再处理的submit事件。

    因为我们指定了事件处理函数是register,所以需要在创建VM时添加一个register函数:

    var vm = new Vue({
        el: '#vm',
        data: {
            ...
        },
        methods: {
            register: function () {
                // 显示JSON格式的Model:
                alert(JSON.stringify(this.$data));
                // TODO: AJAX POST...
            }
        }
    });
    

    在register()函数内部,我们可以用AJAX把JSON格式的Model发送给服务器,就完成了用户注册的功能。

    展开全文
  • Vue 双向绑定MVC模式以往的MVC模式是单向绑定,即Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新MVVM模式MVVM模式就是Model–View–ViewModel模式。它实现了View的变动,自动反映在 ...

    Vue 双向绑定

    MVC模式

    v2-16162a9591e46f75ed06dc952b540fb9_b.jpg

    以往的MVC模式是单向绑定,即Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新

    MVVM模式

    MVVM模式就是Model–View–ViewModel模式。它实现了View的变动,自动反映在 ViewModel,反之亦然。 我对于双向绑定的理解,就是用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。再说细点,就是在单向绑定的基础上给可输入元素(input、textare等)添加了change(input)事件,(change事件触发,View的状态就被更新了)来动态修改model。

    v2-9fb9fb6ec79c83fd38e74c1980f96352_b.jpg

    双向绑定原理

    vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。 我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令(如v-model,v-on)对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。因此接下去我们执行以下3个步骤,实现数据的双向绑定:

    1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。

    2.实现一个订阅者Watcher,每一个Watcher都绑定一个更新函数,watcher可以收到属性的变化通知并执行相应的函数,从而更新视图。

    3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显示在视图上,然后初始化相应的订阅者(Watcher)。

    1.实现一个Observer

    Observer是一个数据监听器,其实现核心方法就是Object.defineProperty( )。如果要对所有属性都进行监听的话,那么可以通过递归方法遍历所有属性值,并对其进行Object.defineProperty( )处理 如下代码实现了一个Observer。

    function Observer(data) {
        this.data = data;
        this.walk(data);
    }
    
    Observer.prototype = {
        walk: function(data) {
            var self = this;
            //这里是通过对一个对象进行遍历,对这个对象的所有属性都进行监听
            Object.keys(data).forEach(function(key) {
                self.defineReactive(data, key, data[key]);
            });
        },
        defineReactive: function(data, key, val) {
            var dep = new Dep();
          // 递归遍历所有子属性
            var childObj = observe(val);
            Object.defineProperty(data, key, {
                enumerable: true,
                configurable: true,
                get: function getter () {
                    if (Dep.target) {
                      // 在这里添加一个订阅者
                      console.log(Dep.target)
                        dep.addSub(Dep.target);
                    }
                    return val;
                },
               // setter,如果对一个对象属性值改变,就会触发setter中的dep.notify(),通知watcher(订阅者)数据变更,执行对应订阅者的更新函数,来更新视图。
                set: function setter (newVal) {
                    if (newVal === val) {
                        return;
                    }
                    val = newVal;
                  // 新的值是object的话,进行监听
                    childObj = observe(newVal);
                    dep.notify();
                }
            });
        }
    };
    
    function observe(value, vm) {
        if (!value || typeof value !== 'object') {
            return;
        }
        return new Observer(value);
    };
    
    // 消息订阅器Dep,订阅器Dep主要负责收集订阅者,然后在属性变化的时候执行对应订阅者的更新函数
    function Dep () {
        this.subs = [];
    }
    Dep.prototype = {
      /**
       * [订阅器添加订阅者]
       * @param  {[Watcher]} sub [订阅者]
       */
        addSub: function(sub) {
            this.subs.push(sub);
        },
      // 通知订阅者数据变更
        notify: function() {
            this.subs.forEach(function(sub) {
                sub.update();
            });
        }
    };
    Dep.target = null;

    在Observer中,当初我看别人的源码时,我有一点不理解的地方就是Dep.target是从哪里来的,相信有些人和我会有同样的疑问。这里不着急,当写到Watcher的时候,你就会发现,这个Dep.target是来源于Watcher。

    2.实现一个Watcher

    Watcher就是一个订阅者。用于将Observer发来的update消息处理,执行Watcher绑定的更新函数。 如下代码实现了一个Watcher

    function Watcher(vm, exp, cb) {
        this.cb = cb;
        this.vm = vm;
        this.exp = exp;
        this.value = this.get();  // 将自己添加到订阅器的操作
    }
    
    Watcher.prototype = {
        update: function() {
            this.run();
        },
        run: function() {
            var value = this.vm.data[this.exp];
            var oldVal = this.value;
            if (value !== oldVal) {
                this.value = value;
                this.cb.call(this.vm, value, oldVal);
            }
        },
        get: function() {
            Dep.target = this;  // 缓存自己
            var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数
            Dep.target = null;  // 释放自己
            return value;
        }
    };

    在我研究代码的过程中,我觉得最复杂的就是理解这些函数的参数,后来在我输出了这些参数之后,函数的这些功能也容易理解了。vm,就是之后要写的SelfValue对象,相当于Vue中的new Vue的一个对象。exp是node节点的v-model或v-on:click等指令的属性值。如v-model="name",exp就是"name"。cb,就是Watcher绑定的更新函数。 上面的代码中就可以看出来,在Watcher的getter函数中,Dep.target指向了自己,也就是Watcher对象。在getter函数中,

    var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数。

    这里获取vm.data[this.exp] 时,会调用Observer中Object.defineProperty中的get函数

    get: function getter () {
                    if (Dep.target) {
                      // 在这里添加一个订阅者
                      console.log(Dep.target)
                        dep.addSub(Dep.target);
                    }
                    return val;
                },

    从而把watcher添加到了订阅器中,也就解决了上面Dep.target是哪里来的这个问题。

    3.实现一个Compile

    v2-6f12eb9b5b1b01cdf90c4b9b39135608_b.jpg

    Compile主要的作用是把new SelfVue 绑定的dom节点,(也就是el标签绑定的id)遍历该节点的所有子节点,找出其中所有的v-指令 1.如果子节点含有v-指令,即是元素节点,则对这个元素添加监听事件。(如果是v-on,则node.addEventListener('click'),如果是v-model,则node.addEventListener('input'))。接着初始化模板元素,创建一个Watcher绑定这个元素节点。

    2.如果子节点是文本节点,即 {{ data }} ,则用正则表达式取出 {{ data }} 中的data,然后var initText = this.vm[exp],用initText去替代其中的data。

    具体代码参见

    4.实现一个MVVM

    可以说MVVM是Observer,Compile以及Watcher的“boss”了,他需要安排给Observer,Compile以及Watche做的事情如下

    a、Observer实现对MVVM自身model数据劫持,监听数据的属性变更,并在变动时进行notify b、Compile实现指令解析,初始化视图,并订阅数据变化,绑定好更新函数 c、Watcher一方面接收Observer通过dep传递过来的数据变化,一方面通知Compile进行view update。 最后,把这个MVVM抽象出来,就是vue中Vue的构造函数了,可以构造出一个vue实例。

    最后写一个html测试一下我们的功能

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>self-vue</title>
    </head>
    <style>
        #app {
            text-align: center;
        }
    </style>
    <body>
        <div id="app">
            <h2>{{title}}</h2>
            <input v-model="name">
            <h1>{{name}}</h1>
            <button v-on:click="clickMe">click me!</button>
        </div>
    </body>
    <script src="js/observer.js"></script>
    <script src="js/watcher.js"></script>
    <script src="js/compile.js"></script>
    <script src="js/mvvm.js"></script>
    <script type="text/javascript">
    
         var app = new SelfVue({
            el: '#app',
            data: {
                title: 'hello world',
                name: 'canfoo'
            },
            methods: {
                clickMe: function () {
                    this.title = 'hello world';
                }
            },
            mounted: function () {
                window.setTimeout(() => {
                    this.title = '你好';
                }, 1000);
            }
        });
    
    </script>
    </html>

    先执行mvvm中的new SelfVue(...),在mvvm.js中,

    observe(this.data);
    new Compile(options.el, this);

    先初始化一个监听器Observer,用于监听该对象data属性的值。 然后初始化一个解析器Compile,绑定这个节点,并解析其中的

    v-,{{ }}指令

    (每一个指令对应一个Watcher)并初始化模板数据以及初始化相应的订阅者,并把订阅者添加到订阅器中(Dep)。这样就实现双向绑定了。 如果v-model绑定的元素,

    <input v-model="name">

    即输入框的值发生变化,就会触发Compile中的

    node.addEventListener('input', function(e) {
                var newValue = e.target.value;
                if (val === newValue) {
                    return;
                }
                self.vm[exp] = newValue;
                val = newValue;
            });

    self.vm[exp] = newValue;这个语句会触发mvvm中SelfValue的setter,以及触发Observer对该对象name属性的监听,即Observer中的Object.defineProperty()中的setter。setter中有通知订阅者的函数dep.notify,Watcher收到通知后就会执行绑定的更新函数。 最后的最后就是效果图啦:

    v2-526b29f107df8543a307d5de31864b93_b.gif
    展开全文
  • 双向绑定的原理(vue) 简介: 双向绑定:指的就是,绑定对象属性的改变到用户界面的变化的能力,反之亦然。换种说法,如果我们有一个user对象和一个name属性,一旦我们赋了一个新值给user.name,在UI上就会显示新的...

    双向绑定的原理(vue)

    简介:

    双向绑定:指的就是,绑定对象属性的改变到用户界面的变化的能力,反之亦然。换种说法,如果我们有一个user对象和一个name属性,一旦我们赋了一个新值给user.name,在UI上就会显示新的姓名了。同样地,如果UI包含了一个输入用户姓名的输入框,输入一个新值就应该会使user对象的name属性做出相应的改变。

    vue双向绑定的实现(2.0以上)

    一:通过这个方法 Object.defineProperty 来实现 双向绑定 ( vue 2.x)

    二:Object.proxy(代理)来实现Vue3.x的双向绑定,使用代理能够解决一些性能问题,解决了defineProperty这个方法的历史遗留问题(监听数组会产生监听失效的问题)

    Object.defineProperty 来实现 双向绑定的原理代码简写

    //代码如下
    <script>
            var obj = {
                value: 0
            }
    		//Object.defineProperty给对象绑定方法,有obj 和 obj需要设置属性的值
            Object.defineProperty(obj, "value", {
                // setter 方法,设置值的方法
                set(val) {
                    console.log('current value:', val)
                    document.getElementById('valueNode').innerText = val
                },
                // getter 方法,获取值的方法,必须实现放回值
                get() {
                    console.log('dispatch getter function')
                    // return obj.value
                    return document.getElementById('valueNode').innerText
                }
            })
    
            function setValueEvt() {
                obj.value = window.event.currentTarget.value
            }
        </script>
    

    Object.defineProperty 来实现 双向绑定的原理总结

    ​ 通过Object.defineProperty这个方法,给对象某个属性(如:value)设置set()方法和get()方法,当我们给对象属性value设置值的时候,就会调用set方法。当我们取value值得时候,就会触发get方法。get()方法必须要有返回值

    展开全文
  • 小程序中的数据双向绑定 首先通过 bindinput 绑定文本框的输入事件 在 data 中声明一个变量 content ,将其动态绑定成文本框的 value 值 在 bindinput 事件中通过事件参数 e.detail.value 可以获取到文本框中最新的 ...

    小程序中的数据双向绑定

    首先通过 bindinput 绑定文本框的输入事件
    在 data 中声明一个变量 content ,将其动态绑定成文本框的 value 值
    在 bindinput 事件中通过事件参数 e.detail.value 可以获取到文本框中最新的 value 值
    通过 this.setData 将文本框最新的 value 值 赋值给 动态绑定的value值 content 即可实现数据的双向绑定

    vue中的数据双向绑定

    首先为文本框绑定 @input 监听文本框的输入事件
    为文本框动态绑定 value 属性,其值是在data中定义的变量
    在 @input绑定的事件中 通过事件参数 event.target.value 可以获取到 input 框中最新的value值
    将其重新获取到的 value 赋值给 value值动态绑定的那个变量
    区别:
    大体上区别不大,绑定事件不同,以及获取value值的具体方式不同,以及在小程序中设置data中的数据,需要调用 this.setData方法进行设置

    展开全文
  • Angular 双向绑定

    2021-01-18 10:25:39
    Angular10教程--2.3 双向绑定双向绑定大致可以分成两种类型:一、普通组件的双向绑定二、表单中的双向绑定[(ngModel)]单独使用表单元素在标签中使用总结: 前面我们了解了属性绑定、事件绑定以及输入和输出的使用,...
  • 一、什么是Vue的双向绑定?其实就是v-model 很多时候都会用v-model,但是他到底是什么呢?v-model的作用:v-model可以实现绑定一个变量:1、在变量变化的时候,ui会变化2、用户改变ui的时候,数据会变化 <input v...
  • 一、什么是Vue的双向绑定?其实就是v-model 很多时候都会用v-model,但是他到底是什么呢?v-model的作用:v-model可以实现绑定一个变量:1、在变量变化的时候,ui会变化2、用户改变ui的时候,数据会变化 <input v...
  • vue双向绑定源码解析1、概念监听器 Observer:用来劫持并监听所有属性,如果属性发生变化,就通知订阅者;订阅器 Dep:用来收集订阅者,对监听器Observer和 订阅者Watcher进行统一管理;订阅者 Watcher:可以收到...
  • MVVM实现数据双向绑定

    2021-02-18 11:46:13
    MVVM实现数据双向绑定
  • 小程序中的数据双向绑定 . 首先通过 bindinput 绑定文本框的输入事件 . 在 data 中声明一个变量 content ,将其动态绑定成文本框的 value 值 . 在 bindinput 事件中通过事件参数 e.detail.value 可以获取到文本框中...
  • 主要介绍了Vue.js单向绑定和双向绑定,结合实例形式分析了vue.js单向绑定与双向绑定相关原理、实现方法及操作技巧,需要的朋友可以参考下
  • 值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。 单向数据绑定是使用状态管理工具(如redux)的前提。如果我们使用vuex,那么数据流也是单项的,这时就会...
  • ext.js等框架逐步过渡到当前的mvvm模式,让前端开发者将注意力从dom操作逐渐解脱出来,专注于逻辑的实现,个人认为开发效率至少提升了1倍,mvvm模式的一个核心便是数据的双向绑定。什么是数据的双向绑定?上面说的是...
  • Vue2xUEditorvmodel双向绑定
  • vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。前端培训Vue 双向绑定原理几个要点:1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。2.实现一个订阅者...
  • 主要介绍了Angular和Vue双向数据绑定的实现原理(重点是vue的双向绑定),非常不错,具有参考借鉴价值,感兴趣的朋友一起看看吧
  • vue双向绑定

    2019-08-10 09:00:01
    单向绑定:单向数据变化 视图更新 双向绑定:视图更新也会影响数据变化 不使用v-model: ...v-model 是 @input + :value 的一个语法糖: ...不只输入框有双向绑定,常见的表单项也可以进行双向绑定: ...
  • Vue的双向绑定

    2021-04-09 00:59:14
    注意:我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。 如果我们使用vuex,那么数据流也是单向的,这时就会和双向数据绑定有冲突。 2、...
  • 双向绑定原理

    2020-03-31 17:15:10
    双向绑定 hello,大家好,大家都知道vue双向绑定的原理吗,这次我们就来聊一聊。 Vue是利用Object.defineProperty()里面的set与get方法来实现数据双向绑定的,下面就来了解一下吧。 <body> <input type=...
  • 相信很多人都知道双向绑定原理是基于Object.defineProperty实现的,通过该方法将对象的属性转化为getter/setter,进而实现响应式,(顺便提一句该方法在低版本的浏览器没有很好的支持,所以这也是ie8以下不支持vue的...
  • angular双向绑定

    2019-12-24 09:56:37
    Angular 中的双向绑定其实就是属性绑定+事件绑定 <input [value]="username" (input)="username = $event.target.value" /> [ ] 是属性绑定 **( )**是事件绑定 FormsModule 中提供的指令 ngModel 可以简化...
  • angular 双向绑定

    2019-08-01 16:26:16
    使用双向绑定必须在根模块引入FormMoudule,并且导入到imports中就可以使用了 单项绑定(从组件到模板,从模板到组件) 双向绑定的原理就是实现从模板到组件,组件到模板 ...
  • 教大家轻松实现javascript数据双向绑定
  • js实现数据双向绑定

    2017-07-18 10:18:11
    数据双向绑定源码
  • 那么下面就来看看关于React双向绑定的实现。 双向绑定的使用: 组件需要mixins:引用LinkedStateMixin。它提供一个linkState方法。 参数是state属性 双向绑定用valueLink={this.linkState(XX)} linkState方法返回...
  • 很多同学在理解 Vue 的时候都把 Vue 的数据响应原理理解为双向绑定,但实际上这是不准确的,我们之前提到的数据响应,都是通过数据的改变去驱动 DOM 视图的变化,而双向绑定除了数据驱动 DOM 外, DOM 的变化反过来...
  • 在现在web前端面试过程中,如果面试了vue,很多面试官会问面试者:vue中数据双向绑定的原理是什么?那么本文也是围绕这一个核心来讲。vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的,其中比较...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,583
精华内容 8,633
关键字:

双向绑定