JSX簡(jiǎn)介以及在Vue3中使用JSX+antd開(kāi)發(fā)組件

一莫其、什么是JSX?

就像這樣:

let jsx = <h1>hello world</h1>;

從表面上來(lái)看這和html沒(méi)啥區(qū)別耸三,但是請(qǐng)看左邊乱陡;我們把一段html代碼直接賦值給了一個(gè)變量。
JSX=javascript xml就是Javascript和XML結(jié)合的一種格式仪壮。是 JavaScript 的語(yǔ)法擴(kuò)展憨颠,只要你把HTML代碼寫(xiě)在JS里,那就是JSX积锅。

二爽彤、書(shū)寫(xiě)規(guī)范

JSX支持換行
let jsx = (
    <div>
        <h1>hello world</h1>
        <button/>
    </div>
)

1、jsx頂部只能有一個(gè)根元素缚陷,通常我們用<div></div>包起來(lái)(在Vue3中也可以使用和React一樣不占據(jù)Dom結(jié)構(gòu)的Fragment<></>空標(biāo)簽)适篙。
2、為了方便閱讀蹬跃,jsx外面需要包上一層小括號(hào)()
3匙瘪、標(biāo)簽要閉合(單邊標(biāo)簽得有斜杠)

jsx的注釋都需要用花括號(hào)包起來(lái)
{
    //我是單行注釋
}

{/*我是一段注釋*/}
jsx插入變量
const _c = 'hello world';
let jsx = (
    <div>
        <h1>{ _c }</h1>
    </div>
)
jsx表達(dá)式嵌入

1.運(yùn)算表達(dá)式

const a = 1;
const b = 1;
let jsx = (
  <div>{ a + b }</div>
)

2.三元表達(dá)式

let _t = 'hello world';
let a = 1;
let b = 2;
let hasButton = true;
let jsx = (
  <>
    <h1>{ _t === 'hello world' ? a :b }</h1>
    {
      //如果hasButton為true,則渲染button組件
      hasButton && <button/>
     }
  </>
)

3.函數(shù)調(diào)用

const func1 = ()=>{ return (<div>func1</div>) }
let jsx = (
    <div>
        <h1>
        {
            //如果在render外定義的函數(shù)蝶缀,請(qǐng)注意加this:this.func1()
            func1()
        }
        </h1>
    </div>
)
JSX 綁定屬性

1.綁定普通屬性

let jsx = (
    <>
        <h1 title={title}>hello world</h1>
    </>
)

2.綁定style

在jsx中丹喻,windows風(fēng)格的命名方式(屬性、style翁都、方法碍论、event)都需要轉(zhuǎn)換成駝峰式的寫(xiě)法,比如柄慰,正常寫(xiě)一個(gè)style指定左邊的外邊距:margin-left:‘10px’,需要換成:marginLeft: '10px'鳍悠;

let jsx = (
    <>
        <h1 style={{ marginLeft:'10px',width:'100%' }}>hello world</h1>
    </>
)

3.綁定class

在jsx中,class屬性需要指定為className坐搔,因?yàn)閏lass在JavaScript中是保留字段

const hasCss = true;
const h1Css = [
    'flex',
    hasCss ? 'css' : 'noCss',
]
let jsx = (
    <>
        <h1 className='flex'>hello world</h1>
        <h1 className={h1Css}>hello world</h1>
    </>
)

在vue3+jsx中藏研,jsx文件里面可以用css模塊化的方式進(jìn)行樣式導(dǎo)入后綁定。即在vue.config.js文件中css配置項(xiàng)中開(kāi)啟css模塊化(requireModuleExtension: true)概行,然后把css文件命名設(shè)置成***.module.less

import style from './style.module.less'
let jsx = (
    <>
        <h1 className={style.h1Css}>hello world</h1>
    </>
)
JSX 綁定事件

JSX中綁定事件類似在HTML原生中綁定事件蠢挡,只不過(guò)React中事件命名采用小駝峰(camelCase),而不是純小寫(xiě);(Vue3中經(jīng)過(guò)測(cè)試也通用)

function fnc(){}
let jsx = (
  <>
     <button onClick={this.fnc}/>
  </>
)
JSX 條件渲染

