深入理解双向绑定

以下均为个人理解,希望大家带着自己疑问去阅读,有异议请在讨论区或公众号留言,作者是一个喜欢讨论的人。

一. 双向绑定是什么?

目前在前端框架中,多多少少都会有一些双向绑定的内容,我们也许用的很熟练,但是却很少去思考它的本质。

双向,理解即两个方向。在前端中,可理解为分别是视图上展现出数据的页面端和浏览器分配的一块特定存储数据的内存端。

绑定,理解为能相互改变对方,最终达到一致性。比如在Vue或React中,,通过把接口返回的数据置给Vue的data或React的state中,经过页面渲染后便可以在视图上表现出来。

双向绑定,即眼睛不可见的一块特定计算机内存中的数据发生变化后,能够体现我们眼睛能看到的页面视图层面上。比如在Vue中,当改变实例中data时,页面便对应改变,当我们主动改变页面上值时,再去检查实例中的data时,也相应发生了改变。注意React是单向数据流,只能是内存数据变化引起视图数据变化,而视图数据变化则需要手动setState去改变特定内存数据。


二. 如何实现一个双向绑定?

首先,理解了上面关于双向绑定的含义后,请停一下,花几分钟思考一下,如果让你去实现一个双向绑定,请理一下自己的思路,继续往下阅读,看看我们的思想有没有碰撞。

思路1:

如果想让A和B两块内容相互保持一致,可以让A和B同步起来,当在改变A的触发事件执行的时候顺手改一下B,在改变B的时候在改一下A,从而达到AB同步。

在页面中,当接口返回后,先将内存的变量赋值,再将页面某一个dom要展示的value重新设置一下。当手动改变页面上dom的value时,同时将之前申请的内存里的变量再做一次赋值操作,这样便可以完成两块内容的同步。

看下面这段代码即上面的实现:

const obj = {};
const dom = document.querySelector('.input');
let text = '初始化'
Object.defineProperty(obj, 'text', {
  set(value) {
    text = value;
    dom.value = value;
  }
});

// 页面手动改变input值
dom.onchange=function(e){
  const inputVal = e.target.value;
  data.text = inputVal
};

思路2:

想让AB保持一致,但是改变A时候并不去关注B的内容,这时候就需要B自身订阅监听A的内容是否变化,如果变化更新自己的值,从而达到目标。

具体操作,当改变内存中的某个变量A的值变化前,由于B想要跟A同步,B即需要监听A的值是否变化,则需要一个主动轮询检查AB内容值是否一致,一旦变化则更新B,从而达到AB一致性。

看下面这段代码即上面的实现:

let text = '初始化';
const dom = document.querySelector('.input');
const oldText = dom.innerText;

setInterval(()=>{
  if (oldText!==text) {
    dom.value = text;
  }
}, 1000);

setTimeout(()=>{
  text = '内容变化';
}, 3000);

// 页面手动改变input值
dom.onchange=function(e){
  const inputVal = e.target.value;
  data.text = inputVal
};

思路3:

AB想保持一致性,但是想要AB两者之间要完全解耦,没有过多的联系,则需要引入一个第三方进来,让A变化时,告诉一下第三方,第三方去做更新B的值的动作。

在实现过程中,引入发布者订阅者的方式,当A发生变化时,发布一条消息,而B则提前订阅好A的内容,由A的变化引起发布,从而B的订阅也得到变化,保持了AB的一致性。

需要先完成发布/订阅的角色。

let data ={ text: 'sada' };
const dom = document.querySelector('.input');
const oldText = dom.innerText;

var event = {
  ev: '',
  listen (fn) {
    this.ev = fn;
  },
  trigger (money) {
    this.ev(money);
  }
};

event.listen((text)=>{
  dom.value = text;
});

// 模拟数据变化
setInterval(()=>{
  data.text = `变化了${Math.random()}`
  event.trigger(data.text)
}, 3000);

// 页面手动改变input值
dom.onchange=function(e){
  const inputVal = e.target.value;
  data.text = inputVal
};

三. 总结

以上从三种方式去梳理了双向绑定的实现。大名鼎鼎的Vue便属于第一种和第三种的结合,称之为“数据挟持”,而Angularjs即是第二种称为“脏检查”,两大框架在此之上做了很多的优化内容,最终成就如今被人称赞的“双向绑定”。

如上内容均为自己总结,难免会有错误或者认识偏差,如有问题,希望大家留言指正,以免误人。有什么问题请留言,会尽力回答之。

本文分享自微信公众号 - 全栈者(fullStackEngineer)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-06-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员成长指北

公司要求会使用框架vue,面试题会被问及哪些?

如果你是一个已经在学习前端开发的初学者亦或者是一名在代码界纵横多年的程序员,那你一定知道现在最火的前端框架之一Vue.js。它相比于React与Angular上...

12130
来自专栏前端达人

Vue中组件之间8种通信方式,值得收藏

vue是数据驱动视图更新的框架, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢?首先我们需要知道在vue中组件之间存在什么样的关...

13030
来自专栏call_me_R

【译】如何大大简化你的Vuex Store

随着Vue应用程序的大小增加,Vuex Store中的actions和mutations也会增加。本文,我们将介绍如何将其减少到易于管理的东西。

7820
来自专栏较真的前端

在微信小程序中实现商品曝光的统计

在电商运营的工作中,运营人员需要关心很多数字,除了简单的PV和UV外,还有商品曝光量、商品浏览量、加入购物车、支付量,基于这些数字可以构建漏斗模型,帮助优化各个...

39810
来自专栏前端黑板报

Rollup构建发布一个Vue组件

在项目目录下面创建 src 目录并添加 index.js 文件和 vue-component.vue

10220
来自专栏前端达人

十款热门的Vue.js工具和库

随着Vue.js越来越热门,被很多开发人员采用,因此其生态也越来越完善,相关的工具和库也很丰富。这主要得益于:Vue的学习曲线,清晰的设计结构和使用文档,让有经...

32320
来自专栏程序员成长指北

Vue中组件之间8中通信方式,值得收藏

vue是数据驱动视图更新的框架, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢? 首先我们需要知道在vue中组件之间存在什么样的...

9420
来自专栏女程序员的日常_Lin

Vue SSR

vue.js是构建客户端应用程序的框架,在默认情况下,在浏览器输出Vue组件,进行生成DOM和操作DOM。Vue SSR 就是实现将组件渲染为服务器端的HTML...

79310
来自专栏开发架构二三事

vue之vuex2.0使用详解

Vuex 的核心是 store, 它是一个通过 Vuex.Store 构造函数生成的对象。为什么它会是核心呢?因为我们调用这个构造函数创建store 对象的时候...

8320
来自专栏开发架构二三事

vue之vue-router实例

本文转自: https://www.cnblogs.com/SamWeb/p/6610733.html

8420

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励