精华内容
下载资源
问答
  • Vue双向绑定原理简单总结Vue双向绑定原理 Vue双向绑定原理 总结 vue.js是采用数据劫持结合发布者-订阅模式的方式, 通过Object.defineProperty()来劫持各个属性的setter,getter, 在数据创建时,发布消息给订阅者...

    Vue双向绑定原理简单总结

    Vue双向绑定原理

    总结

    • vue.js是采用数据劫持结合发布者-订阅模式的方式,
    • 通过Object.defineProperty()来劫持各个属性的setter,getter,
    • 在数据创建时,发布消息给订阅者,触发相应的监听回调
    展开全文
  • Vue双向绑定原理 Proxy核心 render渲染的机制 就用简单的代码来实现以下这个双向绑定的机制 <body> <div id="div1"> name:{{name}}&...

    Vue的双向绑定原理

    • Proxy核心

    • render渲染的机制

    就用简单的代码来实现以下这个双向绑定的机制

    <body>
        <div id="div1">
            name:{{name}}<br>
            age:{{age}}<br>
            <input type="text" name="" id="" value="" v-model="name">
        </div>
        <script>
            let el = document.getElementById('div1')
            let template = el.innerHTML
            let _data = {
                name:'kajian',
                age:'18'
            }
    
            let data = new Proxy(_data, {
                set (obj, name, value) {
                    obj[name] = value
                    render()
                }
            })
            render()
            function render () {
                el.innerHTML = template.replace(/{\{\w+}\}/g, (str)=>{
                    str = str.substring(2,str.length-2)
                    return _data[str]
                })
                //双向绑定
                //找所有的v-model
                Array.from(el.getElementsByTagName('input'))//获取所有input 为一个数组
                .filter(el=>el.getAttribute('v-model'))//筛选出含有v-model的input
                .forEach(input=>{
                    let name = input.getAttribute('v-model')//对应的v-model是谁
                    input.value = _data[name]//input的值为_data的值
    
                    //双向操作
                    input.oninput = function () {
                        data[name] = this.value//通过Proxy代理修改数据
                    }
                })
            }
        </script>
    </body>
    
    展开全文
  • Vue双向绑定原理初学

    2019-07-18 15:31:14
    Vue双向绑定原理入门双向绑定概念数据可观测依赖收集完整示例总结 从开始学习前端到现在走在进入中高级前端开发的路上,觉得上手容易又简单的就是Vue框架,包含其相关的生态系统。一直只是简单了解双向绑定的原理,...


    从开始学习前端到现在走在进入中高级前端开发的路上,觉得上手容易又简单的就是Vue框架,包含其相关的生态系统。一直只是简单了解双向绑定的原理,并没有手动去实现或者去拜读过源码。而vue双向绑定基本是面试必考项,通过这段时间的学习,输出以下双向绑定的简单实现示例。

    参考文章:
    通俗易懂了解Vue双向绑定原理及实现

    双向绑定

    概念

    概念:MVVM的双向绑定是指:视图变化更新数据,数据变化更新视图,视图与数据两者相互关联。
    vue官网有提到view和model两个概念,分别对应这里的视图层和数据层,而实现两者相互关联的就是vue的viewmodel即vue 实例。(如下图)
    在这里插入图片描述
    第一步视图变化更新数据,即用户界面的行为触发数据的变化。这个是我们经常使用到的:通过事件监听,执行数据处理逻辑。
    第二步数据变化更新视图,那么问题来了:怎么在数据变化时去更新相关的视图?乍一看这是什么问题,直接在数据变化时去操作dom不就可以了吗?是的,想法没错。但是,有两个问题:

    1. 要知道数据什么时候变化,不可能在每个更改数据的地方去操作dom
    2. 去更新哪些dom,这些依赖于当前数据的dom怎么收集到?什么时候去搜集?

    把这两个问题弄清楚,解决掉,基本就可以实现一个简单的双向绑定逻辑了,也就能更好的理解vue的双向绑定的实现原理。
    后续为了方便描述,我们把依赖于数据的dom(当然不止是dom,还可能是其他的)称为订阅者。

    数据可观测

    第一个问题,要知道源数据什么时候变化,在变化时进行后续更新操作。“在一个对象时候变化时,进行一系列逻辑处理”,这种模式是不是很熟悉:事件监听。因为是针对数据的,所以这里应该是监听数据,问题就变为如何监听数据的变化,换一种说法就是如何实现数据的可观测
    Javascript有一个方法Object.defineProperty()

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
    Object.defineProperties()是他的复数方法。

    Object.defineProperty()可以定义属性的存取描述符即setter/getter方法:

    get
    一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。
    默认为 undefined。
    set
    一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
    默认为 undefined。

    所以我们可以通过这个方法去给我们要监听的数据做监听:使用 Object.defineProperty 把这些属性全部转为 getter/setter(vue就是对data这么做的),这样就可以在set方法里监测到数据的变化,那我们第一个问题就解决掉了。
    我们先定义一个转化属性为getter/setter的方法:

    // 定义实现监测响应的方法
    function defineReactive(obj, key, val) { 
    	observe(val); // 递归进行数据监测
    	Object.defineProperty(obj, key, {
    		get() {
    			console.log(`获取${key}的值`);
    			return val;
    		}, 
    		set(newValue) {
    			console.log(`设置${key}的值`);
    			val = newValue;
    		}
    	})
    }
    
    // 定义初始化数据响应的方法
    function obeserve(data) {
    	if(!data || typeof data !== 'object') {
    		return;
    	}
    	let keys = Objec.keys(data);
    	keys.forEach((key) => {
    		defineReact(data, key, data[key]);
    	})
    }
    

    依赖收集

    我们现在知道怎么监测到数据变化了,下面看一下如何确定要更新的对象——订阅者。我们需要把订阅者收集起来,在数据发生变化的时候统一通知他们进行更新。
    还是Object.defineProperty(),看一下上面它的get方法:当访问该属性时,该方法会被执行。我们要收集订阅者,是不是就可以在订阅者初始化的时候调用一下数据的get,触发收集方法。
    首先定义一个用来存放订阅者的容器:

    class Dep {
    	constructor() {
    		this.subs = [];
    	},
    	addSub(sub) {
    		this.subs.push(sub);
    	}, 
    	depend() { // 判断是否要添加依赖
    		if(Dep.target) {	
    			this.addSub(Dep.target);
    		}
    	}, 
    	notify() {
    		this.subs.forEach((sub) => {
    			sub.update(); // 元素进行更新
    		})
    	}
    }
    
    Dep.target = null
    // 稍微改造下监测逻辑
    function defineReactive(obj, key, val) { 
    	observe(val);
    	let dep = new Dep();
    	Object.defineProperty(obj, key, {
    		get() {
    			dep.depend();
    			console.log(`获取${key}的值`);
    			return val;
    		}, 
    		set(newValue) {
    			console.log(`设置${key}的值`);
    			val = newValue;
    			dep.notify();
    		}
    	})
    }
    

    我们想在get的时候去收集订阅者,如何把订阅者传到容器里进行收集呢?这里给容器添加了一个参数target作为订阅者的缓存,当需要收集时,即把订阅者赋值给Dep.target,Dep就会在添加时将其加入到订阅者数组Dep.subs中。

    上面我们说了为了将订阅者信息进行收集,在每个订阅者初始化的时候去调用依赖数据的get方法。而我们只需要在初始化的时候去进行订阅者收集,所以,只有在初始化时去缓存当前的订阅者。如下:

    class Watcher {
    	constructor(vm, exp, cb) {
    		this.vm = vm;
    		this.exp = exp;
    		this.cb = cb;
    		this.value = this.get(); // 初始化时执行一下get
    	},
    	get() {
    		Dep.target = this; // 缓存自己
    		let value = this.vm.data[this.exp]; // 会触发依赖的收集
    		Dep.target = null;
    		return value;
    	}, 
    	update() {
    		let value = this.vm.data[this.exp];
    		let oldValue = this.value;
    		if(oldValue !== value) {
    			this.value = value;
    			this.cb.call(this.vm, value, oldValue1);
    		}
    	}
    }
    

    到这里,我们先是通过Object.defineProperty()实现了数据的可观测,定义Dep作为订阅者容器,在订阅者初始化时,触发数据的get方法,在数据get方法里执行Dep中添加依赖的方法,完成对订阅者的收集。再就是在数据的set方法中执行订阅者容器的notify,通知各个订阅者进行更新。就酱。

    完整示例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue 双向绑定</title>
    </head>
    <body>
        <h1 id="test"></h1>
        <input type="text">
        <input type="button" value="改变data内容" onclick="changeInput()">
        
    <script src="observer.js"></script>
    <script src="watcher.js"></script>
    <script>
        function myVue (data, el, exp) {
            this.data = data;
            observable(data);                      //将数据变的可观测
            el.innerHTML = this.data[exp];           // 初始化模板数据的值
            new Watcher(this, exp, function (value) {
                el.innerHTML = value;
            });
            return this;
        }
    
        var ele = document.querySelector('#test');
        var input = document.querySelector('input');
        
        var myVue = new myVue({
            message: 'hello world'
        }, ele, 'message');
        
        //改变输入框内容
        input.oninput = function (e) {
            myVue.data.message = e.target.value
        }
        //改变data内容
        function changeInput(){
            myVue.data.message = "Five hundred away"
        
        }
    </script>
    </body>
    </html>
    observer.js
    
    

    总结

    先回顾一下,好吧,上面已经回顾了。看图:
    在这里插入图片描述

    官方图:
    在这里插入图片描述

    我们只看了Observer劫持监听、Dep添加订阅者、通知变化、Watcher更新三个模块。Compile之后再看,大家可以自己去查阅资料。希望看完本文档对大家理解vue的双向绑定能有初步了解。

    发布者-订阅者模式:
    其实就是上文说到的假的“事件监听”,即发布者收集订阅者信息,在发布者进行发布时,通知订阅者进行处理。

    观察者模式:
    对对象进行监测,如果对象作出一些动作,即进行相关操作。

    附:
    作者是一前端开发学习者,整体思路基于个人的学习理解,描述的内容如有错误和不足,欢迎指正和批评。

    展开全文
  • vue双向绑定原理

    2019-07-01 00:06:00
    Vue是一个MVVM框架,数据绑定简单来说,就是当数据发生变化时,相应的视图会进行更新,当视图更新时,数据也会跟着变化。 实现数据绑定的方式大致有以下几种: - 1、发布者-订阅者模式(backbone.js) - 2、脏...

    什么是双向数据绑定?Vue是一个MVVM框架,数据绑定简单来说,就是当数据发生变化时,相应的视图会进行更新,当视图更新时,数据也会跟着变化。

    实现数据绑定的方式大致有以下几种:

    - 1、发布者-订阅者模式(backbone.js)
    - 2、脏值检查(angular.js)
    - 3、数据劫持(vue.js)

    发布者-订阅者模式

    一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set('property', value),有兴趣可参考这里

    我们更希望可以通过 vm.property = value 这种方式进行数据更新,同时自动更新视图。

    脏值检查

    angular是通过脏值检查方式来对比数据是否变化,来决定是否更新视图,最常见的方式是通过setInterval()来监测数据变化,当然,只会在某些指定事件触发时下才进行脏值检查。大致如下:

    - DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
    - XHR响应事件 ( $http )
    - 浏览器Location变更事件 ( $location )
    - Timer事件( $timeout , $interval )
    - 执行 $digest() 或 $apply()

    数据劫持

    Vue.js则是通过数据劫持以及结合发布者-订阅者来实现的,数据劫持是利用ES5的Object.defineProperty(obj, key, val)来劫持各个属性的的setter以及getter,在数据变动时发布消息给订阅者,从而触发相应的回调来更新视图。

    一、实现最基础的数据绑定

    <input type="text" id="in"/>
        输入的值为:<span id="out"></span>
    
        <script>
            var int = document.getElementById('in');
            var out = document.getElementById('out');
            var obj = {};
    
            Object.defineProperty(obj, 'msg', {
                enumerable: true,
                configurable: true,
                set (newVal) {
                    out.innerHTML = newVal;
                }
            })
    
            int.addEventListener('input', function(e) {
                obj.msg = e.target.value;
            })
        </script>

    Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性:里面有三个值,分别如下:

    1. obj 需要定义属性的当前对象
    2. prop 当前需要定义的属性名
    3. desc 属性描述符
    • 一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。

    有兴趣可以深入了解,这里就不多解释了=。=

    二、双向数据绑定实现(此处用MVue替代)

    上面的只是简单的使用了Object.defineProperty(),并不是我们最终想要的效果,最终想要的效果如下:

    <div id="app">
            <input type="text" v-model="text">
            输入的值为:{{text}}
            <div>
                <input type="text" v-model="text">
            </div>
        </div>
        <script>
            var vm = new MVue({
                el: '#app',
                data: {
                    text: 'hello world'
                }
            })
        </script>

    实现思路:
    1、输入框以及文本节点和data中的数据进行绑定
    2、输入框内容变化时,data中的对应数据同步变化,即 view => model
    3、data中数据变化时,对应的文本节点内容同步变化 即 model => view

    上述流程如图所示:

    1、实现一个数据监听器Obverser,对data中的数据进行监听,若有变化,通知相应的订阅者。
    2、实现一个指令解析器Compile,对于每个元素上的指令进行解析,根据指令替换数据,更新视图。
    3、实现一个Watcher,用来连接Obverser和Compile, 并为每个属性绑定相应的订阅者,当数据发生变化时,执行相应的回调函数,从而更新视图。
    4、构造函数 (new MVue({}))

    MVue构造函数

    在初始化MVue实例时,对data中每个属性劫持监听,同时进行模板编译,指令解析,最后挂载到相应的DOM中。

    function MVue (options) {
            this.$el = options.el;
            this.$data = options.data;
    
            // 初始化操作,后面会说
            // ...
        }

    1、实现 view => model

    DocumentFragment(文档片段)

    vue进行编译时,将挂载目标的所有子节点劫持到DocumentFragment中,经过一份解析等处理后,再将DocumentFragment整体挂载到目标节点上。

    function nodeToFragment (node, vm) {
            var flag = document.createDocumentFragment();
            var child;
            while (child = node.firstChild) {
                compile(child, vm);
                 if (child.firstChild) {
                    var dom = nodeToFragment(child, vm);
                    child.appendChild(dom);
                }
                flag.appendChild(child);
            }
            return flag;
        }

    模板编译(指令解析,事件绑定、初始化数据绑定)

    编译过程图

    代码如下:

    function compile (node, vm) {
            let reg = /\{\{(.*)\}\}/;
            // 元素节点
            if (node.nodeType === 1) {
                var attrs = node.attributes;
                for (let attr of attrs) {
                    if (attr.nodeName === 'v-model') {
                        // 获取v-model指令绑定的data属性
                        var name = attr.nodeValue;
                        // 绑定事件
                        node.addEventListener('input', function(e) {
                            vm.$data[name] = e.target.value;
                        })
                        // 初始化数据绑定
                        node.value = vm.$data[name];
                        // 移除v-model 属性
                        node.removeAttribute('v-model')
                    }
                }
            }
            
            // 文本节点
            if (node.nodeType === 3) {
                if (reg.test(node.nodeValue)) {
                    var name = RegExp.$1 && (RegExp.$1.trim());
                    // 绑定数据到文本节点中
                     node.nodeValue = node.nodeValue.replace(new RegExp('\\{\\{\\s*(' + name + ')\\s*\\}\\}'), vm.$data[name]);
                }
            }
        }

    现在,我们修改下MVue构造函数,增加模板编译,如下:

    function MVue (options) {
            this.$el = options.el;
            this.$data = options.data;
    
            // 模板编译
            let elem = document.querySelector(this.$el);
            elem.appendChild(nodeToFragment(elem, this))
        }

    那么,我们的view => model 已经实现了,包括初始化绑定默认值,只要修改了input中的值,data中对应的值相应变化,并触发了setter, 更新属性值等(可以自行在set方法中打印看效果,或者在控制台手动输入vm.$data.text也会看到效果)。
    2、实现 model => view
    上面可以看出,虽然我们实现了初始化数据绑定,以及输入框变化时,data中text也会变化,但是文本节点仍然没有任何变化,那么如果做到文本节点也同步变化呢,这里用的是发布者-订阅者模式。

     

    转载于:https://www.cnblogs.com/LWWTT/p/11111874.html

    展开全文
  • vue双向绑定原理

    2019-08-23 15:57:13
    通俗易懂了解Vue双向绑定原理及实现 Vue双向绑定原理,教你一步一步实现双向绑定 机制:数据劫持结合发布者订阅者模式 思路: 1.双向绑定过程:输入框输入值—>数据值变化---->页面数据显示变化 2.第一步很简单...
  • 目录vue双向绑定原理及实现面试解释 vue双向绑定原理及实现 数据双向绑定原理简单概括的话就是: View层影响Model层是通过对 ‘keyup’ 等事件的监听。 Model层影响View层是通过 Object.defineProperty( ) 方法劫持...
  • Vue双向绑定的核心方法是Object.defineProperty(),对data的每个属性进行了get、set的拦截。(数据劫持) Object.defineProperty(),该方法有三个参数, 第一个是属性所在的对象; 第二个是你要操作的属性; 第...
  • vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的.本文重点给大家介绍Vue数据双向绑定原理简单实现方法,感兴趣的朋友跟随脚本之家小编一起学习吧
  • 研究了一下vue双向绑定原理,所以简单记录一下,以下例子只是简单实现,还请大家不要吐槽~ 之前也了解过vue是通过数据劫持+订阅发布模式来实现MVVM的双向绑定的,但一直没仔细研究,这次深入学习了一下,借此机会...
  • Vue双向数据绑定原理

    2020-05-26 09:28:33
    vue数据双向绑定原理。 实现简单vue的过程,主要实现{{}}、v-model和事件指令的功能。 相关代码地址:github.com/canfoo/self… vue数据双向绑定原理 vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的...
  • 当我学习vue时,带给我最大的感觉是双向数据绑定太方便了,不用操作DOM,视图会根据数据的改变而改变。所以我感觉学习vue的同学有必要了解一下它的实现原理 1.vue双向绑定原理 var obj =...
  • vue 双向数据绑定原理

    2019-10-11 11:57:26
    使用vue也好有一段时间了,虽然对其双向绑定原理也有了解个大概,但也没好好探究下其原理实现,所以这次特意花了几晚时间查阅资料和阅读相关源码,自己也实现一个简单vue双向绑定版本,先上个成果图来吸引各位:...
  • vue数据双向绑定原理  vue数据双向绑定是通过(数据劫持)+(发布者-订阅者模式)的方式来实现的,而所谓的数据劫持就是通过Object.defineProperty() 来实现的,所谓的Object.defineProperty( )是用来做什么的?...
  • 本文仅探究双向绑定是怎样实现的。先讲涉及的知识点,再用简化得不能再简化的代码实现一个简单的 hello world 示例。 参考文章:https://segmentfault.com/a/1190000006599500一、访问器属性 访问器属性是对象中的...
  • 很久之前看过vue的一些原理,对...vue双向绑定原理浅析 vue数据的双向绑定是通过数据劫持,并结合发布-订阅模式的方式来实现的。 我们先通过一个最简单的vue例子来查看vue初始化数据上的对象到底是什么东西。 ...
  • 简单的实现数据的双向绑定首先来了解一个东西:Object.defineProperty() https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty 这里是MDN对这个的详细说明简.....
  • 自我评价 vue数据双向绑定原理分析和简单实现 代码总计分为三个版本,v3为最终版本 效果图 博客地址
  • 在不少面试中都有涉及到VUE双向绑定原理这个问题,于是便简单研究了一下,在这里简单的记录下自己的学习心得,小白初识VUE,若有错的地方请各位大佬提出,一起进步。 首先来段代码看看这神奇的双向绑定 <!...
  • 1 了解vue双向数据绑定原理 2 了解原理后,对有趣的灵魂进行一波塑造,简单实现一个MVVM框架 Vue实现双向数据绑定的做法 vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个...
  • 引言:vue双向绑定原理简单来说就是:vue内部使用object.defineProperty方法给所有数据加上getter和setter方法,在数据发生改变时发布消息给订阅者Watcher,触发响应的监听回调。 object .defineProperty是JS里一...
  • 代码很好理解,但是在看代码之前需要知道Vue双向绑定原理其实就是基于Object.defineProperty 实现的双向绑定 官方传送门 这里我们用官方的话来说Object.defineProperty() 方法会直接在一个对象上定义一个新属性,...
  • vue双向数据绑定是通过数据劫持和发布者-订阅者模式的方式来进行实现的 数据劫持:就是我们访问或者是设置对象的属性的时候,会触发Object.defineProperty()函数来进行劫持(拦截)的,返回(get)设置(set)的两个...
  • Vue数据双向绑定原理 在这里是需要区分vue2和vue3的,它们底层是不同的。 (一)Vue2双向数据绑定原理 简单理解: vue2数据双向绑定是由数据劫持结合发布-订阅的模式实现的,通过object.defineProperty()来劫持对象...
  • Vue双向绑定原理详解

    2017-07-16 13:26:00
    前言:Vue最核心的功能之一就是响应式的数据绑定模式,即view与model任意一方改变...以下是一个最简单双向绑定的例子: <body> <div id="app"> <input type="text" v-model="msg"> ...
  • 关于vue双向绑定简单实现

    千次阅读 2016-12-21 18:27:11
    vue双向绑定原理简单实现:数据劫持+订阅发布模式

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 408
精华内容 163
关键字:

vue双向绑定简单原理

vue 订阅