在jsx中业踏,不允許使用if禽炬、if-else,請(qǐng)使用三元運(yùn)算符或者邏輯與&&
同樣勤家,也允許使用for循環(huán)腹尖,請(qǐng)使用JS中的高階函數(shù)map、filter……

const t = 'hello world';
const arg1 = 1;
const arg2 = 2;
const hasButton = true;
const list = [1,2,3,4,5,6,7,8,9];
let jsx = (
    <div>
        <h1>
        {
            t === 'hello world' ?  arg1 : arg2
        }
        </h1>
    {
            //如果hasButton為true伐脖,則渲染button組件
            hasButton && <button/>
        }
        <ul>
        {
            list.map((item) => <li>{item}</li>)
        }
        </ul>
    </div>
)

二热幔、為什么我們要拋棄Vue的優(yōu)勢(shì)和各種指令去使用JSX

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

<script type="text/x-template" id="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>
</script>
Vue.component('anchored-heading', {
  template: '#anchored-heading-template',
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

這里用模板并不是最好的選擇:不但代碼冗長(zhǎng)认烁,而且在每一個(gè)級(jí)別的標(biāo)題中重復(fù)書(shū)寫(xiě)了 <slot></slot>,在要插入錨點(diǎn)元素時(shí)還要再次重復(fù)介汹。
雖然模板在大多數(shù)組件中都非常好用却嗡,但是顯然在這里它就不合適了。那么嘹承,我們來(lái)嘗試使用 render 函數(shù)重寫(xiě)上面的例子:

Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level,   // 標(biāo)簽名稱
      this.$slots.default // 子節(jié)點(diǎn)數(shù)組
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

三窗价、如何在vue3中使用JSX

vue3中jsx的兩種寫(xiě)法

1.在vue3中,可以直接使用render選項(xiàng)編寫(xiě)叹卷。

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

2.也可以在setup中返回

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

在項(xiàng)目目錄中新建***.jsx文件撼港;
jsx文件中從vue中導(dǎo)入defineComponent

如何導(dǎo)入JSX導(dǎo)入的組件以及向子組件傳值
<template>
  <Demo3  name="我是由父組件傳向子組件的"/>
</template>
<script>
import Demo3 from'./components/Demo3.jsx'
export default {
  name: 'App',
  components: {
    Demo3
  },
  setup(){
    return{
    }
  }
}
</script>
子組件接收并使用父組件傳過(guò)來(lái)的值
import { defineComponent } from 'vue'
export default defineComponent ({
    props:{
        name:{
            type:String
        }
    },
    setup(props) {
        const render = () =>{
            return (
                <div>
                    hello {props.name}
                </div>
            );
        }
        return render
    },
})
子組件傳值給父組件
import { defineComponent } from 'vue'
export default defineComponent ({
    setup({emit}) {
        let childNode = '不是老王';
        emit('clickMe',childNode )
        const render = () =>{
            return (
                <>
                  請(qǐng)無(wú)視我
                </>
            );
        }
        return render
    },
})
父組件接收子組件傳值
<template>
  <Demo3  @clickMe="clickMe"/>
</template>
<script>
import Demo3 from'./components/Demo3.jsx'
export default {
  name: 'App',
  components: {
    Demo3
  },
  setup(){
    const clickMe = (val) => {
      console.log(val)
    }
    return{
      locale: zhCN,
      clickMe
    }
  }
}
</script>

vue3+jsx+antd--Demo

import { defineComponent, ref, reactive } from 'vue'
import { Form, Input, Button  } from 'ant-design-vue';
export default defineComponent({
    setup() {
        let formRef = ref();// 綁定表單,對(duì)提交時(shí)觸發(fā)表單驗(yàn)證規(guī)則
        let formState = reactive({
            name: '',
            password: '',
            type: null // 下拉下選擇默認(rèn)值 設(shè)置為null  默認(rèn)展示placeholder的值 設(shè)置為1 展示typeArr  id為1 的 ‘類型1’
        });
        let typeArr = ref([
            {
                id: 1,
                type: '類型1'
            },
            {
                id: 2,
                type: '類型2'
            }
        ]);
        const validatePassword = () => {
            if (formState.password == '123456789') {
                return Promise.reject('密碼不能是123456789');
            } else {
                return Promise.resolve();
            }
        };
        let rules = {
            name: [
                {
                    required: true,
                    message: '請(qǐng)輸入賬號(hào)',
                    trigger: 'blur'
                },
            ],
            password: [
                {
                    required: true,
                    message: '請(qǐng)輸入密碼',
                    trigger: 'change',
                    // 觸發(fā)方式   ['change', 'blur']  可以這樣多種寫(xiě)法
                    // type:'string|array|number' //這是規(guī)定了類型  字符串  數(shù)組   數(shù)字 
                },
                {
                    validator: validatePassword,//自定義規(guī)則
                    trigger: 'blur'
                }
            ],
            type: [
                {
                    required: true,
                    message: '請(qǐng)選擇類型',
                    trigger: 'blur'
                }
            ]
        };

        const onSubmit = () => {
            // formRef 就是為了這一步  這樣點(diǎn)擊提交的時(shí)候  會(huì)觸發(fā)表單驗(yàn)證 注:綁定formRef時(shí)不是{this.formRef}
            console.log(formRef.value)
            formRef.value
                .validate()
                .then(() => {
                    console.log('values', formState);
                    // 表單驗(yàn)證通過(guò)就會(huì)執(zhí)行這里  你就可以操作了
                    formRef.value.resetFields(); // 重置表單到初始狀態(tài)
                })
                .catch((error) => {
                    console.log('error', error);
                });
        }
    
        return {
            formRef,
            formState,
            rules,
            typeArr,
            onSubmit
        }
    },
    render() {
        return (
            <>
                <Form
                    ref="formRef"
                    model={this.formState} // 綁定表單的初始對(duì)象
                    rules={this.rules} // 表單的規(guī)則綁定 可以自定義規(guī)則
                    wrapperCol={{ span: 18 }} labelCol={{ span: 4 }} // 控制每一行 label 和 輸入框 的占比 
                >
            {/* name 表單域 model 字段骤竹,在使用 validate(自定義規(guī)則)帝牡、resetFields(表單重置) 方法的情況下,該屬性是必填的 */}
                    <Form.Item ref="name" label="賬號(hào)" name="name">
                        <Input v-model={[this.formState.name, 'value']} />
                    </Form.Item>
                    <Form.Item ref="password" label="密碼" name="password">
                        <Input v-model={[this.formState.password, 'value']} />
                    </Form.Item>
                    <Form.Item name="type" label="下拉選擇">
                        <a-select ref="type" v-model={[this.formState.type, 'value']} placeholder="請(qǐng)選擇類型" >
                            {this.typeArr.map((item) => {
                                return (
                                    <a-select-option v-model={[item.id, 'value']} key={item.id}>
                                        {item.type}
                                    </a-select-option>
                                );
                            })}
                        </a-select>
                    </Form.Item>
                    <Form.Item>
                        <Button onClick={this.onSubmit}>提交</Button>
                    </Form.Item>
                </Form>
            </>
        );
    }
})
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蒙揣,一起剝皮案震驚了整個(gè)濱河市靶溜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌懒震,老刑警劉巖罩息,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異个扰,居然都是意外死亡瓷炮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)递宅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)娘香,“玉大人冬筒,你說(shuō)我怎么就攤上這事∶┲鳎” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵土榴,是天一觀的道長(zhǎng)诀姚。 經(jīng)常有香客問(wèn)我,道長(zhǎng)玷禽,這世上最難降的妖魔是什么赫段? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮矢赁,結(jié)果婚禮上糯笙,老公的妹妹穿的比我還像新娘。我一直安慰自己撩银,他們只是感情好给涕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著额获,像睡著了一般够庙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抄邀,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天耘眨,我揣著相機(jī)與錄音,去河邊找鬼境肾。 笑死剔难,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的奥喻。 我是一名探鬼主播偶宫,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼衫嵌!你這毒婦竟也來(lái)了读宙?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤楔绞,失蹤者是張志新(化名)和其女友劉穎结闸,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體酒朵,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桦锄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蔫耽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片结耀。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡留夜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出图甜,到底是詐尸還是另有隱情碍粥,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布黑毅,位于F島的核電站嚼摩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矿瘦。R本人自食惡果不足惜枕面,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缚去。 院中可真熱鬧潮秘,春花似錦、人聲如沸易结。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)衬衬。三九已至买猖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滋尉,已是汗流浹背玉控。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狮惜,地道東北人高诺。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像碾篡,于是被迫代替她去往敵國(guó)和親虱而。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容