• Web Component-处理数据


    在前一篇中,我们开发了一个Reply组件,大概长这样

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BGaumn2T-1656511082807)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2fa68a485f5242f5b5e1eb75dfc801c1~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

    功能是完成了,不过今天浏览看到一篇文章Handling data with Web Components,大概是介绍了 Web Component 中数据交互的几种方式,有不少收获,特此总结记录一下

    attribute VS property

    首先是attributeproperty,我们之前的代码中使用的是attribute来将comments传递到组件中,组件拿到后开始渲染数据。这种方案有一个弊端:attribute只接收字符串类型的数据,由于comments是一个数组类型,因此我们在传递之前需要使用JSON.stringify一下以及使用数据时需要JSON.parse一下,使用起来有一些不够方便

    // 更新comments时需要处理成字符串
    reply.setAttribute("comments", JSON.stringify(comments));
    
    // 使用时需要解析成数组
    if (name === "comments") {
      this.renderComments(JSON.parse(newValue));
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    那么有没有一种更好的方式来取代这种方式呢?有的,可以使用property来传递数据

    propertyattribute中文翻译过来意思很接近,但实际上是有不小的区别

    考虑下面这一行代码

    <input type="text" value="Age:" /> 
    
    • 1

    typevalue就是input标签的_attribute_

    当浏览器编译完 HTML 代码,会生成与之对应的一个个 DOM 节点,每个 DOM 节点是一个对象,此时它又拥有很多_property_,例如heightaltchecked

    对于一个 DOM 节点对象来讲,property就是这个对象上的属性;attribute是该对象对应的 HTML 标签元素上的属性

    propertyattribute大致上一一对应,但也有些特例,比如上述input标签的value。DOM 节点对象上的value会在输入之后发生变化,假如用户输入的是John,那么此时Input.value的返回值是John,而Input.getAttribute('value')的返回值则是Name:。此外还有其他的一些特例,感兴趣的可以去这里What is the difference between properties and attributes in HTML看看原文

    既然property是对象上的一个属性,那个肯定也可以给它赋一个对象类型的值!接下来就使用property来重构Reply组件

    使用 property 重构组件

    其实修改起来非常方便,代码改动还是比较少的

    首先是最下面给组件更新值的代码需要变动:不再使用setAttribute,而是直接设置comments属性

    reply.setAttribute("comments", JSON.stringify(comments));
    
    // 修改为 ⬇️
    
    reply.comments = comments; 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其次,我们需要一对gettersetter来监听数据变化从而渲染新的值

    class Reply extends HTMLElement {
      constructor() {
        // 在这里,我们使用_comments来保存comments数据
        this._comments = [];
      }
      get comments() {
        return this._comments;
      }
    
      set comments(newValue) {
        this._comments = newValue;
        this.renderComments(newValue);
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    同时,删除监听comments属性相关的代码,因为我们这个已经通过setter实现数据监听了

    到这里,我们已经完成重构,实现组件的原本功能了

    不过我们要更新一步!

    既然我们都能传递数组进去了,那么在大胆点,可不可以传递一个函数呢?

    当然可以!!!

    我们可以直接在reply上挂载一个onSubmitComment函数,在Reply内部按钮点击时调用该回调,并将数据传递出来

    // 直接在组件实例上挂载一个回调函数
    reply.onSubmitComment = (e) => {
      comments.push({
        comment: e,
        nickName,
        avatar,
      });
      reply.comments = comments;
    };
    
    // 组件内部,点击按钮时调用该函数
    submitBtn.addEventListener("click", () => {
      this.onSubmitComment?.(commentInput.value);
      commentInput.value = "";
    }); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    芜湖~ 🎉

    完整代码在这里

    总结

    attribute只能传递字符串数据,property由于是 DOM 对象上的属性,因此可以传递诸如对象、函数等复杂类型的数据。

    据此,我们可以使用property来将数据直接设置到组件实例上,组件内部新增一对gettersetter来接收数据,而且我们还可以直接在组件实例上挂载一个回调函数,在组件内部可以直接调用该回调。

    此外在处理类似于disable这种类型的attribute时也可以使用property+gettersetter来实现布尔类型属性的设置

    总之,attributeproperty搭配使用将极大提高开发效率

    参考

    What is the difference between properties and attributes in HTML

    # Handling data with Web Components

  • 相关阅读:
    Linux用户空间与内核空间(理解高端内存)
    Jmeter项目实战
    问题记录--VSCode、CMake、MSVC编译,可执行文件无输出
    记录--Vue常问问题整合
    计算机毕业设计ssm高校图书馆网站m7o77系统+程序+源码+lw+远程部署
    go语言rpc初体验
    浅谈 深度学习、机器学习、人工智能
    论文精读:GHM:Gradient Harmonized Single-stage Detector
    翻译: 网页排名PageRank算法的来龙去脉 以及 Python实现
    【数论】卡特兰数
  • 原文地址:https://blog.csdn.net/web2022050902/article/details/125530383