当前位置: 首页 > Web前端 > vue.js

面试官:说说你对双向绑定的理解?

时间:2023-03-31 20:07:40 vue.js

本文为面试官VUE系列。就是把Model绑定到View上。当我们用JavaScript代码更新Model时,View会自动更新。双向绑定很容易想到。在单向绑定的基础上,当用户更新View时,Model的数据也会自动更新。更新了,这种情况是双向绑定的。举个栗子。当用户填写表单时,View的状态会更新。如果此时Model的状态可以自动更新,就相当于Model和View实现了双向绑定。关系图如下2、双向绑定的原理是什么我们都知道Vue是一个数据双向绑定的框架。双向绑定由三个重要部分构成数据层(Model):应用数据和业务逻辑视图层(View):应用展示效果、各种UI组件业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图相关联,上面的分层架构方案可以用专业术语来称呼:MVVM这里控制层的核心功能是“数据双向绑定”。自然,我们只需要了解它是什么,就可以进一步了解数据绑定的原理。了解ViewModel的主要职责:数据变化后更新视图。视图更改后更新数据。当然,它还有两个主要部分组成监听器。(Observer):监控所有数据的属性。编译器:扫描分析每个元素节点的指令,根据指令模板替换数据,绑定相应的更新函数。3、我们如何实现双向数据我们还是以Vue为例,先来看看Vue中的双向绑定流程是怎样的。newVue()首先进行初始化,对数据进行响应式处理。这个过程发生在Observe和编译模板的同时,找到动态绑定从数据中获取指定的数据,并初始化视图。这个过程发生在Compile中,同时定义了一个update函数和Watcher。以后相应的数据发生变化时,Watcher会调用update函数,因为某个view中可能会出现某个key的数据。多次,所以每个key都需要一个管家Dep来管理多个Watcher。一旦以后数据中的数据发生变化,它会先找到对应的Dep,通知所有Watcher执行update函数。流程图如下:首先是一个构造函数:对数据类进行初始化和响应式处理Vue{constructor(options){this.$options=options;this.$data=options.data;//对数据选项做响应式处理observe(this.$data);//代理数据到vmproxy(this);//执行编译newCompile(options.el,this);}}对数据选项执行响应式特定操作functionobserve(obj){if(typeofobj!=="object"||obj==null){return;}新的观察者(obj);}classObserver{constructor(value){this.value=value;这个。步行(价值);}步行(对象){对象。键(对象).forEach((key)=>{defineReactive(obj,key,obj[key]);});}}Compile扫描并解析每个元素节点的指令,根据指令模板替换数据,并绑定相应的更新函数classCompile{constructor(el,vm){this.$vm=vm;this.$el=document.querySelector(el);//获取domif(this.$el){this.compile(this.$el);}}compile(el){constchildNodes=el.childNodes;Array.from(childNodes).forEach((node)=>{//遍历子元素if(this.isElement(node)){//判断是否为节点console.log("compileelement"+node.nodeName);}elseif(this.isInterpolation(node)){console.log("编译插值文本"+node.textContent);//判断是否为插值文本{{}}}if(node.childNodes&&node.childNodes.length>0){//判断是否有子元素this.compile(node);//递归遍历子元素}});}isElement(node){返回node.nodeType==1;}isInterpolation(node){returnnode.nodeType==3&&/\{\{(.*)\}\}/.test(node.textContent);}}dependencycollectionview数据中的某个key会在数据中使用,称为依赖同一个key可能会出现多次,每次都需要Watcher收集维护。这个过程称为依赖收集。多个Watcher需要由一个Dep管理。当需要更新时,Dep会统一通知实现思路defineReactive在初始化视图时为每个key创建一个Dep实例。读取一个key,比如name1,创建一个watcher1。由于触发了name1的getter方法,所以将watcher1添加到name1对应的Dep中。当name1更新时,setter被触发,你可以通过对应的Dep通知它管理所有的Watcher更新//负责更新viewsclassWatcher{constructor(vm,key,updater){this.vm=vmthis.key=keythis.updaterFn=updater//当创建实例,将当前实例赋值给Dep.target静态属性Dep.target=this//读取key,触发getvm[key]//空Dep.target=null}//执行dom中的更新函数未来,由depupdate(){this.updaterFn.call(this.vm,this.vm[this.key])}}declarationDepclassDep{constructor(){this.deps=[];调用//依赖管理}addDep(dep){this.deps.push(dep);}notify(){this.deps.forEach((dep)=>dep.update());}}创建watcher时触发getterclassWatcher{constructor(vm,key,updateFn){Dep.target=this;this.vm[this.key];Dep.target=null;}}依赖集合,创建一个Dep实例functiondefineReactive(obj,key,val){this.observe(val);常量部门=新部门();Object.defineProperty(obj,key,{get(){Dep.target&&dep.addDep(Dep.target);//Dep.target是Watcher实例returnval;},set(newVal){if(newVal===val)return;dep.notify();//通知dep执行update方法},});}参考https://www.liaoxuefeng.com/w...https://juejin.cn/post/684490...https://vue3js.cn@JS语音社区