国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

vue中正確使用jsx語(yǔ)法的姿勢分享

發(fā)布時(shí)間:2021-08-17 12:16 來(lái)源: 閱讀:0 作者:啥都不會(huì )的小前端 欄目: JavaScript 歡迎投稿:712375056

目錄

        前言

        又到了愉快的摸魚(yú)時(shí)間,我覺(jué)得不能荒廢,H5頁(yè)面我一直用的vant,出于對源碼的好奇,我從git上拉了一份vant源碼,里面竟然都是jsx寫(xiě)的組件,于是我開(kāi)始了對在vue中使用jsx的探索

        虛擬DOM

        什么是虛擬DOM

        在這之前,先了解下虛擬DOM,vue和react框架都在內部使用了虛擬DOM,這樣做的原因是通過(guò)js操作DOM的計算成本很高,雖然js更新速度很快,但是查找dom并更新的成本很高。那么有什么方法可以?xún)?yōu)化呢,vue等框架使用js對象,通過(guò)改變js對象,最后進(jìn)行批量處理,一次更新DOM,所以虛擬DOM本質(zhì)上就是一個(gè)js對象

        虛擬DOM的優(yōu)點(diǎn)

        • 從原先的操作真實(shí)DOM到操作虛擬DOM,降低查找成本
        • 通過(guò)diff比對,我們可以更快的定位數據的變化,從而更新DOM
        • 更好的ui更新
        • 抽象渲染過(guò)程,帶來(lái)了實(shí)現跨平臺的能力,如vue3中的createRenderer API

        渲染函數是什么

        渲染函數是用來(lái)生成虛擬DOM的。我們在vue單文件中編寫(xiě)模板語(yǔ)法,最終會(huì )在底層實(shí)現中被編譯成渲染函數

        Vue 推薦在絕大多數情況下使用模板來(lái)創(chuàng )建你的 HTML。然而在一些場(chǎng)景中,你真的需要 JavaScript 的完全編程的能力。這時(shí)你可以用渲染函數,它比模板更接近編譯器。

        當出現以下場(chǎng)景,雖然下列寫(xiě)法也能實(shí)現想要的效果,但是他不僅冗長(cháng),而且我們?yōu)槊總€(gè)級別標題重復書(shū)寫(xiě)了 。當我們添加錨元素時(shí),我們必須在每個(gè) v-if/v-else-if 分支中再次重復它

        const { createApp } = Vue
        
        const app = createApp({})
        
        app.component('anchored-heading', {
          template: `
            <h1 v-if="level === 1">
              <slot></slot>
            </h1>
            <h2 v-else-if="level === 2">
              <slot></slot>
            </h2>
            <h3 v-else-if="level === 3">
              <slot></slot>
            </h3>
            <h4 v-else-if="level === 4">
              <slot></slot>
            </h4>
            <h5 v-else-if="level === 5">
              <slot></slot>
            </h5>
            <h6 v-else-if="level === 6">
              <slot></slot>
            </h6>
          `,
          props: {
            level: {
              type: Number,
              required: true
            }
          }
        })
        

        雖然模板在大多數組件中都非常好用,但是顯然在這里它就不合適了。那么,我們來(lái)嘗試使用 render 函數重寫(xiě)上面的例子:

        const { createApp, h } = Vue
        
        const app = createApp({})
        
        app.component('anchored-heading', {
          render() {
            return h(
              'h' + this.level, // tag name
              {}, // props/attributes
              this.$slots.default() // array of children
            )
          },
          props: {
            level: {
              type: Number,
              required: true
            }
          }
        })
        

        jsx

        這樣寫(xiě)渲染函數有點(diǎn)痛苦,有沒(méi)有更接近模板的寫(xiě)法呢,vue提供了一個(gè)babel-plugin-jsx babel插件來(lái)讓vue支持jsx寫(xiě)法

        我這邊使用的vuecli創(chuàng )建的vue3 + ts項目,腳手架已經(jīng)集成了jsx和ts的相關(guān)依賴(lài)

        在vue3中編寫(xiě)jsx的兩種方式

        直接將文件后綴名從vue改成tsx或者jsx

        在vue3中,可以直接使用render選項編寫(xiě)

        import { defineComponent } from "vue";
        export default defineComponent({
          name: "Jsx",
          render() {
            return <div>我是一個(gè)div</div>;
          },
        });
        
        

        也可以在setup中返回

        import { defineComponent } from "vue";
        export default defineComponent({
          name: "Jsx",
          setup() {
            return () => <div>我是div</div>;
          },
        });
        
        

        兩種方式都可以,具體看個(gè)人習慣,setup中訪(fǎng)問(wèn)不到this,但是render中可以通過(guò)this訪(fǎng)問(wèn)當前vue實(shí)例

        用法

        class綁定,和react的jsx綁定的有區別,react中使用className,vue中使用class

         setup() {
           return () => <div class="test">我是div</div>;
         },
        

        style綁定

          setup() {
            return () => <div style={{ color: "red" }}>我是div</div>;
          },
        

        props綁定

        // 父組件
        setup() {
            return () => (
              <div style={{ color: "red" }}>
                <span>我是父組件</span>
                <Mycom msg={"我是父組件傳的值"} />
              </div>
         );
        
        // 子組件,setup的第一個(gè)參數,可以獲取props里的值
          setup(props) {
            return () => <div>我是子組件{props.msg}</div>;
          },
        

        事件綁定

        setup() {
            function eventClick() {
              console.log("點(diǎn)擊");
            }
            return () => <button onClick={eventClick}>按鈕</button>;
        },
        

        組件自定義事件

        // 子組件
        import { defineComponent } from "vue";
        export default defineComponent({
          name: "Mycom",
          emits: ["event"],
          setup(props, { emit }) {
            function sendData() {
              emit("event", "子組件傳遞的數據");
            }
            return () => (
              <div>
                <span>自定義事件</span>
                <button onClick={sendData}>傳遞數據</button>
              </div>
            );
          },
        });
        
        // 父組件
        // @ts-nocheck
        // 這樣寫(xiě)在jsx中沒(méi)問(wèn)題,但是在tsx中會(huì )報ts類(lèi)型錯誤,所以我在上面忽略了當前文件ts監測@ts-nocheck
        import { defineComponent } from "vue";
        import Mycom from "./mycom";
        export default defineComponent({
          name: "Jsx",
          setup() {
            function getSon(msg: string) {
              console.log(msg);
            }
            return () => (
              <div>
                <Mycom onEvent={getSon} />
              </div>
            );
          },
        });
        
        

        也可以這樣解決ts類(lèi)型報錯

          setup() {
            function getSon(msg: string) {
              console.log(msg);
            }
            return () => (
              <div>
                <Mycom {...{ onEvent: getSon }} />
              </div>
            );
          },
        

        插槽

        // 父組件
        setup() {
            const slots = {
              test: () => <div>具名插槽</div>,
              default: () => <div>默認插槽</div>,
            };
            return () => (
              <div>
                <Mycom v-slots={slots}></Mycom>
              </div>
            );
        },
        
        setup(props, { slots }) {
        // 子組件
            return () => (
              <div>
                <span>插槽</span>
                {slots.default?.()}
                {slots.test?.()}
              </div>
            );
          },
        

        指令,v-if,v-for等指令在jsx中無(wú)法使用,jsx只支持v-model和v-show指令

          setup() {
            const inputData = ref("");
            return () => (
              <div>
                <span v-show={true}>顯示</span>
                <span v-show={false}>隱藏</span>
                <input type="text" v-model={inputData.value} />
                <span>{inputData.value}</span>
              </div>
            );
        },
        

        最后

        話(huà)不多說(shuō),我先打開(kāi)vant源碼,準備開(kāi)啟我的第一個(gè)組件源碼閱讀 src =>button=>button.tsx

        到此這篇關(guān)于vue中正確使用jsx的文章就介紹到這了,更多相關(guān)vue中使用jsx內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

        參考

        免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

        久久久久人妻精品区一三寸| 中文字幕AV一区中文字幕天堂| 四虎国产精品永久免费网址| 日日做夜狠狠爱欧美黑人| 人人妻人人澡人人爽人人DVD| 成人无码潮喷在线观看|