Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 一区二区三区四区在线视频,亚洲综合在线观看视频,国产精品久久久久影院色老大

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

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

          家好,我卡頌。

          近日,Meta開(kāi)源了一款「CSS-in-JS庫(kù)」 —— StyleX。看命名方式,Style - X是不是有點(diǎn)像JS - X,他們有關(guān)系么?當(dāng)然有。

          JSX是一種「用JS描述HTML」的語(yǔ)法規(guī)范,廣泛應(yīng)用于前端框架中(比如ReactSolidJS...),由Meta公司提出。

          同樣的,按照Meta的設(shè)想,StyleX是一種「用JS描述CSS」的語(yǔ)法規(guī)范。

          早在React Conf 2019[1]Meta工程師「Frank」就介紹了這種Meta內(nèi)部使用的「CSS-in-JS庫(kù)」

          Meta內(nèi)部使用,到大會(huì)對(duì)外宣傳,這期間肯定已經(jīng)經(jīng)歷大量?jī)?nèi)部項(xiàng)目的洗禮。而從做完宣傳到最終開(kāi)源,又經(jīng)歷了快5年時(shí)間。

          那么,這款Meta出品、打磨這么長(zhǎng)時(shí)間的「CSS-in-JS庫(kù)」,到底有什么特點(diǎn)呢?

          本文讓我們來(lái)聊聊。

          為什么需要CSS解決方案

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

          • BEM命名規(guī)范
          • CSS Module規(guī)范
          • 原子CSS(比如TailwindCSS
          • CSS-in-JS(比如emotion

          為什么需要這些方案?原生CSS哪里不好?在這里,我們舉個(gè)小例子(例子來(lái)源于「React Conf 2019」)。考慮如下代碼:

          CSS文件如下:

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

          HTML文件如下:

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

          請(qǐng)問(wèn)p標(biāo)簽是什么顏色的?

          class來(lái)看,bluered后面,p應(yīng)該是藍(lán)色的么?

          實(shí)際上,樣式取決于他們?cè)跇邮奖碇卸x的順序,.red的定義在.blue后面,所以p應(yīng)該是紅色的。

          是不是已經(jīng)有點(diǎn)暈了?再增加點(diǎn)難度。如果.red.blue分別在兩個(gè)文件中定義呢?

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

          p的樣式就取決于最終打包代碼中樣式文件的加載順序。

          上面只是原生CSS「選擇器優(yōu)先級(jí)相關(guān)的一個(gè)缺陷」(除此外還有其他缺陷,比如「作用域缺失」...)。隨著項(xiàng)目體積增大、項(xiàng)目維護(hù)時(shí)間變長(zhǎng)、項(xiàng)目維護(hù)人員更迭,這些缺陷會(huì)被逐漸放大。

          正是由于這些原因,才出現(xiàn)了各種「CSS解決方案」

          StyleX的基本使用

          StyleXAPI很少,掌握下面兩個(gè)就能上手使用:

          • stylex.create,創(chuàng)建樣式
          • stylex.props,定義props

          比如:

          import * as stylex from 'stylex';
          
          // 創(chuàng)建樣式
          const styles = stylex.create({
            red: {color: 'red'},
          });
          
          // 定義props
          const redStyleProps = stylex.props(styles.red);
          

          使用時(shí):

          <div {...redStyleProps}>文字顏色是紅色</div>
          

          stylex是如何解決上面提到的red blue優(yōu)先級(jí)問(wèn)題呢?其實(shí)很簡(jiǎn)單,考慮如下代碼:

          import * as stylex from 'stylex';
          
          // 創(chuàng)建樣式
          const styles = stylex.create({
            red: {color: 'red'},
            blue: {color: 'blue'}
          });
          
          // 使用
          <p {...styles.props(styles.red, styles.blue)}></p>
          

          樣式的優(yōu)先級(jí)只需要考慮styles.props中的定義順序(bluered后面,所以顏色為blue),不需要考慮樣式表的存在。

          有些同學(xué)會(huì)說(shuō),看起來(lái)和常見(jiàn)的CSS-in-JS沒(méi)啥區(qū)別啊。那stylex相比于他們的優(yōu)勢(shì)是啥呢?

          相比其他CSS-in-JS的優(yōu)勢(shì)

          首先要明確,stylex雖然以CSS-in-JS的形式存在,但本質(zhì)上他是一種「用JS描述CSS的規(guī)范」。文章開(kāi)頭也提到,他的定位類似JSX

          既然是規(guī)范,那他就不是對(duì)CSS的簡(jiǎn)單封裝、增強(qiáng),而是一套「自定義的樣式編寫(xiě)規(guī)范」,只不過(guò)這套規(guī)范最終會(huì)被編譯為CSS

          作為對(duì)比,LessSass這樣的「CSS預(yù)處理器」就是對(duì)CSS語(yǔ)法的封裝、增強(qiáng)

          那么,stylex都有哪些規(guī)范呢?

          比如,stylex鼓勵(lì)將樣式與組件寫(xiě)在同一個(gè)文件,類似VueSFC(單文件組件)。這么做除了讓組件的樣式與邏輯更方便維護(hù),也減少了stylex編譯的實(shí)現(xiàn)難度。

          再比如,CSS中各種選擇器的復(fù)雜組合增強(qiáng)了選擇器的靈活性。但同時(shí)也增強(qiáng)了不確定性。舉個(gè)例子,考慮如下三個(gè)選擇器:

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

          這些對(duì).className應(yīng)用的選擇器將影響.className的某些后代。當(dāng)這樣的選擇器多了后,很可能會(huì)在開(kāi)發(fā)者不知道的情況下改變某些后代元素的樣式。

          遇到這種情況我們一般會(huì)怎么處理呢?正確的選擇當(dāng)然是找到上述影響后代的選擇器,再修改他。

          但大家工作都這么忙,遇到這種問(wèn)題,多半就是用新的選擇器覆寫(xiě)樣式,必要的時(shí)候還會(huì)加!important后綴。久而久之,這代碼就沒(méi)法維護(hù)了。

          為了規(guī)避這種情況,在stylex中,除了「可繼承樣式」(指「當(dāng)父元素應(yīng)用后,子孫元素默認(rèn)會(huì)繼承的樣式」,比如color)外,不支持這些「可以改變子孫后代樣式的選擇器」

          那我該如何讓子孫組件獲得父組件同樣的樣式呢?通過(guò)props透?jìng)靼 ?/span>

          也就是說(shuō),stylex禁用了CSS中可能造成混淆的選擇器,用JS的靈活性彌補(bǔ)這部分功能的缺失。

          有些同學(xué)可能會(huì)說(shuō):這些功能,其他「CSS-in-JS庫(kù)」也能做啊。

          這就要談到「CSS-in-JS庫(kù)」最大的劣勢(shì) —— 為了計(jì)算出最終樣式,在運(yùn)行時(shí)會(huì)造成額外的樣式計(jì)算開(kāi)銷。

          stylex通過(guò)編譯來(lái)減少運(yùn)行時(shí)的開(kāi)銷。比如對(duì)于上面提到過(guò)的stylex的代碼:

          import * as stylex from 'stylex';
          
          // 創(chuàng)建樣式
          const styles = stylex.create({
            red: {color: 'red'},
          });
          
          // 定義props
          const redStyleProps = stylex.props(styles.red);
          

          編譯后的產(chǎn)物包括如下兩部分:

          JS的編譯產(chǎn)物:

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

          CSS的編譯產(chǎn)物:

          .x1e2nbdu {
            color: red;
          }
          

          所以,運(yùn)行時(shí)實(shí)際運(yùn)行的代碼始終為:

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

          對(duì)于再?gòu)?fù)雜的樣式,stylex都會(huì)通過(guò)編譯生成「可復(fù)用的原子類名」

          即使是跨文件使用樣式,比如我們?cè)诹硪粋€(gè)文件也定義個(gè)使用color: 'red'樣式的stylex屬性foo

          import * as stylex from '@stylexjs/stylex';
          
          const styles = stylex.create({
            foo: {
              color: 'red',
            },
            bar: {
              backgroundColor: 'blue',
            },
          });
          

          會(huì)得到如下編譯結(jié)果,其中x1e2nbdu是一個(gè)原子類名,他是上一個(gè)文件中styles.red的編譯產(chǎn)物:

          import * as stylex from '@stylexjs/stylex';
          
          const styles = {
            foo: {
              color: 'x1e2nbdu',
              $$css: true,
            },
            bar: {
              backgroundColor: 'x1t391ir',
              $$css: true,
            },
          };
          

          隨著項(xiàng)目體積增大,樣式表的體積也能控制在合理的范圍內(nèi)。這種對(duì)原子類名的控制粒度是其他「CSS-in-JS庫(kù)」辦不到的。

          相比于原子CSS的優(yōu)勢(shì)

          stylex相比TailwindCSS這樣的原子CSS有什么優(yōu)勢(shì)呢?

          這就要談到原子CSS的一個(gè)特點(diǎn) —— 使用約定好的字符串實(shí)現(xiàn)樣式。比如,使用TailwindCSS定義圖片的樣式:

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

          效果如下:

          由于樣式都是由不同的「原子類名字符串」組合而成,TS沒(méi)法分析,這就沒(méi)法實(shí)現(xiàn)「樣式的類型安全」

          什么叫「樣式的類型安全」?通俗的講,如果我實(shí)現(xiàn)一個(gè)組件,組件通過(guò)style props定義樣式,我只希望使用者能夠改變colorfontSize兩個(gè)樣式屬性,不能修改其他屬性。如果能實(shí)現(xiàn)這一點(diǎn),就是「樣式的類型安全」

          「樣式的類型安全」有什么意義呢?舉個(gè)例子:設(shè)想開(kāi)發(fā)基礎(chǔ)組件庫(kù)的團(tuán)隊(duì)使用stylex。那么當(dāng)業(yè)務(wù)團(tuán)隊(duì)使用該組件庫(kù)時(shí),就只能自定義組件的一些樣式(由組件庫(kù)團(tuán)隊(duì)約束)。

          當(dāng)基礎(chǔ)組件庫(kù)升級(jí)時(shí),組件庫(kù)團(tuán)隊(duì)能很好對(duì)組件樣式向下兼容(因?yàn)橹乐挥心男邮皆试S被修改)。

          stylex中,由于stylex.create的產(chǎn)物本質(zhì)是對(duì)象,所以我們可以為每個(gè)產(chǎn)物定義類型聲明。比如在如下代碼中,我們限制了組件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;
            }>;
          };
          

          總結(jié)

          我猜想,當(dāng)更多人知道stylex后,他會(huì)收到比當(dāng)初TailwindCSS火時(shí)更多的兩級(jí)分化的評(píng)價(jià)。

          畢竟,stylex的設(shè)計(jì)初衷是為了解決Meta內(nèi)部復(fù)雜應(yīng)用的樣式管理。如果:

          • 你項(xiàng)目沒(méi)有達(dá)到Meta這樣的體量
          • 你項(xiàng)目沒(méi)有多年的迭代周期
          • 你項(xiàng)目前前后后沒(méi)有多個(gè)工程師經(jīng)手

          那大概率是不能接受stylex設(shè)計(jì)理念中的這些約束。

          對(duì)于stylex,你怎么看?

          參考資料

          [1]

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

          前端開(kāi)發(fā)中,Vue 一直以其簡(jiǎn)單、高效的框架而備受開(kāi)發(fā)者青睞。然而,隨著 React 在市場(chǎng)上的流行,許多開(kāi)發(fā)者開(kāi)始對(duì) JSX(JavaScript XML)這種聲明式編程風(fēng)格產(chǎn)生興趣。本文將探討 JSX 在 Vue3 中的應(yīng)用,并對(duì)其是否成為 Vue3 前端開(kāi)發(fā)的未來(lái)進(jìn)行論證。

          Vue3與JSX的愛(ài)恨情仇

          在開(kāi)始之前,我們先來(lái)了解一下 Vue 本身的模版語(yǔ)法和 JSX 分別是什么。

          Vue3模版語(yǔ)法

          Vue3 模版語(yǔ)法是 Vue.js 中常用的一種聲明式模板語(yǔ)法,使用 HTML 語(yǔ)法來(lái)描述視圖。在模板語(yǔ)法中,可以通過(guò)插值、指令和事件綁定等方式來(lái)將數(shù)據(jù)與視圖關(guān)聯(lián)起來(lái)。這是其簡(jiǎn)單易用和上手快的主要原因之一。

          <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 的模板語(yǔ)法使用雙花括號(hào)({{ }})進(jìn)行數(shù)據(jù)插值,使用v-ifv-for等指令處理?xiàng)l件和循環(huán)邏輯。

          什么是JSX?

          JSX 是一種 JavaScript 的語(yǔ)法擴(kuò)展,它允許在 JavaScript 代碼中編寫(xiě)類似于 XML 的結(jié)構(gòu)。React 是第一個(gè)廣泛使用 JSX 的框架,它將組件的結(jié)構(gòu)和邏輯封裝在 JSX 中,用于描述 UI 組件的層次結(jié)構(gòu)。隨著 React 的成功,也隨著時(shí)間的推移,JSX 逐漸成為了一種通用的模式,被許多其他框架和庫(kù)所采用支持。

          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 表達(dá)式(如{title}),也可以使用條件語(yǔ)句(如{showText && <p>This is a demo text.</p>})和數(shù)組的map方法來(lái)處理循環(huán)邏輯。

          這些只是舉例,有很多的 JavaScript 語(yǔ)法和方法等,都可以在這里使用。總之,使用 JSX 開(kāi)發(fā),可以很大程度上利用好 JavaScript,開(kāi)發(fā)更加方便。

          如何配置JSX?

          在 Vue3 中,我們可以通過(guò) Vue 官方提供的項(xiàng)目腳手架工具 create-vue 來(lái)新建一個(gè)支持JSX的項(xiàng)目。首先,確保你安裝了最新版本的 Node.js(我用的是 16+ 版本),然后執(zhí)行以下命令:

          npm init vue@latest
          

          這個(gè)命令將會(huì)安裝并執(zhí)行 create-vue 工具。在執(zhí)行過(guò)程中,你會(huì)看到一些可選的功能配置提示,其中會(huì)有如下內(nèi)容:

          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 ...
          

          執(zhí)行到? Add JSX Support?時(shí)選擇Yes,這樣 JSX 就會(huì)自動(dòng)安裝。如果不確定是否要開(kāi)啟某個(gè)功能,你可以直接按下回車鍵選擇 No

          當(dāng)然,你也可以在已有的Vue項(xiàng)目中配置JSX。

          在已有項(xiàng)目中配置JSX,首先需要安裝相關(guān)依賴:

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

          然后,在項(xiàng)目的vite.config.ts文件中進(jìn)行配置。具體的配置內(nèi)容如下圖所示:

          image.png

          配置完成后,現(xiàn)在我們就可以在項(xiàng)目中使用 JSX 語(yǔ)法來(lái)開(kāi)發(fā)了。這樣,我們可以根據(jù)具體的場(chǎng)景選擇使用 Vue 模板或 JSX 語(yǔ)法。

          總的來(lái)說(shuō),配置 JSX 是非常簡(jiǎn)單的,通過(guò)上述步驟,我們可以輕松地在 Vue 項(xiàng)目中使用 JSX,發(fā)揮其簡(jiǎn)潔、易讀的優(yōu)勢(shì),讓我們的代碼更加優(yōu)雅和高效。

          模板語(yǔ)法 vs JSX

          現(xiàn)在,我們來(lái)對(duì)比一些具體的代碼示例,看看 Vue3 模板語(yǔ)法和 JSX 之間的差異。

          1000.webp

          1.數(shù)據(jù)插值

          Vue3 模板語(yǔ)法使用雙花括號(hào){{}}進(jìn)行數(shù)據(jù)插值,而 JSX 使用花括號(hào){}

          模板示例:

          <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指令進(jìn)行條件渲染,而在 JSX 中,我們使用 JavaScript 的條件表達(dá)式。

          模板示例:

          <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指令來(lái)處理列表渲染,而在 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>
              );
            },
          });
          

          模板語(yǔ)法和JSX的優(yōu)劣勢(shì)

          接下來(lái),我們將對(duì) Vue 模板和 JSX 進(jìn)行對(duì)比,從多個(gè)方面分析它們的優(yōu)勢(shì)與劣勢(shì)。

          a. 語(yǔ)法簡(jiǎn)潔性

          Vue 模板使用 HTML 語(yǔ)法,更加接近常規(guī) HTML 結(jié)構(gòu),因此對(duì)于前端開(kāi)發(fā)者來(lái)說(shuō)比較容易上手。然而,「隨著項(xiàng)目的復(fù)雜性增加,模板中可能會(huì)包含大量的指令和插值,導(dǎo)致代碼變得冗長(zhǎng)。」 例如,條件渲染、循環(huán)遍歷等情況都需要使用 Vue 特定的指令。「相比之下,JSX 在 JavaScript 語(yǔ)法的基礎(chǔ)上,使用類似 XML 的結(jié)構(gòu),使得代碼更加緊湊和直觀。」

          模板示例:

          <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>
            );
          };
          

          從上面的對(duì)比可以看出,JSX語(yǔ)法更加簡(jiǎn)潔,尤其在條件渲染循環(huán)遍歷方面更加靈活。

          b. 組件化開(kāi)發(fā)

          Vue.js 本身就支持組件化開(kāi)發(fā),但是在 Vue 模板中,組件的定義與使用是通過(guò)特定的 HTML 標(biāo)簽和 Vue 指令實(shí)現(xiàn)的。這種方式雖然簡(jiǎn)單易懂,但是在代碼重用和維護(hù)方面可能會(huì)有一些限制。相比之下,JSX 在 React 中的組件化開(kāi)發(fā)非常強(qiáng)大,組件可以直接在 JavaScript 中定義,并且支持更加靈活的組合方式。

          模板示例:

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

          JSX示例:

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

          從上面的對(duì)比可以看出,JSX 允許在JavaScript中直接定義組件,并且組件的傳參更加直觀。

          c. 類型檢查與IDE支持

          由于 Vue 模板使用了特定的指令和 HTML 語(yǔ)法,IDE 對(duì)于代碼的支持可能相對(duì)有限。而 JSX 是 JavaScript 的擴(kuò)展語(yǔ)法,因此可以與類型檢查工具(如TypeScript)完美結(jié)合,同時(shí)得到更好的 IDE 支持,例如自動(dòng)補(bǔ)全、代碼跳轉(zhuǎn)等。

          d. 可擴(kuò)展性

          Vue 模板的語(yǔ)法是固定的,不能隨意擴(kuò)展。而 JSX 作為 JavaScript 的一部分,不需要額外的指令或語(yǔ)法,可以通過(guò)編寫(xiě)函數(shù)和組件來(lái)擴(kuò)展其語(yǔ)法,也使得處理邏輯、計(jì)算和條件渲染變得更加靈活和方便。

          e.生態(tài)系統(tǒng)的互通性

          JSX 作為 React 的核心特性,擁有龐大的社區(qū)和豐富的生態(tài)系統(tǒng),為開(kāi)發(fā)者提供了海量的工具和庫(kù)。

          同時(shí) JSX 在多個(gè)框架中得到了廣泛支持,開(kāi)發(fā)者們可以更輕松地在不同的項(xiàng)目和技術(shù)棧之間切換,而無(wú)需學(xué)習(xí)不同的模板語(yǔ)法。如文章上面“如何配置JSX?”中對(duì)已有項(xiàng)目的配置,將 JSX 作為插件寫(xiě)到 Vue Plugin 即可配置完成。

          模板語(yǔ)法和JSX的適用場(chǎng)景

          Vue3 的模板語(yǔ)法和 JSX 各有優(yōu)劣,因此它們?cè)诓煌膱?chǎng)景下有不同的適用性。

          模板語(yǔ)法的適用場(chǎng)景

          • 快速原型開(kāi)發(fā):對(duì)于快速構(gòu)建原型或小型項(xiàng)目,Vue3 的模板語(yǔ)法非常適合,可以快速上手和開(kāi)發(fā)。
          • HTML/CSS開(kāi)發(fā)者:對(duì)于更擅長(zhǎng) HTML/CSS 的開(kāi)發(fā)者,Vue3 的模板語(yǔ)法更加親切。

          JSX的適用場(chǎng)景

          • 復(fù)雜交互:對(duì)于具有復(fù)雜交互邏輯的項(xiàng)目,使用 JSX 可以更靈活地處理各種條件和事件。
          • React生態(tài)系統(tǒng):如果項(xiàng)目需要使用豐富的 React 生態(tài)系統(tǒng),或者團(tuán)隊(duì)已經(jīng)熟悉了 React 和 JSX,那么繼續(xù)使用 JSX 是合理的選擇。

          總結(jié)

          無(wú)論是從開(kāi)發(fā)體驗(yàn)、技術(shù)生態(tài)還是未來(lái)趨勢(shì)來(lái)看,JSX它使得組件的模板結(jié)構(gòu)更加清晰、聲明性,提供了更強(qiáng)大的 JavaScript 表達(dá)能力,同時(shí)也增強(qiáng)了與其他技術(shù)棧的互通性。雖然傳統(tǒng)的 Vue2 模板語(yǔ)法在一定程度上仍然適用,但通過(guò)引入 JSX,Vue3 在前端開(kāi)發(fā)領(lǐng)域擁有更廣闊的發(fā)展前景。開(kāi)發(fā)者們可以更加便利地構(gòu)建復(fù)雜的交互界面,同時(shí)又能享受到 Vue3 帶來(lái)的性能優(yōu)勢(shì)。

          線程前端框架:Voe.js

          看一眼 API,乍一看仿佛和 fard 類似的 API,仿佛又寫(xiě)了個(gè)跨端小程序框架?

          然而并不是……

          voe 是一個(gè)底層小程序框架

          意思是它實(shí)現(xiàn)了小程序的雙線程,利用“沙箱” 隔離 web 環(huán)境,屏蔽 dom 能力

          接下來(lái)結(jié)合 微信小程序 介紹一下主要思路:

          目標(biāo)

          絕對(duì)的控制力,意思是用戶不能操作 dom,不能使用 web API,不能使用完整的 jsx 和 html,不能……反正就是啥都不能!

          就好像 sm 角色一樣,s 對(duì) m 的絕對(duì)控制與虐待,m 只能服從命令與受虐

          所以我把小程序的雙線程架構(gòu)又稱為 【主奴架構(gòu)】

          沙箱

          小程序中不能操作 dom,不是因?yàn)樗帘瘟?dom API 或者屏蔽了事件,這樣做是不切實(shí)際的

          大家都是尋找一個(gè)非 dom 環(huán)境作為沙箱,比如 v8,比如 worker,比如 native,比如 wasm

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

          voe 使用 web worker 作為沙箱

          為什么不使用 v8 或 native?

          這就是純粹的個(gè)人選擇了,不選擇 v8 或 native 應(yīng)該是,但是偏偏我個(gè)人更偏前一點(diǎn),web worker 的計(jì)算力默認(rèn)是優(yōu)于 v8 或 native 的(同等硬件水平),但是 v8 也有好處,比如 node 可以使用 cookie,然后擁有一些先進(jìn)的 API

          將框架拆到兩個(gè)不同的線程中

          重點(diǎn)來(lái)了,兩個(gè)線程中,如何安排框架工作呢?

          有幾個(gè)原則:

          1. 用戶邏輯必須跑在 worker 中,完全不讓碰 主線程
          2. 計(jì)算力的邏輯盡可能多的放到 worker 中

          于是乎,就變成下面這個(gè)樣子:

          然后,困難如約而至,沙箱與主線程之間的鴻溝來(lái)自 dom 元素和 事件函數(shù),這兩者無(wú)法傳遞

          我絞盡腦汁,想了一個(gè)完全之策

          將不能傳遞的東西保存到自己線程中并建立映射,將索引傳到另一個(gè)線程

          比如,事件是這樣傳遞的:

          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 中存起來(lái),然后將 id 傳給主線程,主線程事件觸發(fā)的時(shí)候,將 id 和 event 參數(shù)交還給 worker

          for (const k in props) {
           if (k[0] === 'o' && k[1] === 'n') {
           let id = props[k]
           props[k] = event => {
           // 不能傳太多,此處省略對(duì)事件的簡(jiǎn)化操作
           worker.postMessage({
           type: EVENT,
           event,
           id
           })
           }
           }
          }

          然后在 worker 中,根據(jù)索引映射,找到對(duì)應(yīng)的事件并觸發(fā)

          是的沒(méi)錯(cuò)就是這樣,這個(gè)方法是萬(wàn)能的,比如我們的 diff 方法

          既然 diff 無(wú)法將 dom 傳出去,那么我們就傳 dom 的 index

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

          比如這個(gè)方法,parent 和 node 都是 dom 元素,是沒(méi)辦法傳遞的,我們就……傳他們的索引,may be 長(zhǎng)這樣:

          [ [0,'insertBefore',1] ]
          

          dom 是這樣的:

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

          如果此時(shí)我們要?jiǎng)h除 index 為 3 的節(jié)點(diǎn),那對(duì)應(yīng)生成的結(jié)構(gòu),應(yīng)該是這樣:

          [ [1,'removeChild',3] ]
          

          刺不刺激,我們成功找到了一個(gè)思路,能夠?qū)崿F(xiàn)不同的 diff 算法啦

          要知道,微信小程序就沒(méi)有找到類似的思路,他們的 diff 還是 virtual-dom 的那套古老的深度遍歷,代碼多性能差……

          綜上所述,上面介紹了雙線程的主要思路,這些思路不僅僅適用于這個(gè)框架,同樣適用于其他跨端的場(chǎng)景

          vue 3

          這里簡(jiǎn)單說(shuō)一下 vue 3,嗯大家看到,voe 的名字和 API 神似 vue 3,事實(shí)上我確實(shí)將 vue 3 的核心抄過(guò)來(lái)了,包括依賴收集,響應(yīng)式,狀態(tài)更新,組合函數(shù)……

          這只是順手的事兒,其實(shí)比起 voe 的核心思路,API 是沒(méi)什么所謂的

          因?yàn)閹缀跛械墓荆绻胍阕约旱男〕绦颍贾荒苓^(guò)來(lái)參考思路,然后 API 很可能就和微信保持一致了

          所以我覺(jué)得 vue 3 的 API 足夠簡(jiǎn)單,正好可以弱化 API

          就抄過(guò)來(lái)了……

          大家可以可以將 voe 作為 vue 3 的最小實(shí)現(xiàn),用于協(xié)助閱讀源碼也是很 OK 的哈!

          雙線程 vs 異步渲染

          題外話,大家應(yīng)該都知道我之前寫(xiě)的框架 fre.js,也應(yīng)該對(duì) concurrent(時(shí)間切片)、suspense 等異步渲染的機(jī)制有所了解

          如今我又來(lái)搞 web worker,是因?yàn)樗鼈z的思路是類似的,場(chǎng)景也是一樣的

          1. 時(shí)間切片是利用宏任務(wù),將 diff 等低優(yōu)先級(jí)任務(wù)后放到宏任務(wù)隊(duì)列中,從而模擬了雙線程,不阻斷 UI
          2. 雙線程是利用 web worker,將 diff 等高計(jì)算力的任務(wù)放到 worker 中,從而不阻斷主線程 UI 渲染

          兩者的場(chǎng)景同樣都是可視化,高幀率動(dòng)畫(huà),大量數(shù)據(jù)與計(jì)算……

          可惜本身這種場(chǎng)景需求實(shí)在太少了,所以 preact 和 vue 團(tuán)隊(duì)紛紛發(fā)聲,表示不想搞也不需要搞::>_<::

          但是到我這來(lái)說(shuō)的話,其實(shí)我不在意框架有沒(méi)有人用,也不在于業(yè)務(wù)的,我更加傾向于一種技術(shù)創(chuàng)新,所以從這個(gè)方面,只要是新的思路,總歸有它的價(jià)值

          總結(jié)

          呼~(yú)終于寫(xiě)完了,在掘金發(fā)文,必須要長(zhǎng)啊

          最后放上 voe 的 github:

          github.com/132yse/voe


          作者:132


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


          主站蜘蛛池模板: 一区二区三区视频网站| 亚洲高清偷拍一区二区三区| 一区二区三区无码高清| 色欲综合一区二区三区| 日韩视频在线观看一区二区| 亚洲AV无码一区二区三区牲色| 日本中文字幕一区二区有码在线| 波多野结衣一区二区三区高清在线| tom影院亚洲国产一区二区| 国产高清不卡一区二区| 国产精品无圣光一区二区| 国产A∨国片精品一区二区| 国产一国产一区秋霞在线观看| 精品香蕉一区二区三区| 亚洲一区二区三区在线网站| 亚洲一区电影在线观看| 精品一区二区三区东京热| 国偷自产av一区二区三区| 中文字幕一区二区三区永久| 中文字幕一区二区三| 国产亚洲情侣一区二区无码AV| 国产av天堂一区二区三区| 天堂Aⅴ无码一区二区三区| 制服中文字幕一区二区| 国产午夜精品一区理论片| 国产另类TS人妖一区二区| 国产精品视频一区二区噜噜 | 亚洲一区二区三区在线| 亚洲成AV人片一区二区密柚 | 亚洲国产高清在线精品一区| 一区二区三区视频在线| 91香蕉福利一区二区三区| AV无码精品一区二区三区| 亚洲AV成人一区二区三区观看 | 久久99国产精品一区二区| 亚洲av无码一区二区三区乱子伦| 久久人妻av一区二区软件| 日韩在线一区二区| 国产成人av一区二区三区在线| 亚洲AV成人精品日韩一区18p | 在线精品一区二区三区|