整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

你了解 JSX,那你了解 StyleX 么?

家好,我卡颂。

近日,Meta开源了一款「CSS-in-JS库」 —— StyleX。看命名方式,Style - X是不是有点像JS - X,他们有关系么?当然有。

JSX是一种「用JS描述HTML」的语法规范,广泛应用于前端框架中(比如ReactSolidJS...),由Meta公司提出。

同样的,按照Meta的设想,StyleX是一种「用JS描述CSS」的语法规范。

早在React Conf 2019[1]Meta工程师「Frank」就介绍了这种Meta内部使用的「CSS-in-JS库」

Meta内部使用,到大会对外宣传,这期间肯定已经经历大量内部项目的洗礼。而从做完宣传到最终开源,又经历了快5年时间。

那么,这款Meta出品、打磨这么长时间的「CSS-in-JS库」,到底有什么特点呢?

本文让我们来聊聊。

为什么需要CSS解决方案

市面上有非常多「CSS解决方案」,比如:

  • BEM命名规范
  • CSS Module规范
  • 原子CSS(比如TailwindCSS
  • CSS-in-JS(比如emotion

为什么需要这些方案?原生CSS哪里不好?在这里,我们举个小例子(例子来源于「React Conf 2019」)。考虑如下代码:

CSS文件如下:

.blue {color: blue;}
.red {color: red;}

HTML文件如下:

<p class="red blue">我是什么颜色?</p>

请问p标签是什么颜色的?

class来看,bluered后面,p应该是蓝色的么?

实际上,样式取决于他们在样式表中定义的顺序,.red的定义在.blue后面,所以p应该是红色的。

是不是已经有点晕了?再增加点难度。如果.red.blue分别在两个文件中定义呢?

# css文件1
.blue {color: blue;}
# css文件2
.red {color: red;}

p的样式就取决于最终打包代码中样式文件的加载顺序。

上面只是原生CSS「选择器优先级相关的一个缺陷」(除此外还有其他缺陷,比如「作用域缺失」...)。随着项目体积增大、项目维护时间变长、项目维护人员更迭,这些缺陷会被逐渐放大。

正是由于这些原因,才出现了各种「CSS解决方案」

StyleX的基本使用

StyleXAPI很少,掌握下面两个就能上手使用:

  • stylex.create,创建样式
  • stylex.props,定义props

比如:

import * as stylex from 'stylex';

// 创建样式
const styles = stylex.create({
  red: {color: 'red'},
});

// 定义props
const redStyleProps = stylex.props(styles.red);

使用时:

<div {...redStyleProps}>文字颜色是红色</div>

stylex是如何解决上面提到的red blue优先级问题呢?其实很简单,考虑如下代码:

import * as stylex from 'stylex';

// 创建样式
const styles = stylex.create({
  red: {color: 'red'},
  blue: {color: 'blue'}
});

// 使用
<p {...styles.props(styles.red, styles.blue)}></p>

样式的优先级只需要考虑styles.props中的定义顺序(bluered后面,所以颜色为blue),不需要考虑样式表的存在。

有些同学会说,看起来和常见的CSS-in-JS没啥区别啊。那stylex相比于他们的优势是啥呢?

相比其他CSS-in-JS的优势

首先要明确,stylex虽然以CSS-in-JS的形式存在,但本质上他是一种「用JS描述CSS的规范」。文章开头也提到,他的定位类似JSX

既然是规范,那他就不是对CSS的简单封装、增强,而是一套「自定义的样式编写规范」,只不过这套规范最终会被编译为CSS

作为对比,LessSass这样的「CSS预处理器」就是对CSS语法的封装、增强

那么,stylex都有哪些规范呢?

比如,stylex鼓励将样式与组件写在同一个文件,类似VueSFC(单文件组件)。这么做除了让组件的样式与逻辑更方便维护,也减少了stylex编译的实现难度。

再比如,CSS中各种选择器的复杂组合增强了选择器的灵活性。但同时也增强了不确定性。举个例子,考虑如下三个选择器:

  • .className > *
  • .className ~ *
  • .className:hover > div:first-child

这些对.className应用的选择器将影响.className的某些后代。当这样的选择器多了后,很可能会在开发者不知道的情况下改变某些后代元素的样式。

遇到这种情况我们一般会怎么处理呢?正确的选择当然是找到上述影响后代的选择器,再修改他。

但大家工作都这么忙,遇到这种问题,多半就是用新的选择器覆写样式,必要的时候还会加!important后缀。久而久之,这代码就没法维护了。

为了规避这种情况,在stylex中,除了「可继承样式」(指「当父元素应用后,子孙元素默认会继承的样式」,比如color)外,不支持这些「可以改变子孙后代样式的选择器」

那我该如何让子孙组件获得父组件同样的样式呢?通过props透传啊~

也就是说,stylex禁用了CSS中可能造成混淆的选择器,用JS的灵活性弥补这部分功能的缺失。

有些同学可能会说:这些功能,其他「CSS-in-JS库」也能做啊。

这就要谈到「CSS-in-JS库」最大的劣势 —— 为了计算出最终样式,在运行时会造成额外的样式计算开销。

stylex通过编译来减少运行时的开销。比如对于上面提到过的stylex的代码:

import * as stylex from 'stylex';

// 创建样式
const styles = stylex.create({
  red: {color: 'red'},
});

// 定义props
const redStyleProps = stylex.props(styles.red);

编译后的产物包括如下两部分:

JS的编译产物:

import * as stylex from 'stylex';
const redStyleProps = {className: 'x1e2nbdu'};

CSS的编译产物:

.x1e2nbdu {
  color: red;
}

所以,运行时实际运行的代码始终为:

<div {...{className: 'x1e2nbdu'}}>...</div>

对于再复杂的样式,stylex都会通过编译生成「可复用的原子类名」

即使是跨文件使用样式,比如我们在另一个文件也定义个使用color: 'red'样式的stylex属性foo

import * as stylex from '@stylexjs/stylex';

const styles = stylex.create({
  foo: {
    color: 'red',
  },
  bar: {
    backgroundColor: 'blue',
  },
});

会得到如下编译结果,其中x1e2nbdu是一个原子类名,他是上一个文件中styles.red的编译产物:

import * as stylex from '@stylexjs/stylex';

const styles = {
  foo: {
    color: 'x1e2nbdu',
    $$css: true,
  },
  bar: {
    backgroundColor: 'x1t391ir',
    $$css: true,
  },
};

随着项目体积增大,样式表的体积也能控制在合理的范围内。这种对原子类名的控制粒度是其他「CSS-in-JS库」办不到的。

相比于原子CSS的优势

stylex相比TailwindCSS这样的原子CSS有什么优势呢?

这就要谈到原子CSS的一个特点 —— 使用约定好的字符串实现样式。比如,使用TailwindCSS定义图片的样式:

<img class="w-24 h-24 rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512">

效果如下:

由于样式都是由不同的「原子类名字符串」组合而成,TS没法分析,这就没法实现「样式的类型安全」

什么叫「样式的类型安全」?通俗的讲,如果我实现一个组件,组件通过style props定义样式,我只希望使用者能够改变colorfontSize两个样式属性,不能修改其他属性。如果能实现这一点,就是「样式的类型安全」

「样式的类型安全」有什么意义呢?举个例子:设想开发基础组件库的团队使用stylex。那么当业务团队使用该组件库时,就只能自定义组件的一些样式(由组件库团队约束)。

当基础组件库升级时,组件库团队能很好对组件样式向下兼容(因为知道只有哪些样式允许被修改)。

stylex中,由于stylex.create的产物本质是对象,所以我们可以为每个产物定义类型声明。比如在如下代码中,我们限制了组件style props只能接受如下stylex样式

import type {StyleXStyles} from '@stylexjs/stylex';

type Props = {
  // ...
  style?: StyleXStyles<{
    color?: string;
    backgroundColor?: string;
    borderColor?: string;
    borderTopColor?: string;
    borderEndColor?: string;
    borderBottomColor?: string;
    borderStartColor?: string;
  }>;
};

总结

我猜想,当更多人知道stylex后,他会收到比当初TailwindCSS火时更多的两级分化的评价。

毕竟,stylex的设计初衷是为了解决Meta内部复杂应用的样式管理。如果:

  • 你项目没有达到Meta这样的体量
  • 你项目没有多年的迭代周期
  • 你项目前前后后没有多个工程师经手

那大概率是不能接受stylex设计理念中的这些约束。

对于stylex,你怎么看?

参考资料

[1]

React Conf 2019: https://www.youtube.com/watch?v=9JZHodNR184&t=270s

前端开发中,Vue 一直以其简单、高效的框架而备受开发者青睐。然而,随着 React 在市场上的流行,许多开发者开始对 JSX(JavaScript XML)这种声明式编程风格产生兴趣。本文将探讨 JSX 在 Vue3 中的应用,并对其是否成为 Vue3 前端开发的未来进行论证。

Vue3与JSX的爱恨情仇

在开始之前,我们先来了解一下 Vue 本身的模版语法和 JSX 分别是什么。

Vue3模版语法

Vue3 模版语法是 Vue.js 中常用的一种声明式模板语法,使用 HTML 语法来描述视图。在模板语法中,可以通过插值、指令和事件绑定等方式来将数据与视图关联起来。这是其简单易用和上手快的主要原因之一。

<template>
  <div>
    <h1>{{ title }}</h1>
    <p v-if="showText">{{ text }}</p>
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      title: 'Vue3 Template Syntax',
      text: 'This is a demo text.',
      showText: true,
      list: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' },
      ],
    };
  },
};
</script>

