更新時間:2021-09-02 10:33:08 來源:動力節點 瀏覽3798次
ant-design-vue開源了一段時間后,收到了一些反饋,尤其是Form組件上線后,很多用戶對JSX的使用感到迷惑和不習慣,為此專門介紹下Vue JSX的使用姿勢及注意事項。
Form組件的自動收集校驗功能需要在JSX下使用,當然如果不需要自動收集校驗,你依然可以使用template
Vue推薦在絕大多數情況下使用template來創建你的HTML。然而在一些場景中,你真的需要 JavaScript 的完全編程的能力,就需要使用 render 函數,它比 template 更接近編譯器。但是復雜的render函數書寫異常痛苦,好在官方提供了一個 Babel 插件,可以將更接近于模板語法的JSX轉譯成JavaScript。
使用過React的同學對JSX肯定不陌生,但是Vue的JSX寫法和React的還是有一些區別。
React中父子之間傳遞的所有數據都是屬性,即所有數據均掛載在`props`下(style, className, children, value, onChange等等)。
Vue則不然,僅僅屬性就有三種:組件屬性props,普通html屬性attrs,Dom屬性domProps。
接下來我們通過一個示例來詳細解釋他們的區別:本文代碼可在codesandbox查看運行
const ButtonCounter = {
name: "button-counter",
props: ["count"],
methods: {
onClick() {
this.$emit("change", this.count + 1);
}
},
render() {
return (
<button onClick={this.onClick}>You clicked me {this.count} times.</button>
);
}
};
export default {
name: "button-counter-container",
data() {
return {
count: 0
};
},
methods: {
onChange(val) {
this.count = val;
}
},
render() {
const { count, onChange } = this;
return (
<div>
<ButtonCounter
style={{ marginTop: "10px" }}
count={count}
type="button"
onChange={onChange}
/>
<ButtonCounter
style={{ marginTop: "10px" }}
count={count}
type="button"
domPropsInnerHTML={`hello ${this.count}.`}
onChange={onChange}
/>
</div>
);
}
};
組件屬性props:指組件聲明的屬性,即上述示例中聲明的props: ['count']。
普通html屬性attrs: 指組件未聲明的屬性,即上述示例中的type="button",該屬性默認會直接掛載到組件根節點的上,如果不需要掛載到根節點,可聲明 inheritAttrs: false。
Dom屬性domProps:指的Dom屬性,如上述示例中的innerHTML,它會覆蓋組件內部的children, 這類屬性我們一般很少使用到。
同樣事件屬性也分了兩種:on nativeOn
答:正則則則...... ?,babel-plugin-transform-vue-jsx插件會通過正則匹配的方式在編譯階段將書寫在組件上屬性進行“分類”。
onXXX的均被認為是事件,nativeOnXXX是原生事件,domPropsXXX是Dom屬性,
class,staticClass,style,key,ref,refInFor,slot,scopedSlots這些被認為是頂級屬性,至于我們屬性聲明的props,以及html屬性attrs,不需要加前綴,插件會將其統一分類到attrs屬性下,然后在運行階段根據是否在props聲明來決定屬性歸屬(即屬于props還是attrs)。
第一、屬性分類是編譯階段進行的分類,那么對于動態屬性如何劃分分類?
在React中所有屬性都是頂級屬性,直接使用{...props}就可以了,但是在Vue中,你需要明確該屬性所屬的分類,如一個動態屬性value和事件change,你可以使用如下方式(延展屬性)傳遞:
const dynamicProps = {
props: {},
on: {},
}
if(haValue) dynamicProps.props.value = value
if(hasChange) dynamicProps.on.change = onChange
<Dynamic {...dynamicProps} />
當然你可以混合著使用:
<Dynamic {...dynamicProps} style="color: red"/>
先別高興太早,如果你沒有深入使用過Vue JSX,不建議你使用混合方式,因為Vue會對其進行屬性合并,至于合并的規則官方也并沒有詳細的文檔,文檔中有一處示例,我在這再舉一個例子:
const dynamicProps2 = { on: { change: onChange2 } };
<Dynamic
{...{ on: { change: onChange1 } }}
{...dynamicProps2}
onChange={onChange3}
/>
上例中的onChange1、onChange2、onChange3都會觸發,而你想要的可能僅僅是onChange3。其它屬性的合并規則我就不一一列舉了,總之,我不建議你使用混合方式,除非你及你的團隊其他小伙伴對其規則了解的足夠透徹。
注:理想情況你不應該需要動態屬性,在業務開發中也比較少的使用動態屬性,但如果你嘗試開發一些通用性比較強的組件,就很難逃過動態屬性的使用。
第二、如果聲明的屬性就是onXXX怎么處理?
首先我不建議你這么做,但如果真的需要,你必須明確該屬性的分類,如下所示:
<div>
<Dynamic value="獲取到value,然而并不能獲取到onXXX" onXXX="?" />
<Dynamic {...{ props: { onXXX: "獲取到onXXX,但不建議使用" } }} />
</div>
第三、函數式組件的props如何處理?
注意:在 2.3.0 之前的版本中,如果一個函數式組件想要接受 props,則 props 選項是必須的。在 2.3.0 或以上的版本中,你可以省略 props 選項,所有組件上的屬性都會被自動解析為 props。
props和attrs之間存在著很微妙的關系,在普通組件中,只要明確聲明的屬性會被劃分到props分類中,剩下的均在attrs中。而對于函數式組件,只要省略了props選項,傳參時不管是否明確分類,最終context.props獲取到的都是全部屬性,如果你需要獲取明確的分類情況,可以在context.data下查看。
總之,在函數式組件中,推薦省略props選項。
第四、指令是否還可用?
很不幸的告訴你,大多數指令并不能在JSX中使用,對于原生指令,只有v-show是支持的。
大部分指令在JSX中可以使用表達式來替代,如:條件運算符(?:)替代v-if、array.map替代v-for
對于自定義的指令,可以使用如下方式使用:
const directives = [
{ name: 'my-dir', value: 123, modifiers: { abc: true } }
]
return <div {...{ directives }}/>
以上就是動力節點小編介紹的"在Vue中使用JSX的正確姿勢",希望對大家有幫助,想了解更多可查看編程入門教程。動力節點在線學習教程,針對沒有任何Java基礎的讀者學習,讓你從入門到精通,主要介紹了一些Java基礎的核心知識,讓同學們更好更方便的學習和了解Java編程,感興趣的同學可以關注一下。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習