仿照vue-lit 打造一个现代的web计数器组件

原创
2020/09/26 20:08
阅读数 584

 

原文链接: 仿照vue-lit 打造一个现代的web计数器组件

上一篇: node tesseract 图片色值过滤 识别图中的数字

下一篇: js 颜色库 chroma 和 color

不得不说尤大佬还是会想啊, 看这个demo确实让人眼前一亮

之前我们用vue或者react写组件, 但是只是对原有的html元素进行组合, 并且很多写法都要编译到低级去执行, 编译的结果就是代码体积变大, 下载和加载耗时变长, 改一行代码, 编译几分钟看结果, 但是现在浏览器已经支持很多高级特性了, 如果能够控制用户的使用环境, 那么我们可以面向现代浏览器编程, 使用自定义组件和js的高级语法, 充分发挥浏览器的能力, 探索前端的边界到底在哪里.

react也搞了很多东西, 但是由于涉及不多, 所以没有这么大的触动, 不过那个lane有点意思, 以后有时间在看吧

 

https://github.com/yyx990803/vue-lit

https://github.com/vitejs/vite

效果, 和组件一样, 有自己的数据, 和传统的组件一样可复用

dom结构可以看出, 我们使用了浏览器的自定义组件, 使用shadow dom完成了组件的封装

https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_custom_elements

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <style>
      .counter {
        width: 100px;
        height: 100px;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <my-counter class="counter" value="0"></my-counter>
      <my-counter class="counter" value="3"></my-counter>
    </div>
    <script>
      class MyCounter extends HTMLElement {
        constructor() {
          super();
          let value = +this.getAttribute("value");
          console.log(this);
          const shadow = this.attachShadow({ mode: "open" });
          console.log(shadow);
          const span = document.createElement("span");
          span.innerText = "value:" + value;
          const button = document.createElement("button");
          button.innerText = "add";
          button.addEventListener("click", () => {
            span.innerText = "value:" + ++value;
          });
          shadow.appendChild(span);
          shadow.appendChild(button);
        }
      }
      customElements.define("my-counter", MyCounter);
    </script>
  </body>
</html>

 

但是我们可以看到, 我们需要自己处理事件相应, 和重新渲染, 稍有写麻烦, 利用vue的响应式和lit-html的轻量级引擎, 我们可以实现一个更加简单的Counter, 同时也可以借助这个思路, 重新打造一个MVVM库

 

使用lit-html封装组件

可以看到下面的dom结构, 和之前我们写的差不多, 但是简单了很多, 尤大佬简单的实现一个组件批量注册的方法, 可以像传统组件一般使用, 其中用到了很多技巧, 和vue类似的生命周期和状态管理, 目前没有diff相关, 是直接替换所有字符串

 

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="box">
      <vue-counter value="0"> </vue-counter>
      <vue-counter value="3"></vue-counter>
    </div>
    <script type="module">
      //   import { html, render } from "https://unpkg.com/lit-html?module";
      import { html, render } from "../node_modules/lit-html/lit-html.js";
      import {
        shallowReactive,
        effect,
        ref,
      } from "../node_modules/@vue/reactivity/dist/reactivity.esm-browser.js";
      class VueCounter extends HTMLElement {
        constructor() {
          super();
          const count = ref(+this.getAttribute("value"));
          console.log("count", count);
          const root = this.attachShadow({ mode: "closed" });
          const inc = () => count.value++;
          effect(() => {
            const template = html`<div>
              <span>count:${count.value}</span
              ><button @click=${inc}>inc</button>
            </div>`;
            console.log(count);
            render(template, root);
          });
        }
      }
      customElements.define("vue-counter", VueCounter);
    </script>
  </body>
</html>

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部