首页 > 其他分享 >写几行代码,了解响应式原理

写几行代码,了解响应式原理

时间:2023-05-03 16:44:36浏览次数:46  
标签:const 代码 几行 current 响应 value time property data

作者:袁首京

原创文章,转载时请保留此声明,并给出原文连接。

作为当下的开发人员,无论是不是前端,可能都会频繁的与 React、Vue、Svelte、Solidjs 等等打交道。也许你已经很清楚它们背后的运作原理,那不必往下看了。如果还不是很清楚,那咱们可以一起写几行代码,来瞅一眼这些响应式框架背后的思路。

响应式框架最根本的功能其实只有一条:当数据发生变化时,让界面随之发生变化

如何达成这一点呢?粗略的想一下就会觉得,首先要在数据和与之对应的 HTML 元素之间建立绑定关系。可以以某种方式给特定的 HTML 元素打个标记,然后当与此元素相关的值发生变更时,我们就能通过这个标记找到此元素,然后动态的改变它展示出来的值。

比如如下 HTML 模板片断:

<p>{{ current_time }}</p>

我们可以定义一个模板编译函数:

function compile(tpl) {
  const re = /(\{\{\s+)(\w+)(\s+\}\})/m;
  const mg = tpl.match(re);
  return tpl.replace(">{{", ' vid="' + mg[2] + '">{{').replace(mg[0], "");
}

执行该函数,就会给相关元素打上 vid 标记:

> compile('<p>{{current_time}}</p>')
<p vid="current_time"></p>

这样如果需要,我们就可以很方便的找到页面上需要响应的元素:

const vel = document.querySelector("[vid=current_time]");

接下来是数据部分。如何监测数据的变化呢?一种方案是使用代理。假如我们有如下数据对象:

{
  current_time: "2023-05-03T05:14:46.176Z";
}

可以使用如下函数,为其生成一个代理,拦截其赋值操作:

function reactive(data) {
  return new Proxy(data, {
    set(target, property, value) {
      const prev = target[property];
      target[property] = value;

      if (prev !== value) {
        const vel = document.querySelector(`[vid=${property}]`);
        vel.innerHTML = value;
      }

      return true;
    },
  });
}

接下来,就可以面向数据编程了:

const data = reactive({
  current_time: "2023-05-03T05:14:46.176Z",
});

setInterval(() => {
  data.current_time = new Date().toISOString();
}, 1000);

最终效果如下:

以下是完整代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <script>
      function compile(tpl) {
        const re = /(\{\{\s+)(\w+)(\s+\}\})/m;
        const mg = tpl.match(re);
        return tpl.replace(">{{", ' vid="' + mg[2] + '">{{').replace(mg[0], "");
      }

      function reactive(data) {
        return new Proxy(data, {
          set(target, property, value) {
            const prev = target[property];
            target[property] = value;

            if (prev !== value) {
              const vel = document.querySelector(`[vid=${property}]`);
              vel.innerHTML = value;
            }

            return true;
          },
        });
      }

      const app = {
        tpl: "<p>{{ current_time }}</p>",

        data: {
          current_time: "2023-05-03T05:14:46.176Z",
        },

        mount() {
          const rootEl = document.querySelector("#root");
          rootEl.innerHTML = compile(this.tpl);

          this.data = reactive(this.data);

          this.mounted();
        },

        mounted() {
          setInterval(() => {
            this.data.current_time = new Date().toISOString();
          }, 1000);
        },
      };

      document.addEventListener("DOMContentLoaded", () => {
        app.mount();
      });
    </script>
  </body>
</html>

标签:const,代码,几行,current,响应,value,time,property,data
From: https://www.cnblogs.com/rockety/p/17369256.html

相关文章

  • Logistic 回归测试代码
    简单概念Logistic回归是一种经典的分类方法,多用于二分类的问题。通过寻找合适的分类函数,用以对输入的数据进行预测,并给出判断结果。使用sigmoid函数(逻辑函数)将线性模型的结果压缩到[0,1]之间,使输出的结果具有概率意义,实现输入值到输出概率的转换。sigmoid函数:$g(z)=\f......
  • django 请求与响应
    请求与响应转递数据与接收三个请求方式 三个响应方式 defreq_list(request):#请求1#print(request.method)#m1=request.method#请求2#print(request.GET)#m2=request.GET#请求3#print(request.POST)#m3=......
  • 代码Vlog
    #include<dlib/opencv.h>#include<opencv2/opencv.hpp>#include<dlib/image_processing/frontal_face_detector.h>#include<dlib/image_processing/render_face_detections.h>#include<dlib/image_processing.h>#include<dlib/gu......
  • DVWA之SQL注入—Impossible level代码审计
    Impossiblelevel源代码<?phpif(isset($_GET['Submit'])){//CheckAnti-CSRFtokencheckToken($_REQUEST['user_token'],$_SESSION['session_token'],'index.php');//Getinput$id=$_GET......
  • Java代码读取properties配置文件
    读取properties配置文件packagecom.easycrud.utils;importjava.io.IOException;importjava.io.InputStream;importjava.util.Iterator;importjava.util.Map;importjava.util.Properties;importjava.util.concurrent.ConcurrentHashMap;/***@BelongsProject:E......
  • python设置环境变量在代码中
    以Linux平台为例:>>>importsys>>>sys.path'''['',#当前目录'/usr/local/python3/lib/python37.zip',#python标准库目录'/usr/local/python3/lib/python3.7','/usr/local/python3/lib/python3.7/lib-dynl......
  • SpringBoot定义优雅全局统一Restful API 响应框架
    假如现在有一个Java项目,老板让你做项目组长,定义项目基础框架,系统技术架构选型,你应该如何设计一个规范的统一的RestfulAPI响应框架呢思考目前项目开发,都是基于前后端分离模式开发的,基于后端模板引擎那一套,可能已经不适用一些项目开发流程,和当下开发模式了,尤其在要写比......
  • SpringBoot定义优雅全局统一Restful API 响应框架
    假如现在有一个Java项目,老板让你做项目组长,定义项目基础框架,系统技术架构选型,你应该如何设计一个规范的统一的RestfulAPI响应框架呢思考目前项目开发,都是基于前后端分离模式开发的,基于后端模板引擎那一套,可能已经不适用一些项目开发流程,和当下开发模式了,尤其在要写......
  • 代码自测学习
    1.tensor索引[:,0:3,] 代表从0行开始,一共3-0行b=torch.arange(16,dtype=float).reshape(1,4,4)print(b)print(b[:,0:1,]) ......
  • 《重构:改善既有代码的设计》学习笔记
    代码的坏味道名称说明重构手法神秘命名MysteriousName好的命名能够节省时间改变函数神秘、变量改名、字段改名重复代码DuplicatedName重复代码让人不得不留意其中的细微差异提炼函数、移动语句、函数上移过长函数LongFunction函数越长,就越难理解提炼函......