Vue3 的模板语法使用双花括号({{ }})进行数据插值,使用v-ifv-for等指令处理条件和循环逻辑。

什么是JSX?

JSX 是一种 JavaScript 的语法扩展,它允许在 JavaScript 代码中编写类似于 XML 的结构。React 是第一个广泛使用 JSX 的框架,它将组件的结构和逻辑封装在 JSX 中,用于描述 UI 组件的层次结构。随着 React 的成功,也随着时间的推移,JSX 逐渐成为了一种通用的模式,被许多其他框架和库所采用支持。

React示例:

import React, { useState } from 'react';

function JSXComponent() {
  const [title, setTitle] = useState('JSX in React');
  const [showText, setShowText] = useState(true);
  const list = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' },
  ];

  return (
    <div>
      <h1>{title}</h1>
      {showText && <p>This is a demo text.</p>}
      <ul>
        {list.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default JSXComponent;

Vue3示例:

import { defineComponent, ref } from 'vue';

const JSXComponent = defineComponent({
  setup() {
    const title = ref('JSX in Vue3');
    const showText = ref(true);
    const list = [
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      { id: 3, name: 'Item 3' },
    ];

    return {
      title,
      showText,
      list,
    };
  },
  render() {
    return (
      <div>
        <h1>{this.title}</h1>
        {this.showText && <p>This is a demo text.</p>}
        <ul>
          {this.list.map((item) => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      </div>
    );
  },
});

export default JSXComponent;

从上面不难看出,在 JSX 中,我们可以直接使用 JavaScript 表达式(如{title}),也可以使用条件语句(如{showText && <p>This is a demo text.</p>})和数组的map方法来处理循环逻辑。

这些只是举例,有很多的 JavaScript 语法和方法等,都可以在这里使用。总之,使用 JSX 开发,可以很大程度上利用好 JavaScript,开发更加方便。

如何配置JSX?

在 Vue3 中,我们可以通过 Vue 官方提供的项目脚手架工具 create-vue 来新建一个支持JSX的项目。首先,确保你安装了最新版本的 Node.js(我用的是 16+ 版本),然后执行以下命令:

npm init vue@latest

这个命令将会安装并执行 create-vue 工具。在执行过程中,你会看到一些可选的功能配置提示,其中会有如下内容:

Vue.js - The Progressive JavaScript Framework

✔ Project name: … vue-project
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ...

执行到✔ Add JSX Support?时选择Yes,这样 JSX 就会自动安装。如果不确定是否要开启某个功能,你可以直接按下回车键选择 No

当然,你也可以在已有的Vue项目中配置JSX。

在已有项目中配置JSX,首先需要安装相关依赖:

npm install --save-dev @vue/babel-plugin-jsx

然后,在项目的vite.config.ts文件中进行配置。具体的配置内容如下图所示:

image.png

配置完成后,现在我们就可以在项目中使用 JSX 语法来开发了。这样,我们可以根据具体的场景选择使用 Vue 模板或 JSX 语法。

总的来说,配置 JSX 是非常简单的,通过上述步骤,我们可以轻松地在 Vue 项目中使用 JSX,发挥其简洁、易读的优势,让我们的代码更加优雅和高效。

模板语法 vs JSX

现在,我们来对比一些具体的代码示例,看看 Vue3 模板语法和 JSX 之间的差异。

1000.webp

1.数据插值

Vue3 模板语法使用双花括号{{}}进行数据插值,而 JSX 使用花括号{}

模板示例:

<template>
  <p>{{ message }}</p>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const message = ref('Hello, JSX!');
    return { message };
  },
};
</script>

JSX示例:

import { defineComponent } from 'vue'; 

const DynamicData = defineComponent({
  setup() {
    const message = ref('Hello, JSX!');
    return { message };
  },
  render() {
    return <p>{this.message}</p>;
  },
});

2.条件渲染

在 Vue3 中,我们可以使用v-if指令进行条件渲染,而在 JSX 中,我们使用 JavaScript 的条件表达式。

模板示例:

<template>
  <div>
    <p v-if="showContent">Content is visible.</p>
    <p v-else>Content is hidden.</p>
    <button @click="toggleContent">Toggle</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const showContent = ref(true);

    function toggleContent() {
      showContent.value = !showContent.value;
    }

    return { showContent, toggleContent };
  },
};
</script>

