精华内容
下载资源
问答
  • js实现数据双向绑定

    2017-07-18 10:18:11
    数据双向绑定源码
  • 教大家轻松实现javascript数据双向绑定
  • AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。这篇文章主要带着大家理解Angular数据双向绑定,感兴趣的小伙伴们可以参考一下
  • MVVM实现数据双向绑定

    2021-02-18 11:46:13
    MVVM实现数据双向绑定
  • 微信小程序之数据双向绑定与数据操作 数据双向绑定是指js部分数据发生变化是html部分的数据也会发生变化,当然html部分数据发生变化js部分数据也会发生变化,从而使界面很方便的实现动态数据显示,一般拥有数据双向...
  • 主要介绍了JS数据双向绑定原理与用法,结合实例形式分析了JavaScript数据双向绑定相关原理、实现技巧与操作注意事项,需要的朋友可以参考下
  • Vue.js每天必学之数据双向绑定,如何进行绑定,如何进行数据双向绑定,感兴趣的小伙伴们可以参考一下
  • 数据双向绑定浅析

    万次阅读 2018-08-14 14:39:17
    近期看到一篇文章关于jquerymy.js ,是一个关于数据双向绑定的库,具体源码有4000多行,差不多是JQUERY源码的一半,还没有慢慢细读,就想先把之前对于angular和vue的双向数据绑定给梳理一下。 数据绑定其实跟框架...

    近期看到一篇文章关于jquerymy.js ,是一个关于数据双向绑定的库,就想先把之前对于angular和vue的双向数据绑定给梳理一下。

    数据绑定其实跟框架的设计模式相关,主要有MVC,MVP,MVVM三种,可参考我总结的另一篇文章 浅析MVC,MVP,MVVM

    angular数据双向绑定模块:

    angular其实是从MVC发展过来(MVC的界面和逻辑关联紧密,数据直接从数据库读取),慢慢演变为MVVM模式(MVVM的界面与viewmodel耦合比较松,界面数据是从viewmodel中获取的,也就是Scope),其实设计模式没什么关系,只要适合自己的项目就可以了。

    angular的双向绑定主要是digest循环以及dirty-checking(脏数据检查),包括watch,digest,和apply。

    1.Angular在浏览器循环监听事件中添加了自己的digest循环事件(核心)
    浏览器一直在监听页面上的事件,当你点击一个按钮等等,操作触发之后,回调函数就会执行,然后你就可以做任何DOM操作,等回调+函数执行完成,浏览器就会相应更新DOM。 angular往里面加了监听事件。

    2.watch队列

    每次你绑定一些东西到你的UI界面上时你就会往watch队列里插入一条watch。watch就是那个可以检测它监视的model里时候有变化的东西。当我们的模版加载完毕时,Angular解释器会寻找每个directive(指令),然后生成每个需要的watch。

    3.digest循环
    当浏览器接收到可以被angular context处理的事件时,digest循环就会触发,这个循环包括了两个更小的循环组合起来的,一个是处理evalAsync队列,另一个是watch队列,其实就是digest会遍历我们的watch,然后问它有没有属性和值发生变化了,直到所有的watch队列全部都检查过,一旦有watch改变了,那就要循环从新触发,直到所有的watch都没有变化,这样才能保证所有的model都已经不会再变化了,但是如果循环超过10次的话,那么它将抛出一个异常,这是为了防止无限循环,当digest循环结束时,DOM相应的变化,这就是dirty-checking脏数据检查。

    4.最后由apply来确定是否要进入到angular context实践中,调用了就进入,不调用就不用进入,当我们使用ng-click的时候,angular在时间触发的时候回自动封装到一个apply调用,比如我们写一个ng-model=‘data’,当敲入一个a时,时间就会这样调用apply(“data = a”)。之前我使用jquery时不会更新我绑定的东西,就是因为没有调用apply, 我之前在用JS获取一段视频的时长的时候,在使用oncanplay事件来获取时长之后,发现angular并没有将获取到的时长实时通知给界面,所以手动将事件嵌入apply事件,才得以解决。
    在这里插入图片描述
    5. $digest 和 $apply
    在Angular中,有$apply和$digest两个函数,它们的差异是什么呢?
    最直接的差异是,$apply可以带参数,它可以接受一个函数,上面代码写的例子。$scope.$apply(function(){ … }),然后在应用数据之后,调用这个函数。所以,一般在集成非Angular框架的代码时,可以把代码写在这个里面调用。

    apply的内部实现:

    function $apply(expr) {
    	try {
    		return $eval(expr);
    	} catch (e) {
    		$exceptionHandler(e);
    	} finally {
    		$root.$digest();
    	}
    }
    

    实例:

    var app = angular.module("test", []);
    app.directive("increasea", function() {
        return function (scope, element, attr) {
            element.on("click", function() {
                scope.a++;
                scope.$digest();
            });
        };
    });
    app.directive("increaseb", function() {
        return function (scope, element, attr) {
            element.on("click", function() {
                scope.b++;
                scope.$digest();    //这个换成$apply即可
            });
        };
    });
    app.controller("OuterCtrl", ["$scope", function($scope) {
        $scope.a = 1;
        $scope.$watch("a", function(newVal) {
            console.log("a:" + newVal);
        });
        $scope.$on("test", function(evt) {
            $scope.a++;
        });
    }]);
    
    app.controller("InnerCtrl", ["$scope", function($scope) {
        $scope.b = 2;
    
        $scope.$watch("b", function(newVal) {
            console.log("b:" + newVal);
            $scope.$emit("test", newVal);
        });
    }]);
    
    <div ng-app="test">
        <div ng-controller="OuterCtrl">
            <div ng-controller="InnerCtrl">
                <button increaseb>increase b</button>
                <span ng-bind="b"></span>
            </div>
            <button increasea>increase a</button>
            <span ng-bind="a"></span>
        </div>
    </div> 
    

    现在能看出差别了,在increase b按钮上点击,这时候,a跟b的值其实都已经变化了,但是界面上的a没有更新,直到点击一次increase a,这时候刚才对a的累加才会一次更新上来。
    在这里插入图片描述
    在这里插入图片描述
    怎么解决这个问题呢?只需在increaseb这个指令的实现中,把$digest换成$apply即可。
    在这里插入图片描述
    区别:当调用$digest的时候,只触发当前作用域和它的子作用域上的监控,但是当调用$apply的时候,会触发作用域树上的所有监控。
    因此,从性能上讲,如果能确定自己作的这个数据变更所造成的影响范围,应当尽量调用$digest,只有当无法精确知道数据变更造成的影响范围时,才去用$apply,很暴力地遍历整个作用域树,调用其中所有的监控。
    从另外一个角度,我们也可以看到,为什么调用外部框架的时候,是推荐放在$apply中,因为只有这个地方才是对所有数据变更都应用的地方,如果用$digest,有可能临时丢失数据变更。

    VUE数据双向绑定模块:

    VUE之前我一直没正式接触使用过,最近也正开始学习,所以可能有点不全面。

    VUE双向绑定其实是利用了Object.defineProperty(要操作的对象,要定义或修改的对象属性名,具体行为)这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的(核心)。

    这里写图片描述

    这里写图片描述
    自己尝试了一下,因为之前写过JAVA,所以感觉就是跟JAVA中定义属性是一个意思,无非是JAVA中有private等性质。

    VUE采用的是数据劫持(通过Object.defineProperty劫持各个属性)结合发布者-订阅者的模式,发布者就是向订阅者告知事件已经到达了,你可以执行相应动作了,而订阅者就是在某些时间到达的时候可以通知它并执行相应的动作。

    1. 设置一个监听器,也就是Observe(发布者),用来监听所有的属性。Observe的就是之前写的Object.defineProperty(),因为属性值一般都是比较多,所有采用递归的方式遍历所有的属性值,从而达到监听所有属性的功能。

    2. 指令解析器Compile,对页面上的每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数。

    3. Watcher(订阅者)是连接Observe和compile的桥梁,可以收到每个属性变化的通知,也就是说Observe一旦监听到属性有了变动,就需要去通知watcher,watcher收到属性变化然后去通知Compile并执行相应的更新函数,然后更新界面。

    总结:总的来说,数据的双向绑定,难点是在data改变引起view改变,因为view改变的话,比如input,可以通过监听oninput事件来实现。但是当数据data改变时,处理就比较麻烦,angular采用的是apply调用的方法,而Vue是通过Object.defineProperty()对属性设置一个set函数,当数据改变了就会触发这个函数的方式。两个进行对比来说,因为angular的数据绑定是脏数据检测,简单的说就是监测新值和旧值有没有变化,这样就要定时去检测,而vue触发set方法,各有其优缺点,比如:
    比如一个带checkbox的列表,顶部有一个全选,假设这列表有200条数据,点一下全选,如果单条变更能导致界面reflow,那样的话vue的set/get将对导致大量reflow,而angular则是一次性处理完毕,更新所有数据,把结果数据一次应用到界面。
    同理,如果只改变一个属性,angular会监听全部,而vue只是set/get某个,自然vue好一点。
    总之最好的办法是了解各自使用方式的差异,考虑出它们性能的差异所在,在不同的业务场景中,避开最容易造成性能瓶颈的用法。

    展开全文
  • vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的.本文重点给大家介绍Vue数据双向绑定原理及简单实现方法,感兴趣的朋友跟随脚本之家小编一起学习吧
  • 本文通过实例代码给大家介绍了JS原生数据双向绑定问题,代码简单易懂,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
  • 主要为大家详细介绍了Vue数据双向绑定底层实现原理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了Vue数据双向绑定原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了VUE v-model表单数据双向绑定,结合完整实例形式分析了vue.js实现表单数据双向绑定相关操作技巧,需要的朋友可以参考下
  • 本篇文章主要介绍了javascript实现数据双向绑定的三种方式小结,前端的视图层和数据层有时需要实现双向绑定,目前实现数据双向绑定主要有三种,有兴趣的可以了解一下。
  • 本篇文章主要介绍了浅谈vue中数据双向绑定的实现原理 ,主要使用v-model这个数据双向绑定,有兴趣的可以了解一下
  • 主要给大家介绍了关于Vue数据双向绑定的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了vue中的数据双向绑定问题,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • 主要为大家详细介绍了vue数据双向绑定的注意点,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了Nuxt.js 数据双向绑定的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 主要介绍了AngularJS学习笔记(三)数据双向绑定的简单实例,详解数据双向绑定实例的相关资料,需要的朋友可以参考下。
  • 主要介绍了小程序input数据双向绑定实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了详谈Object.defineProperty 及实现数据双向绑定,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 主要介绍了js实现视图和数据双向绑定的方法,结合实例形式分析了vue.js及jQuery数据绑定相关操作技巧与注意事项,需要的朋友可以参考下
  • React实现数据双向绑定

    万次阅读 2019-03-03 19:24:23
    React手动实现数据双向绑定 和vue 相比 react 并没有提供向 v-model 这样的指令来实现文本框的数据流双向绑定,因为react的设计思路就是单向数据流,所以我们需要借助 onChange 和 setState 来实现一个双向的数据...

    React手动实现数据双向绑定

    • 和vue 相比 react 并没有提供向 v-model 这样的指令来实现文本框的数据流双向绑定,因为react的设计思路就是单向数据流,所以我们需要借助 onChange 和 setState 来实现一个双向的数据流

    • 实现思路大致如下:↓
      react双向数据绑定

    • 如这样一个 input
      <input ref="txt" onChange={ (e)=>this.txtChange(e) } type="text" style={ {width:'100%'} } value={this.state.mydata} />

    //监控文本框的change事件
        txtChange = (e)=>{
            // console.log(this.refs.txt.value)
            // console.log(e)
            const newVal = e.target.value
            this.setState({
                mydata: newVal
            })
        }
    

    全部代码块:

    import React from 'react'
    export default class BindEvent extends React.Component {
        constructor() {
            super()
            this.state = {
                mydata : '',
                name: 'zs',
                age: 18
            }
        }
    
        render() {
            return <div>
                BindEvent 组件
                <hr />
                <button onClick={ ()=>this.show('?', '?', '?‍?') }>按钮</button>
                <h3>{this.state.mydata}</h3>
                {/* 如果只把文本框的value绑定state状态而不提供onChange处理函数的话,提供readOnly变成一个只读的文本框 */}
                {/* <input readOnly type="text" style={ {width:'100%'} } value={this.state.mydata} /> */}
                <input ref="txt" onChange={ (e)=>this.txtChange(e) } type="text" style={ {width:'100%'} } value={this.state.mydata} />
            </div>
        }
        //监控文本框的change事件
        txtChange = (e)=>{
            // console.log(this.refs.txt.value)
            // console.log(e)
            const newVal = e.target.value
            this.setState({
                mydata: newVal
            })
        }
    
        show = (msg1, msg2, msg3)=>{
            this.setState({
                mydata: '123' + msg1 + msg2 + msg3
            }, ()=>console.log(this.state.mydata) )
        }
    
    }
    
    • index
    //固定写法
    import React from 'react'
    // import React, {component} from 'react'
    import ReactDOM from 'react-dom'
    import BindEvent from '@/components/BindEvent'
    import BindInputValue from '@/components/BindInputValue'
    
    
    
    ReactDOM.render(<div>
        <BindInputValue></BindInputValue>
        </div>,document.getElementById('app'))
    
     
    
    展开全文
  • 通过 Proxy 实现数据双向绑定前言defineProperty 缺陷defineProperty 双向绑定Proxy 语法Proxy 双向绑定 前言 用过 Vue 的人都知道 Vue 有双向绑定的功能,Vue 2 是通过 Object.defineProperty 实现的双向绑定,但是...

    前言

    用过 Vue 的人都知道 Vue 有双向绑定的功能,Vue 2 是通过 Object.defineProperty 实现的双向绑定,但是到 Vue3 中,便使用的 Proxy 进行双向绑定。今天就记录一下如何通过 Proxy 实现数据双向绑定。

    defineProperty 缺陷

    defineProperty 的作用是在一个对象上定义属性或者修改已有的属性。defineProperty 与 Proxy 相比,其缺点在于:

    1. 无法监听数组的变化;
    2. 只能劫持对象的属性,无法劫持一个完整的对象。

    defineProperty 语法为:Object.defineProperty(obj, prop, desc)
    第一个参数表示源对象;第二个参数表示对象的属性,第三个参数表示对该属性的描述。

    let obj= {}
    Object.defineProperty(obj, 'text', {
       value: '我是一段文本',
       writable: true, // 是否可以改变,
       configurable:false,//是否可配置
       enumerable:false //是否可枚举
    })
    

    defineProperty 双向绑定

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <input type="text" id="input">
    <div id="text"></div>
    </body>
    <script>
        var input = document.getElementById("input");
        var text = document.getElementById("text");
        var obj = {};
        Object.defineProperty(obj,'text',{
            get:function () {
                console.log('get');
            },
            set:function (val) {
                console.log(val);
                input.value = val;
                text.innerText = val;         
            }
        })
        input.addEventListener('keyup',function (e) {
            obj.text = e.target.value;
        })
    </script>
    </html>
    

    Proxy 语法

    Proxy 是代理的意思,是 ES6 的新语法,与 defineProperty 类似,都是对对象进行一层拦截。但 Proxy 修复了 defineProperty 的问题。可以劫持完整的对象。以下为基础用法。

       var obj = {};
       var obj1 = new Proxy(obj,{
            get:function (target,key,receiver) {
                console.log(target);
                return Reflect.get(target,key,receiver);
            },
            set:function (target,key,val,receiver) {
                console.log(target);
                return Reflect.set(target,key,val,receiver);
            },
            has:function(target, key){
                return Reflect.has(target, key);
            }
        })
    

    以上是通过 Proxy 创建了一个具有拦截功能的 obj 对象。其中 Reflect 也是 ES6 的新语法,为操作对象而提供的 API, 起作用主要有:

    1. 将 Object 对象的一些明显属于语言内部的方法放到Reflect对象上;
    2. 修改 Object 方法返回的结果,使其变得更合理。如:Object.defineProperty(obj, name, desc)在无法定义属性的时候会报错,而Reflect.defineProperty(obj, name, desc)则会返回false;
    3. 让 Object 的操作都变成函数行为。如 Object 的命令式:name in obj和delete obj[name] 则与 Reflect.has(obj, name)、Reflect.deleteProperty(obj, name)相等;
    4. Reflect 对象的方法与 Proxy 对象的方法一一对应,只要 Proxy 对象上有的方法在 Reflect 上也能找到。

    Proxy 双向绑定

    利用 Proxy 的拦截功能,可以在对象的 set 方法上将值同时赋值给 input 和对应的 div。然后在 keyup 事件内给该对象的属性进行赋值。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <input type="text" id="input">
    <div id="text"></div>
    </body>
    <script>
        var input = document.getElementById("input");
        var text = document.getElementById("text");
        var obj = {};
        var obj1 = new Proxy(obj,{
            get:function (target,key,receiver) {
                return Reflect.get(target,key,receiver);
            },
            set:function (target,key,val,receiver) {
                if(key === 'text '){
                  input.value = val;
                  text.innerText = val;
                }     
                return Reflect.set(target,key,val,receiver);
            }
        })
        input.addEventListener('keyup',function (e) {
            obj1.text = e.target.value;
        })
    </script>
    </html>
    
    展开全文
  • 1.Vue2.X的数据双向绑定原理:采用的是Object.defineProperty()方法 <!-- 1.Vue2.x采用的数据双向绑定原理 --> <input type="text" v-model> <p v-bind></p> <script> // 1....

    1.Vue2.X的数据双向绑定原理:采用的是Object.defineProperty()方法

    <!-- 1.Vue2.x采用的数据双向绑定原理 -->
        <input type="text" v-model>
        <p v-bind></p>
        <script>
            // 1.获取行内属性[v-model]
            let txt = document.querySelector('[v-model]');
            // 2.input框实现输入值
            txt.oninput = function(){
                // 3.将获取到的值赋给obj.name
                obj.name = txt.value;
            }
    
            let obj = {};
            // 4.IE8以及以下浏览器不识别该用法,自带了get和set方法
            // get的得到值变化,set是设置值的变化
            Object.defineProperty(obj,'name', {
                get(){
                    console.log('get被调用了');
                },
                // set自带一个参数
                set(value){
                    console.log('set被调用了');
                    // 获取到p的属性
                    let p = document.querySelectorAll('[v-bind]')[0];
                    // 赋值
                    p.innerHTML = value;
                }
            });
    
            // obj.name = 'summer';  // 触发了set
            // console.log(obj.name); // 触发了get
        </script>

     

    2.Vue3.0实现数据的双向绑定原理:采用的是Proxy方法,proxy是个对象

    <input type="text" v-model>
        <p v-bind></p>
        <script>
            let txt = document.querySelector('[v-model]');
            txt.oninput = function(){
               p.obj = txt.value;
            }
    
    
            let obj = {};
            let p = new Proxy(obj,{
                // 1.目标对象
                // 2.被获取的属性值
                // 3.Proxy或继承Proxy
                get(data, property, receiver){
                    // console.log('get被调用了');
                },
                // 1.目标对象
                // 2.被获取的属性值
                // 3.被获取的value值
                // 4.最初被调用的对象Proxy
                set(data, property, value, receiver){
                    // console.log('set被调用了');
                    let p = document.querySelectorAll('[v-bind]')[0];
                    p.innerHTML = value;       
                }
            });
    
            // p.name = 'summer';  // set被调用了
            // console.log(p.name); // get被调用了
            
        </script>

    3.proxy比Object.defineProperty好在哪里?

    proxy优势:

    A.可以直接监听对象而非属性

    B.可以直接监听数组的变化

    C.Proxy有多达13种拦截方式,不限于apply、ownKeys、deleteProperty、has等等是Object.defineProperty不具备的

    D.Proxy返回的是一个新对象,可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改

    Object.defineProperty的优势:

    A.兼容性好,支持IE9,而Proxy的存在浏览器兼容性问题,而且无法用polyfill磨平。

    展开全文
  • 数据双向绑定是个好东西,an1 an2 vue 也都有数据双向绑定的机制,而且基本都差不多,抄来抄去嘛!!下面以一个列表为例子来说下数据双向绑定及数据的操作。 1.把要进行数据双向绑定的属性放在page的data里,然后在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 113,805
精华内容 45,522
关键字:

数据双向绑定