精华内容
下载资源
问答
  • Vue双向绑定原理初学

    2019-07-18 15:31:14
    Vue双向绑定原理入门双向绑定概念数据可观测依赖...而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-08-23 15:57:13
    通俗易懂了解Vue双向绑定原理及实现 Vue双向绑定原理,教你一步一步实现双向绑定 机制:数据劫持结合发布者订阅者模式 思路: 1.双向绑定过程:输入框输入值—>数据值变化---->页面数据显示变化 2.第一步很简单...

    看了很多别人写的文档,总是不能彻底理解,所以整理一遍

    参考文章:
    通俗易懂了解Vue双向绑定原理及实现
    Vue双向绑定原理,教你一步一步实现双向绑定
    机制:数据劫持结合发布者订阅者模式
    思路:
    1.双向绑定过程:输入框输入值—>数据值变化---->页面数据显示变化
    2.第一步很简单,事件监听就可以实现,主要是数据值怎么监听它变化,然后把变化值渲染到页面上
    3.数据劫持:监听数据
    Object.defineProperty()方法可以监听数据变化
    4.发布者订阅者模式:基于上面功能,实现把变化值渲染到页面上

    • 首先要把vue对象的所有属性都进行监听

    • 获取属性就把相应的订阅者填进订阅器中

    • 修改属性就掉用订阅器中所有的订阅者更新方法

    • 订阅者这编译的时候初始化,初始化的时候就被存到相应的订阅器中

    • 编译是解析数据模板比如{{}},v-model,一旦解析到这些,就会获取到prop,和相应的元素,放到订阅者中,就可以建立什么属性变化什么页面元素变化。

    监听器observer:将vue实例对象的data放入,就会把其中所有属性都监听
    订阅器dep:获取属性值并且Dep.target不为空,就将订阅者加入dep中,
    修改属性值,就通知订阅者更新
    订阅者watcher:自己加入dep中,更新视图层
    编译器compile:解析模板,遇到数据绑定,调用用订阅者

    在这里插入图片描述

    展开全文
  • 目录vue双向绑定原理及实现面试解释 vue双向绑定原理及实现 数据双向绑定原理简单概括的话就是: View层影响Model层是通过对 ‘keyup’ 等事件的监听。 Model层影响View层是通过 Object.defineProperty( ) 方法劫持...

    vue双向绑定原理及实现

    数据双向绑定原理简单概括的话就是:
    View层影响Model层是通过对 ‘keyup’ 等事件的监听。
    Model层影响View层是通过 Object.defineProperty( ) 方法劫持数据并结合发布订阅者模式的方式来实现数据的双向绑定。
    在这里插入图片描述
    根据原理图来介绍整个流程:

    1、首先使用Object.defineProperty()中的 getter/setter 作为一个Observer(劫持器)去劫持data对象中的所有属性,在属性 set 的时候通知Dep(订阅者收集器)去通知相关订阅者。

    2、实现一个 Watcher(订阅者),Watcher 就是收到 Dep 数据变化的通知后,会去执行相对应的更新函数来更新视图,同一个数据可能在多处被使用,所以订阅者不止一个;这也是 Dep 存在的意义,对 Watcher 集中起来统一管理。

    3、Dep(订阅者收集器),里面存放每个数据对应的所有 Watcher,当Observer 的 set 方法被触发时,就调用 Dep 里面的的notify(通知)方法,逐条去通知所有的 Watcher 。

    4、Complier是一个编译器,作用是解析模板指令,扫描和解析 vue 代码中每一个节点,先将节点转换为碎片化文档 DocumentFragment(性能优化,减少重排),再一次性 append 所有节点至目标 element 内,完成视图的初始化;同时编译器还担当着初始化 Watcher 的任务,即给 Watcher 绑定相关的更新函数 ,最终使 Watcher 添加到 Dep 中去。

    面试解释

    如果可以的话把整个流程图画出来给面试官看,然后顺着流程讲给他听就行。但是一定要讲到 Object.defineProperty( )

    展开全文
  • vue双向绑定 大家其实对于这个问题不会很陌生,vue中采用mvvm的模式,内置vm将view层与model层两者进行关联,任何一方的变化都会让另外一方受到影响。那回答完后,面试官还会继续追问,请回答一下你理解的双向数据...

    在面试一些大厂的时候,面试官可能会问到你vue双向数据绑定的原理是什么?有些小伙伴不知道是什么东西,这样你在面试官的眼里就大打折扣了。今天小千就来给大家介绍一下vue的双向绑定原理,千万不要错过啦。

    vue双向绑定

    大家其实对于这个问题不会很陌生,vue中采用mvvm的模式,内置vm将view层与model层两者进行关联,任何一方的变化都会让另外一方受到影响。那回答完后,面试官还会继续追问,请回答一下你理解的双向数据绑定背后的原理是什么?那今天我们就一起探讨一下vue的背后的一些方式实现。

    所谓要实现双向数据绑定,vue中内部采用了发布-订阅模式。内部结合了Object.defineProperty这个ES5的新特性(ie8浏览器可不支持哦…),对vue传入的数据进行了相应的数据拦截,为其动态添加get与set方法。当数据变化的时候,就会触发对应的set方法,当set方法触发完成的时候,内部会进一步触发watcher,当数据改变了,接着进行虚拟dom对比,执行render,后续视图更新操作完毕。

    来,直接上图看一下
    在这里插入图片描述
    好,分析完原理后,我们来看下es5这个方法Object.defineProperty有什么用呢?

    上代码运行一下:
    在这里插入图片描述
    运行的时候,我们不难发现,输入框里面的内容改变的时候,p标签里面的值也会对应的得到变化。原因是因为当输入框的内容发生变化的时候,我们获取到了输入框的值,然后将其赋值给object.msg属性。这样object的msg属性的set方法就会被执行,从而将对应的content值进行了改变。

    那后续当我们去修改数据,视图会不会自动更新呢?
    在这里插入图片描述
    这样,整了一个定时器,过了2s中,修改了对象的数据,对象数据发生变化,从而又会触发set方法,实现了响应的数据改变,视图也会变成了hello-world的值。其实,这就是借助了vue中的Object.defineProperty对于数据的拦截处理的流程。

    补充小贴士

    vue 2.x中使用的Object.defineProperty对于数据进行拦截,其实还是有缺陷的

    1、对象属性的新加或者删除无法监听;

    2、数组元素的增加和删除无法监听。

    那为啥2.x的时候不解决呢,从两点考虑:

    1.性能:通过遍历对象的属性进行监听,但是属性值也是对象就需要深度遍历了,这时候显然能够劫持完整对象更好

    2.无法监听数组:属性值改为数组,数组也算是一种特殊的对象,下标其实就是对象的属性,理论上是可以通过

    Object.defineProperty来处理的,那尤大大为什么没有采用这种方式呢,猜测源于数组的使用场景,数组的主要操作场景是遍历,如果每一个元素都挂载set和get方法,会产生巨大性能消耗,而且数组下标变化频繁,操作方法居多,一旦数组长度发生变化,在无法自动检测的状态下,手动更新会是一个相当繁琐的工作。

    那vue中是如何实现对数组的劫持呢,对7种常用的数组操作进行了重写,分别是push() 、pop() 、shift()、 unshift() 、splice() 、sort()、 reverse(),其中Vue.set()对于数组的处理其实就是调用了splice方法。

    针对Object.defineProperty的缺点,ES6 Proxy都能够完美得解决,它唯一的缺 点就是,对IE不友好,所以vue3在检测到如果是使用IE的情况下(没错,IE11都不支持Proxy),会自动降级为Object.defineProperty的数据监听系统。

    那么到这一步,恭喜哦!你已经明白了vue2.x的双向数据绑定原理了。

    展开全文
  • 引言:vue双向绑定原理简单来说就是:vue内部使用object.defineProperty方法给所有数据加上getter和setter方法,在数据发生改变时发布消息给订阅者Watcher,触发响应的监听回调。 object .defineProperty是JS里一...
  • https://juejin.im/post/5dcb548e51882557296f901f
  • 跨域、vue双向绑定相关面试题题目一:题目:vue数据双向绑定的实现原理网址:http://bbs.daxiangclass.com/?... 题目二:题目:懒加载原理?网址:http://bbs.daxiangclass.com/?... 题目三:题目:vue中watch和...
  • Vue的数据双向绑定原理面试中必问的一题。每当被问到Vue数据双向绑定原理的时候,大家可能都会脱口而出:Vue内部通过Object.defineProperty方法属性拦截的方式,把data对象里每个数据的读写转化成getter/setter,...
  • 在之前面试的时候被面试官问到是否了解Vue双向绑定原理,其实自己之前看过双向绑定的原理,但也就是粗略的了解,但是没有深入。面试官当时让我手写一个原理,但是就蒙了????,于是借着这篇博客对自己了解到的知识...
  • Vue双向绑定原理

    2019-04-23 13:45:47
    vue双向绑定面试中几乎都会问到的问题 vue双向绑定原理是利用了object.defineProperty()这个方法,重新定义对象获取属性值(get)和设置属性值(set)来实现的。 ...
  • 在不少面试中都有涉及到VUE双向绑定原理这个问题,于是便简单研究了一下,在这里简单的记录下自己的学习心得,小白初识VUE,若有错的地方请各位大佬提出,一起进步。 首先来段代码看看这神奇的双向绑定 <!...
  • 2019年6月6号,为了爱情,我...面试的第一家,一开始就问 Vue 双向绑定怎么实现。一脸蒙蔽,之前看过源码,但是没有深入研究,只回答出了使用 Object.definePropertyObject.defineProperty(obj, prop, { // ... g...
  • vue双向绑定原理

    2020-03-10 14:51:37
    vue双向绑定原理 为什么要学习双向绑定的原理面试 提升自我学习能力 VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法,重新定义了对象获取属性值(get)和设置属性值(set)的操作来...
  • 昨天接到一个电话面试,上来第一个问题就是Vue双向绑定原理。当时我并不知道如何监听数据层到视图层的变化,于是没答上来,挂电话后,我赶忙查了下资料,主要思路有如下三种。 1.发布者-订阅者模式(backbone.js)...
  • vue 双向绑定原理

    2020-01-16 14:30:30
    ",除了知道v-modle可以实现数据双向绑定,我哪里知道其中的原理面试已凉,回来之后查阅了资料,写下这篇博客,加深自己学习理解,也希望能帮到大家。 VUE是采用数据劫持结合发布者-订阅者模式的方式实现数据...
  • 前言 笔者是某211非计算机相关专业2018届本科生,在校期间有半年多的互联网小公司实习经历。 毕业之后投递360 ,入职了360企业安全成为专门的前端开发工程师,有幸进入一个很赞的团队,遇到很棒的导师和leader ,成长...
  • VUE双向绑定原理是前端小伙伴很难绕过的一道面试题!本篇文章对其原理进行了最大程度的精简,希望对面试VUE开发的前端小伙伴有所帮助!我在这里将指令 v-改为z-,主要完成z-model、z-click、z-text以及z-html四个提...
  • Vue数据双向绑定 Vue是采用数据劫持结合发布/订阅模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
  • vue双向数据绑定原理

    2019-05-17 09:30:51
    这个解答可回答面试中 ① vue双向数据绑定原理 和 ② vue响应原理 问题 基本原理 vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时...
  • 前几天,阿W在宿舍跟我提到在面试的时候被问到的一个问题,是关于Vue双向绑定原理的。当我听到之后,表示一头雾水,于是上网查了一下相关的资料。其中遇到了一个关键词: Object.defineProperty其实这个关键词之前...
  • vue 双向数据绑定原理

    2019-11-19 14:59:11
    Vue双向数据绑定实现原理 vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式。 分为两个进程,一个进程是对挂载目标元素模板里的v-model和{{ }}这两个指令进行编译(绿色)。另一个进程是对传...
  • 原理 vue.js是采用数据劫持结合发布者-订阅者的模式的方法,通过Object.defineProperty()来劫持各个属性的Getter、setter,在数据变动时发送消息给订阅者。 实现的整个流程 首先为每个vue属性用Object....
  • 最近我参加了一次来自合肥的电话面试(第二轮,技术面),是大厂还是小作坊我在这里按下不表,先来说说这次电面给我留下印象较深的几道面试题,这次先来谈谈Vue的数据双向绑定原理。 情景再现: 当我手机铃声响起...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,217
精华内容 2,886
关键字:

vue双向绑定原理面试

vue 订阅