天道酬勤,学无止境

理解VUE双向数据绑定原理和实现


一、原理:

1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;

2.核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法;

3.介绍一下Object.defineProperty()方法
(1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法)
(2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;

set,get方法初步了解

二、先简单的实现一个js的双向数据绑定来熟悉一下这个方法:

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <input type="text" id="a">
        <span id="b"></span>
    </div>
</body>
<script>
    var obj = {};  //定义一个空对象

    var val = 'zhao';  //赋予初始值

    Object.defineProperty(obj, 'val', {//定义要修改对象的属性

        get: function () {

            return val;
        },

        set: function (newVal) { 

             val = newVal;//定义val等于修改后的内容

            document.getElementById('a').value = val;//让文本框的内容等于val
            
            document.getElementById('b').innerHTML = val;//让span的内容等于val

        }

    });
    document.addEventListener('keyup', function (e) {//当在文本框输入内容时让对象里你定义的val等于文本框的值

        obj.val = e.target.value;

    })

</script>

</html>

这样我们就能实现js的双向数据绑定,也对这个方法有初步的了解;
这个例子实现的效果是:随着文本框输入文字的变化,span中会同步显示相同的文字内容;这样就实现了 model => view 以及 view => model 的双向绑定。
通过添加事件监听keyup来触发set方法,而set再修改了访问器属性的同时,也修改了dom样式,改变了span标签内的文本。

三、实现一个真正的双向绑定的原理

1.实现效果
先来看一下vue双向数据绑定是如何进行的,以便我们确定好思考方向

image

 

image

2.任务拆分

拆分任务可以让我们的思路更加清晰:
(1)将vue中的data中的内容绑定到输入文本框和文本节点中
(2)当文本框的内容改变时,vue实例中的data也同时发生改变
(3)当data中的内容发生改变时,输入框及文本节点的内容也发生变化

3.开始任务1——绑定内容
我们先了解一下 DocuemntFragment(碎片化文档)这个概念,你可以把他认为一个dom节点收容器,当你创造了10个节点,当每个节点都插入到文档当中都会引发一次浏览器的回流,也就是说浏览器要回流10次,十分消耗资源。
而使用碎片化文档,也就是说我把10个节点都先放入到一个容器当中,最后我再把容器直接插入到文档就可以了!浏览器只回流了1次。
注意:还有一个很重要的特性是,如果使用appendChid方法将原dom树中的节点添加到DocumentFragment中时,会删除原来的节点。

举个例子:
可以看到,我的app中有两个子节点,一个元素节点,一个文本节点
但是,当我通过DocumentFragment 劫持数据一下后

image

image

image

注意:我的碎片化文档是将子节点都劫持了过来,而我的id为app的div内已经没有内容了。
同时要主要我while的判断条件。判断是否有子节点,因为我每次appendChild都把node中的第一个子节点劫持走了,node中就会少一个,直到没有的时候,child也就变成了undefined,也就终止了循环。

来实现内容绑定
我们要考虑两个问题,一个是如何绑定要input上,另一个是如何绑定要文本节点中。
这样思路就来了,我们已经获取到了div的所以子节点了,就在DocumentFragment里面,然后对每一个节点进行处理,看是不是有跟vm实例中有关联的内容,如果有,修改这个节点的内容。然后重新添加入DocumentFragment中。

首先,我们写一个处理每一个节点的函数,如果有input绑定v-model属性或者有{{ xxx }}的文本节点出现,就进行内容替换,替换为vm实例中的data中的内容

image

然后,在向碎片化文档中添加节点时,每个节点都处理一下。

image

创建Vue的实例化函数

image

效果图如下:

image

我们成功将内容都绑定到了输入框与文本节点上!

4、实现任务2——【view => model
对于此任务,我们从输入框考虑,输入框的问题,输入框如何改变data。我们通过事件监听器keyup,input等,来获取到最新的value,然后通过Object.defineProperty将获取的最新的value,赋值给实例vm的text,我们把vm实例中的data下的text通过Object.defineProperty设置为访问器属性,这样给vm.text赋值,就触发了set。set函数的作用一个是更新data中的text,另一个等到任务三再说。

首先实现一个响应式监听属性的函数。一旦有赋新值就发生变化

image

然后,实现一个观察者,对于一个实例 每一个属性值都进行观察。

image

改写编译函数,注意由于改成了访问器属性,访问的方法也产生变化,同时添加了事件监听器,把实例的text值随时更新

image

实例函数中,观察data中的所有属性值,注意增添了observe

image

最终我们改变input中的内容能改变data中的数据,单页面却没有刷新

image

image

4、实现任务3——【model => view】
通过修改vm实例的属性 该改变输入框的内容 与 文本节点的内容。
这里涉及到一个问题 需要我们注意,当我们修改输入框,改变了vm实例的属性,这是1对1的。
但是,我们可能在页面中多处用到 data中的属性,这是1对多的。也就是说,改变1个model的值可以改变多个view中的值。
这就需要我们引入一个新的知识点:

订阅/发布者模式
订阅发布模式(又称观察者模式)定义了一种一对多的关系,让多个观察者同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察者对象。

发布者发出通知 => 主题对象收到通知并推送给订阅者 => 订阅者执行相应操作
1
举个例子:

image

之前提到的set函数的第二个作用 就是来提醒订阅者 进行noticy操作,告诉他们:“我的text变了!” 文本节点变成了订阅者,接到消息后,立马进行update操作

回顾一下,每当 new 一个 Vue,主要做了两件事:第一个是监听数据:observe(data),第二个是编译 HTML:nodeToFragement(id)。
在监听数据的过程中,我们会为 data 中的每一个属性生成一个主题对象 dep。

在编译 HTML 的过程中,会为每个与数据绑定相关的节点生成一个订阅者 watcher,watcher 会将自己添加到相应属性的 dep 容器中。

我们已经实现:修改输入框内容 => 在事件回调函数中修改属性值 => 触发属性的 set 方法。

接下来我们要实现的是:发出通知 dep.notify() => 触发订阅者的 update 方法 => 更新视图。
这里的关键逻辑是:如何将 watcher 添加到关联属性的 dep 中。

注意: 我把直接赋值的操作改为了 添加一个 Watcher 订阅者

image

那么,Watcher又该做些什么呢?

image

首先,将自己赋给了一个全局变量 Dep.target;

其次,执行了 update 方法,进而执行了 get 方法,get 的方法读取了 vm 的访问器属性,从而触发了访问器属性的 get 方法,get 方法中将该 watcher 添加到了对应访问器属性的 dep 中;

再次,获取属性的值,然后更新视图。

最后,将 Dep.target 设为空。因为它是全局变量,也是 watcher 与 dep 关联的唯一桥梁,任何时刻都必须保证 Dep.target 只有一个值。

image

image

最终我们就实现了这个双向数据绑定功能,虽然很繁琐,但我相信,你多打几遍,一定会对你有所帮助,加油吧!!

最后小编给大家附上源码:

 

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>

        <div id="app">

            <input type="text" v-model="text" /> {{text}}

        </div>

    </body>

    <script type="text/javascript">
        //          编译函数
        function compile(node, vm) {

            var reg = /\{\{(.*)\}\}/; // 来匹配{{xxx}}中的xxx

            //如果是元素节点
            if(node.nodeType === 1) {

                var attr = node.attributes;

                //解析元素节点的所有属性

                for(let i = 0; i < attr.length; i++) {

                    if(attr[i].nodeName == 'v-model') {

                        var name = attr[i].nodeValue //看看是与哪一个数据相关

                        node.addEventListener('input', function(e) { //将与其相关的数据改为最新值
                            vm[name] = e.target.value
                        })

                        node.value = vm.data[name]; //将data中的值赋予给该node

                        node.removeAttribute('v-model')

                    }

                }

            }

            //如果是文本节点

            if(node.nodeType === 3) {

                if(reg.test(node.nodeValue)) {

                    var name = RegExp.$1; //获取到匹配的字符串

                    name = name.trim();

                    //                  node.nodeValue = vm[name]; //将data中的值赋予给该node

                    new Watcher(vm, node, name) //绑定一个订阅者
                }

            }

        }

        //          在向碎片化文档中添加节点时,每个节点都处理一下

        function nodeToFragment(node, vm) {

            var fragment = document.createDocumentFragment();

            var child;

            while(child = node.firstChild) {

                compile(child, vm);

                fragment.appendChild(child);

            }

            return fragment

        }

        //          Vue构造函数     
        //      观察data中的所有属性值,注意增添了observe

        function Vue(options) {

            this.data = options.data;

            observe(this.data, this)

            var id = options.el;

            var dom = nodeToFragment(document.getElementById(id), this)

            //处理完所有节点后,重新把内容添加回去
            document.getElementById(id).appendChild(dom)

        }

        //      实现一个响应式监听属性的函数。一旦有赋新值就发生变化 

        function defineReactive(obj, key, val) {

            var dep = new Dep();

            Object.defineProperty(obj, key, {

                get: function() {

                    if(Dep.target) {

                        dep.addSub(Dep.target)

                    }

                    return val

                },
                set: function(newVal) {

                    if(newVal === val) {

                        return

                    }

                    val = newVal;

                    console.log('新值' + val);

                    //一旦更新立马通知

                    dep.notify();

                }

            })

        }

        //      实现一个观察者,对于一个实例 每一个属性值都进行观察。

        function observe(obj, vm) {

            for(let key of Object.keys(obj)) {

                defineReactive(vm, key, obj[key]);

            }

        }

        //      Watcher监听者

        function Watcher(vm, node, name) {

            Dep.target = this;

            this.vm = vm;
            this.node = node;
            this.name = name;

            this.update();

            Dep.target = null;

        }

        Watcher.prototype = {

            update() {
                this.get();
                this.node.nodeValue = this.value //更改节点内容的关键
            },
            get() {
                this.value = this.vm[this.name] //触发相应的get
            }

        }

        //      dep构造函数

        function Dep() {
            this.subs = []
        }
        Dep.prototype = {
            addSub(sub) {
                this.subs.push(sub)
            },
            notify() {
                this.subs.forEach(function(sub) {
                    sub.update();
                })
            }
        }

        var vm = new Vue({

            el: 'app',

            data: {
                text: '赵刚'
            }

        })
    </script>

</html>
标签

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 理解VUE双向数据绑定原理和实现
    原文链接: https://www.jianshu.com/p/e7ebb1500613 一、原理: 1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变; 2.核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法; 3.介绍一下Object.defineProperty()方法 (1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法) (2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法; set,get方法初步了解 二、先简单的实现一个js的双向数据绑定来熟悉一下这个方法: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA
  • 2021年Vue常见面试题以及答案
    Vue常见面试题 Vue的优点对MVVM的理解?Vue数据双向绑定原理Vue的响应式原理Vue3.x响应式数据原理Vue3.0 里为什么要用 Proxy API替代 defineProperty API?Proxy 与 Object.defineProperty 优劣对比vue中组件的data为什么是一个函数vue中created与mounted区别Vue中computed与method的区别虚拟DOM中key的作用用index作为key可能会引发的问题Vue中watch用法详解vue中对mixins的理解和使用Vue中常用的一些指令vue的自定义指令v-show和v-if指令的共同点和不同点Vue.set 改变数组和对象中的属性说说vue的生命周期的理解第一次页面加载会触发哪几个钩子?Vue组件通信有哪些方式vue-router有几种钩子函数?vue-router路由跳转方式vue-router路由传参Vuex是什么?怎么使用?什么情况下使用 Vuex?Vuex和单纯的全局对象有什么区别?为什么 Vuex 的 mutation 中不能做异步操作? Vue的优点 轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十 kb ;简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;双向数据绑定:保留了 angular 的特点,在数据操作方面更为简单;组件化:保留了
  • 前端常见的Vue面试题目汇总
    这里写自定义目录标题 前端常见的Vue面试题目汇总Vue每个生命周期什么时候被调用谈一下你对MVVM原理的理解请说一下响应式数据的原理为什么Vue采用异步渲染Vue优点Proxy与Object.defineProperty()的对比如何比较React和VueVue中相同逻辑如何抽离nextTick实现原理diff算法的时间复杂度Vue中v-if和v-show的区别异步请求适合在哪个生命周期调用第一次页面加载会触发哪几个钩子为什么v-for和v-if不能连用Vue如何进行组件间的通信父子通信兄弟通信跨级通信 什么时候需要使用beforeDestroy谈谈你对作用域插槽的理解单个插槽:命名插槽:作用域插槽: 谈谈你对keep-alive的了解v-for为什么要用key组件中的data为什么是函数 computed和watch有什么区别computed:watch: vue几种常用的指令vue常用的修饰符Vue的渲染过程Vue中的模板编译原理Vue中v-html会导致哪些问题原生dom绑定Watch中的deep:true是如何实现的action和mutation区别vue-router有哪几种导航钩子实现hash路由和history路由$route和 $router的区别Vuex的理解及使用场景你有对 Vue 项目进行哪些优化?Vue3.0你知道有哪些改进为什么使用异步组件
  • 2020前端高频面试题总结(附答案)
    [ js基础题 ] 1. new的实现原理是什么? 1. 创建一个空对象,构造函数中的this指向这个空对象 2. 这个新对象被执行 [[原型]] 连接 3. 执行构造函数方法,属性和方法被添加到this引用的对象中 4. 如果构造函数中没有返回其它对象,那么返回this,即创建的这个的新对象,否则,返回构造函数中返回的对象。 2. 深拷贝和浅拷贝的区别是什么 1.深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 2.深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。 3. bind、call、apply的区别? bind,call,apply语法概念 1.bind语法: 2.func.bind(thisArg[, arg1[, arg2[, ...]]]) 3.thisArg 当绑定函数被调用时,该参数会作为原函数运行时的this指向。当使用new 操作符调用绑定函数时, 4.该参数无效。 5.arg1, arg2, ... 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。 call语法: 1.fun.call(thisArg, arg1, arg2, ...) 2.thisArg::在fun函数运行时指定的this值。需要注意的是, 3.指定的this值并不一定是该函数执行时真正的this值
  • v-model双向绑定原理_vue面试题解析:数据双向绑定原理
    在现在web前端面试过程中,如果面试了vue,很多面试官会问面试者:vue中数据双向绑定的原理是什么?那么本文也是围绕这一个核心来讲。 vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的,其中比较关键的是数据劫持,下面咱们看一个例子。 var obj = {} Object.defineProperty(obj,'name',{ get:function(){ console.log("获取了"); }, set:function(){ console.log('修改了'); } }) obj.name= 'fei'; obj.name Object.defineProperty( )是用来做什么的?它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举。 思路分析 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据: 关键点在于data如何更新view,因为view更新data其实可以通过事件监听即可,比如input标签监听 'input' 事件就可以实现了。所以我们着重来分析下,当数据改变,如何更新视图的。 数据更新视图的重点是如何知道数据变了,只要知道数据变了,那么接下去的事都好处理。如何知道数据变了,其实上文我们已经给出答案了,就是通过Object.defineProperty( )对属性设置一个set函数
  • vue2.x入坑总结—回顾对比angularJS/React
    从感性的角度讲,我是不屑于用VUE,觉得react套件用起来更顺手,但是vue现在越来火,所以也不得入vue(杂烩汤)的坑。vue/anguarJS/React,三者对关系现在就是:https://www.zhoulujun.cn/uploadfile/images/2018/0626/20180626214906428779269.jpg自己ps了下,觉得深有道理,骚年们自己体悟,然后再问军哥^_^不过回归真题,看vue还是先了解下https://cdn.zhoulujun.cn/vue.jpg(太大,自己打开)vue生命周期及相关主题组件实例周期vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能。学习实例的生命周期,能帮助我们理解vue实例的运行机制,更好地利用钩子函数完成我们的业务代码。create 和 mounted 相关 的函数有:beforecreated》created》beforeMount》mounted》beforeDestroybeforecreated:el 和 data 并未初始化, 案例:可以在这加个loading事件 及获取路由参数,但是this.(data|computed|methods)参数均为undefind(无法访问到 el 属性和 data 属性等
  • Vue数据双向绑定原理(vue2向vue3的过渡)
    众所周知,Vue的两大重要概念: 数据驱动组件系统 接下来我们浅析数据双向绑定的原理 一、vue2 1、认识defineProperty vue2中的双向绑定是基于defineProperty的get操作与set操作,那么我们简单认识下defineProperty, 作用: 就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。 那么我们先来看下Object.getOwnPropertyDescriptor(),有定义方法就会有获取方法,对这就是与defineProperty相对的方法,它可以获取属性值。 var a ={ b:1, c:2 } console.log(Object.getOwnPropertyDescriptor(a,'b')); //查看获取b属性 这就是打印出来的结果,configurable的意思是可便利,enumerable的意思是可枚举,writable的意思是可写。 2、使用defineProperty实现简单的私有变量 知道了属性内部的属性值,我们可以使用defineProperty来实现一个私有变量。 var a ={ b:1, c:2 } Object.defineProperty(a,'b',{ writable:false //不可写 }) console.log(Object.getOwnPropertyDescriptor(a
  • v-model双向绑定原理_Vue 双向数据绑定原理
    Vue 实现 双向数据绑定 主要采用:数据劫持结合“发布-订阅”模式的方式,通过Object.defineProperty()的 set 和 get,在数据变动时发布消息给订阅者触发监听。 当我们在 input 输入内容时,在 p 标签内也会实时展示 input 的内容。 有人会说了,不就是通过获取 input 的 value 赋值给 p 标签的 innerHTML 吗,至于写的这么复杂吗?!你想说的是不是这样? 没错,这样的确可以实现 input 内容实时展示在 p 标签内。但是今天介绍的双向数据绑定,注意是 双向,我们在改变 input 的 value 时是通过 view 层修改的 model 层,如果我们现在通过 model 层修改 view 层呢?来我们实验下~ (未做成动图,抱歉,我把操作过程详细书写,大家可以根据过程自己尝试下看看效果) 我们加个定时器,3秒后修改data,看看视图会不会修改 代码书写完成打开浏览器刷新下,可以直接等待 3 秒看到 p 标签内没有任何内容。也可以刷新后修改下 input 的值,这样 3 秒后 input 和 p 的差异比较明显。 input 内容和 p 标签展示内容不一致 我们在看下通过 Object.defineProperty() 操作的结果 同样加个定时器,3秒后修改data,看看视图会不会修改 我们可以看到 3 秒后视图更新了
  • vue双向绑定原理,拿下我人生中第7个Offer,在线面试指南
    前言 这里是我整理的2019年至2021年期间通过各个渠道花时间专门整理的面试题,其中面试重点和难点都有详细解析,重点讲的是Android各方面的专题讲解包括Java小部分的技术讲解。这些题目有点技术含量,需要时间去研究一下的。 这里我不仅给大家整理了多套BAT面试题,还有小编一路收集到的面试方面的资料包及面试相关视频资料,这些在文末有提供免费领取方式的,其中包括初级,中级,高级不同水平以及不同专题所涉及到的常问范围,及面试专题和答案和系统学习视频资料,免费分享给大家,省去网上到处搜索资料的麻烦。 希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统! 1、一定要把基本的数据结构,经典的算法,Unix编程,程序编译链接及计算机原理等基础知识扎牢,这些会长远影响你的职业发展。 2、 推荐从C语言入门,不单是因为很多操作系统、网络协议栈开源代码由C/C++实现,更多是因为C语言自身的特性:作为高级语言用户无需关注底层细节,同时能直观的看到数据流向。而且C相对语法规则较为简单,可以短时间的上手应用。最重要的是,遵循C/C++、python的学习方式,比直接学习python更能清晰的知道自己程序的内存等性能状况。 3、 不要过于追求第一份工作的工资,甚至可以说不要过于看重前两年的工资(虽然我工作也没满五年
  • vue-双向绑定原理
    1.双向绑定 [1]定义 在视图上的数据发生了变化,data中的数据也要对应改变;data中的数据发生了变化,视图上的数据也要对应改变; [2]原理 vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变; 2.vue2.0双向绑定实现 在vue2.x中数据双向绑定的核心是使用 Object.defineProperty(对象,key,{get(),set()})方法来给对象的属性添加get/set方法实现的! 当我们获取对象中该属性 的数据时,就会调用该属性的get方法 <script> // vue2.x双向绑定核心是通过Object.defineProperty()方法实现 let data = { name: 'chaochao' } Object.defineProperty(data, 'name', { get () { console.log('我是get') }, set () {} }) data.name // 在此处获取了data的name属性值,就会调用name属性的get方法 </script> 注:此时还存咋一个问题,因为我们获取data.name时调用get希望 get方法返回给我们 该属性值也就是说 data.name ; 但是若是return
  • 面试题 请简述vue双向数据绑定原理
    MVVM模式 MVVM模式就是Model–View–ViewModel模式。它实现了View的变动,自动反映在 ViewModel,反之亦然。就是在单向绑定的基础上给可输入元素(input、textare等)添加了change(input)事件,(change事件触发,View的状态就被更新了)来动态修改model。 双向绑定原理 vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。 实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令(如v-model,v-on)对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。 总结成三个步骤 1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。 2.实现一个订阅者Watcher,每一个Watcher都绑定一个更新函数
  • 2020最全前端面试系列(VUE)(初学者快速上手的前端框架)
    2020前端面试系列(VUE)VUE官网MVVM模式的理解VUE双向绑定原理生命周期v-modelVUE初始化闪动watch和computed的优缺点与区别VUE通信Vue性能优化方法VUE-Routerhash模式history模式路由守卫动态路由 VUEXVUE nextTick虚拟DOM和Diff算法原理mixinrender函数 2020前端面试系列(VUE) 前端面试系列 2020最全前端面试系列(ES6) 2020最全前端面试系列(CSS) 2020最全前端面试系列(浏览器原理) 2020最全前端面试系列(数据结构) 2020最全前端面试系列(计算机网络) 2020最全前端面试系列(正则表达式) VUE官网 VUE官网 官网可以一定要自己多看看 MVVM模式的理解 MVVM 是 Model-View-ViewModel 的缩写。 Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。 View代表UI 组件,它负责将数据模型转化成UI 展现出来。 ViewModel监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。 ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉
  • 从0开始探究vue-双向绑定原理
    理解 vue是一个非常优秀的框架,其优秀的双向绑定原理,mvvm模型,组件,路由解析器等,非常的灵活方便,也使开发者能够着重于数据处理,让开发者更清晰的设计自己的业务。 双向绑定,就是数据变化的时候,自动触发视图的变化。 实践 我们都理解,vue2.0中,双向绑定的核心为Object.defineProperty(obj, prop, descriptor),方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象 参数obj为要在其上定义属性的对象。 参数prop为要定义或修改的属性的名称。 参数descriptor为将被定义或修改的属性描述符。 返回被传递给函数的对象。 尝试Object.defineProperty拦截用户对变量的设置 我们可以新建一个项目,用来模拟及学习vue双向绑定的相关内容 + vue相关 + |- 双向绑定原理 + |- js + |- myVue.js + |- index.html 修改index.html中的内容,引入自己创建的myVue.js。 + <!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1
  • 2020年Vue面试题汇总
    Vue面试题总结 理论篇1、对于Vue是一套渐进式框架的理解2、vue.js的两个核心是什么?3、vue生命周期钩子函数有哪些?4、vue 的双向绑定的原理是什么? 语法篇1、请问 v-if 和 v-show 有什么区别?2、vue常用的修饰符3、v-on可以监听多个方法吗?4、vue中 key 值的作用5、Vue 组件中 data 为什么必须是函数?6、v-for 与 v-if 的优先级 组件篇1、vue中子组件调用父组件的方法2、vue中父组件调用子组件的方法3、vue组件之间传值 路由1、怎么定义vue-router的动态路由?怎么获取传过来的值?2、vue-router有哪几种路由守卫?3、$route和 $router的区别是什么?4 、vue-router响应路由参数的变化5、vue-router 传参 vuex 理论篇 1、对于Vue是一套渐进式框架的理解 渐进式代表的含义是:主张最少。 Vue可能有些方面是不如React,不如Angular,但它是渐进的,没有强主张,你可以在原有大系统的上面,把一两个组件改用它实现,当jQuery用;也可以整个用它全家桶开发,当Angular用;还可以用它的视图,搭配你自己设计的整个下层用。你可以在底层数据逻辑的地方用OO和设计模式的那套理念,也可以函数式,都可以,它只是个轻量视图而已,只做了自己该做的事,没有做不该做的事,仅此而已
  • 2021前端面试题和笔试题——Vue
    面试 vue前端工程师的常见面试题及笔试题。 面试了近十几家公司总结出一套VUE面试题,希望能帮助到更多的人。 对 MVVM 的理解 MVVM分为Model、View、ViewModel三者。 Model:代表数据模型 View:代表视图 ViewModel:连接视图和模型,实现数据的双向绑定 Vue 实现数据双向绑定的原理 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。当把一个普通的 JavaScript 对象传给 Vue 作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转化为 getter/setter,用户看不到getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。 1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者 2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数 3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图 对
  • Vue 3.0双向绑定原理的实现
    proxy方法 vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过new Proxy()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 Vue 3.0与Vue 2.0的区别仅是数据劫持的方式由Object.defineProperty更改为Proxy代理,其他代码不变。可查看Vue 2.0双向绑定原理的实现 具体实现过程的代码如下: 定义构造函数function Vue(option){ this.$el = document.querySelector(option.el); //获取挂载节点 this.$data = option.data; this.$methods = option.methods; this.deps = {}; //所有订阅者集合 目标格式(一对多的关系):{msg: [订阅者1, 订阅者2, 订阅者3], info: [订阅者1, 订阅者2]} this.observer(this.$data); //调用观察者 this.compile(this.$el); //调用指令解析器 } 定义指令解析器Vue.prototype.compile = function (el) { let nodes = el.children; //获取挂载节点的子节点 for (var i = 0; i <
  • 面试题:vue实现双向数据绑定的原理(附源代码)
    此面试题浅层次的解释在:前端面试题:vue 的双向数据绑定原理,v-model的源码 深层次,其实就是问你vue数据绑定的原理: 1、使用Object.defineProperty进行数据劫持,把data对象,computed等里的所有属性进行数据劫持。数据劫持的意思可以看:JavaScript中的Object.defineProperty()函数 2、使用观察者模式,完成发布订阅。发布订阅者模式可以看:观察者模式 1)、模板里使用data对象属性的dom对象都订阅。 2)、当data对象里的属性的值发生变化时,就会发布,发布时,就改变了dom里的内容。 以下为源码: 这个代码只是模拟数据绑定的原理,并没有考虑vue的虚拟dom和异步更新队列等问题。 1、模拟vue.js的代码(文件名:vue.js) class Vue{ constructor(obj){ //2、数据挂载 //2.1) 、把obj对象的每个属性,作为vue对象的属性(属性名前面加上 $) for(let key in obj){ this["$"+key] = obj[key]; } //2.2)、把obj.data对象的属性,作为vue对象的属性,并且要有数据劫持的功能和发布订阅的功能 let myObserver = {}; observer.make(myObserver); for(let key in
  • 2021前端面试经常被问到的题(附答案)
    面试经常被问到的题 一、html51、html常见面试题2、艺术喵 2 年前端面试心路历程(字节跳动、YY、虎牙、BIGO)| 掘金技术征文3.前端 100 问:能搞懂 80% 的请把简历给我4、前端优化 二、css1.CSS 基础面试题(附答案)2.如何居中div?3. CSS3新特性4.清除浮动5.media媒体查询6.讲一讲Flex布局,以及常用的属性?7.BFC8.px rem em vh vw之间的区别到底是啥?9.0.5px的线10.12px以下的字体 三、javascript1. Symbol2.dom常用的操作3.Promise4. this5. new4.手写各种原生方法5.单线程异步6. 获取元素节点7.判断一个对象是Array类型8、事件循环9.Set 和Map10、proxy11、 Promise/async/Generator12.继承13.一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧14.闭包15.函数柯里化16、 for...in和for...of区别17、数组去重 四、http1、post 和get 的区别2、http的基本知识3、跨越4、Cookies 与 Session,SessionStore,LocalStore的区别及使用5.从一个url到最终页面渲染完成,发生了什么?6、css 和csrf7
  • 面试题:vue实现双向数据绑定的原理(附源代码)
    原文连接: https://blog.csdn.net/jiang7701037/article/details/104419524 此面试题浅层次的解释在:前端面试题:vue 的双向数据绑定原理,v-model的源码 深层次,其实就是问你vue数据绑定的原理: 1、使用Object.defineProperty进行数据劫持,把data对象,computed等里的所有属性进行数据劫持。数据劫持的意思可以看:JavaScript中的Object.defineProperty()函数 2、使用观察者模式,完成发布订阅。发布订阅者模式可以看:观察者模式 1)模板里使用data对象属性的dom对象都订阅。 2)当data对象里的属性的值发生变化时,就会发布,发布时,就改变了dom里的内容。 以下为源码: 这个代码只是模拟数据绑定的原理,并没有考虑vue的虚拟dom和异步更新队列等问题。 1、模拟vue.js的代码(文件名:vue.js) class Vue{ constructor(obj){ //2、数据挂载 //2.1) 、把obj对象的每个属性,作为vue对象的属性(属性名前面加上 $) for(let key in obj){ this["$"+key] = obj[key]; } //2.2)、把obj.data对象的属性,作为vue对象的属性
  • Vue前端面试题总结(二十六)双向数据绑定的原理 详解
    Vue双向数据绑定的原理 1.Vue双向数据绑定是通过 数据劫持 结合 发布订阅者 的方式来实现的 也就是说数据和视图一起更新 数据发生变化 视图也发生变化 视图发生变化 数据也发生变化 2.关于双向数据绑定 其核心是object.defineProperty()方法 双向绑定的核心object.defineProperty()是什么 采用数据劫持结合发布者-订阅者模式的方式 - Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调 (1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法) (2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法; 来源:https://blog.csdn.net/Rick_and_mode/article/details/108650653