JSX示例:

import { defineComponent } from 'vue'; 

const ConditionalRender = defineComponent({
  setup() {
    const showContent = ref(true);
    return { showContent };
  },
  render() {
    return (
      <div>
        {this.showContent ? <p>Content is visible.</p> : <p>Content is hidden.</p>}
        <button onClick={() => this.showContent = !this.showContent}>Toggle</button>
      </div>
    );
  },
}};

3.列表渲染

在 Vue3 中,我们使用v-for指令来处理列表渲染,而在 JSX 中,我们使用 JavaScript 的map方法。

模板示例:

<template>
  <ul>
    <li v-for="item in items" :key="item">{{ item }}</li>
  </ul>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const items = ref(['Apple', 'Banana', 'Orange']);
    return { items };
  },
};
</script>

JSX示例:

import { defineComponent } from 'vue'; 

const ListRendering = defineComponent({
  setup() {
    const items = ref(['Apple', 'Banana', 'Orange']);
    return { items };
  },
  render() {
    return (
      <ul>
        {this.items.map(item => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    );
  },
});

模板语法和JSX的优劣势

接下来,我们将对 Vue 模板和 JSX 进行对比,从多个方面分析它们的优势与劣势。

a. 语法简洁性

Vue 模板使用 HTML 语法,更加接近常规 HTML 结构,因此对于前端开发者来说比较容易上手。然而,「随着项目的复杂性增加,模板中可能会包含大量的指令和插值,导致代码变得冗长。」 例如,条件渲染、循环遍历等情况都需要使用 Vue 特定的指令。「相比之下,JSX 在 JavaScript 语法的基础上,使用类似 XML 的结构,使得代码更加紧凑和直观。」

模板示例:

<template>
  <div>
    <h1 v-if="showTitle">{{ title }}</h1>
    <ul>
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

JSX示例:

const MyComponent = () => {
  return (
    <div>
      {showTitle && <h1>{title}</h1>}
      <ul>
        {items.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
};

从上面的对比可以看出,JSX语法更加简洁,尤其在条件渲染循环遍历方面更加灵活。

b. 组件化开发

Vue.js 本身就支持组件化开发,但是在 Vue 模板中,组件的定义与使用是通过特定的 HTML 标签和 Vue 指令实现的。这种方式虽然简单易懂,但是在代码重用和维护方面可能会有一些限制。相比之下,JSX 在 React 中的组件化开发非常强大,组件可以直接在 JavaScript 中定义,并且支持更加灵活的组合方式。

模板示例:

<template>
  <div>
    <my-component :prop1="value1" :prop2="value2" />
  </div>
</template>

JSX示例:

const MyComponentWrapper = () => {
  return (
    <div>
      <MyComponent prop1={value1} prop2={value2} />
    </div>
  );
};

从上面的对比可以看出,JSX 允许在JavaScript中直接定义组件,并且组件的传参更加直观。

c. 类型检查与IDE支持

由于 Vue 模板使用了特定的指令和 HTML 语法,IDE 对于代码的支持可能相对有限。而 JSX 是 JavaScript 的扩展语法,因此可以与类型检查工具(如TypeScript)完美结合,同时得到更好的 IDE 支持,例如自动补全、代码跳转等。

d. 可扩展性

Vue 模板的语法是固定的,不能随意扩展。而 JSX 作为 JavaScript 的一部分,不需要额外的指令或语法,可以通过编写函数和组件来扩展其语法,也使得处理逻辑、计算和条件渲染变得更加灵活和方便。

e.生态系统的互通性

JSX 作为 React 的核心特性,拥有庞大的社区和丰富的生态系统,为开发者提供了海量的工具和库。

同时 JSX 在多个框架中得到了广泛支持,开发者们可以更轻松地在不同的项目和技术栈之间切换,而无需学习不同的模板语法。如文章上面“如何配置JSX?”中对已有项目的配置,将 JSX 作为插件写到 Vue Plugin 即可配置完成。

模板语法和JSX的适用场景

Vue3 的模板语法和 JSX 各有优劣,因此它们在不同的场景下有不同的适用性。

模板语法的适用场景

  • 快速原型开发:对于快速构建原型或小型项目,Vue3 的模板语法非常适合,可以快速上手和开发。
  • HTML/CSS开发者:对于更擅长 HTML/CSS 的开发者,Vue3 的模板语法更加亲切。

JSX的适用场景

  • 复杂交互:对于具有复杂交互逻辑的项目,使用 JSX 可以更灵活地处理各种条件和事件。
  • React生态系统:如果项目需要使用丰富的 React 生态系统,或者团队已经熟悉了 React 和 JSX,那么继续使用 JSX 是合理的选择。

总结

无论是从开发体验、技术生态还是未来趋势来看,JSX它使得组件的模板结构更加清晰、声明性,提供了更强大的 JavaScript 表达能力,同时也增强了与其他技术栈的互通性。虽然传统的 Vue2 模板语法在一定程度上仍然适用,但通过引入 JSX,Vue3 在前端开发领域拥有更广阔的发展前景。开发者们可以更加便利地构建复杂的交互界面,同时又能享受到 Vue3 带来的性能优势。

线程前端框架:Voe.js

看一眼 API,乍一看仿佛和 fard 类似的 API,仿佛又写了个跨端小程序框架?

然而并不是……

voe 是一个底层小程序框架

意思是它实现了小程序的双线程,利用“沙箱” 隔离 web 环境,屏蔽 dom 能力

接下来结合 微信小程序 介绍一下主要思路:

目标

绝对的控制力,意思是用户不能操作 dom,不能使用 web API,不能使用完整的 jsx 和 html,不能……反正就是啥都不能!

就好像 sm 角色一样,s 对 m 的绝对控制与虐待,m 只能服从命令与受虐

所以我把小程序的双线程架构又称为 【主奴架构】

沙箱

小程序中不能操作 dom,不是因为它屏蔽了 dom API 或者屏蔽了事件,这样做是不切实际的

大家都是寻找一个非 dom 环境作为沙箱,比如 v8,比如 worker,比如 native,比如 wasm

以上都是 OK 的,我猜微信小程序等也是用的类似的沙箱

voe 使用 web worker 作为沙箱

为什么不使用 v8 或 native?

这就是纯粹的个人选择了,不选择 v8 或 native 应该是,但是偏偏我个人更偏前一点,web worker 的计算力默认是优于 v8 或 native 的(同等硬件水平),但是 v8 也有好处,比如 node 可以使用 cookie,然后拥有一些先进的 API

将框架拆到两个不同的线程中

重点来了,两个线程中,如何安排框架工作呢?

有几个原则:

  1. 用户逻辑必须跑在 worker 中,完全不让碰 主线程
  2. 计算力的逻辑尽可能多的放到 worker 中

于是乎,就变成下面这个样子:

然后,困难如约而至,沙箱与主线程之间的鸿沟来自 dom 元素和 事件函数,这两者无法传递

我绞尽脑汁,想了一个完全之策

将不能传递的东西保存到自己线程中并建立映射,将索引传到另一个线程

比如,事件是这样传递的:

let handlers = new WeakSet()
 if (props) {
 for (const k in props) {
 if (k[0] === 'o' && k[1] === 'n') {
 let e = props[k]
 let id = handlers.size + 1
 handlers.set({ id: e })
 props[k] = id 
 }
 }
 }

将事件放到 map 中存起来,然后将 id 传给主线程,主线程事件触发的时候,将 id 和 event 参数交还给 worker

for (const k in props) {
 if (k[0] === 'o' && k[1] === 'n') {
 let id = props[k]
 props[k] = event => {
 // 不能传太多,此处省略对事件的简化操作
 worker.postMessage({
 type: EVENT,
 event,
 id
 })
 }
 }
}

然后在 worker 中,根据索引映射,找到对应的事件并触发

是的没错就是这样,这个方法是万能的,比如我们的 diff 方法

既然 diff 无法将 dom 传出去,那么我们就传 dom 的 index

if (oldVNode ==null||oldVNode.type!==newVNode.type) { 
 parent.insertBefore(createNode(newVNode), node)
}

比如这个方法,parent 和 node 都是 dom 元素,是没办法传递的,我们就……传他们的索引,may be 长这样:

[ [0,'insertBefore',1] ]

dom 是这样的:

<div id="root" index="0">
 <ul index="1">
 <li index="2" />
 <li index="3" />
 </ul>
</div>

如果此时我们要删除 index 为 3 的节点,那对应生成的结构,应该是这样:

[ [1,'removeChild',3] ]

刺不刺激,我们成功找到了一个思路,能够实现不同的 diff 算法啦

要知道,微信小程序就没有找到类似的思路,他们的 diff 还是 virtual-dom 的那套古老的深度遍历,代码多性能差……

综上所述,上面介绍了双线程的主要思路,这些思路不仅仅适用于这个框架,同样适用于其他跨端的场景

vue 3

这里简单说一下 vue 3,嗯大家看到,voe 的名字和 API 神似 vue 3,事实上我确实将 vue 3 的核心抄过来了,包括依赖收集,响应式,状态更新,组合函数……

这只是顺手的事儿,其实比起 voe 的核心思路,API 是没什么所谓的

因为几乎所有的公司,如果想要搞自己的小程序,都只能过来参考思路,然后 API 很可能就和微信保持一致了

所以我觉得 vue 3 的 API 足够简单,正好可以弱化 API

就抄过来了……

大家可以可以将 voe 作为 vue 3 的最小实现,用于协助阅读源码也是很 OK 的哈!

双线程 vs 异步渲染

题外话,大家应该都知道我之前写的框架 fre.js,也应该对 concurrent(时间切片)、suspense 等异步渲染的机制有所了解

如今我又来搞 web worker,是因为它俩的思路是类似的,场景也是一样的

  1. 时间切片是利用宏任务,将 diff 等低优先级任务后放到宏任务队列中,从而模拟了双线程,不阻断 UI
  2. 双线程是利用 web worker,将 diff 等高计算力的任务放到 worker 中,从而不阻断主线程 UI 渲染

两者的场景同样都是可视化,高帧率动画,大量数据与计算……

可惜本身这种场景需求实在太少了,所以 preact 和 vue 团队纷纷发声,表示不想搞也不需要搞::>_<::

但是到我这来说的话,其实我不在意框架有没有人用,也不在于业务的,我更加倾向于一种技术创新,所以从这个方面,只要是新的思路,总归有它的价值

总结

呼~终于写完了,在掘金发文,必须要长啊

最后放上 voe 的 github:

github.com/132yse/voe


作者:132


链接:https://juejin.im/post/5dd1edf3e51d4561ea3fb3cd