姿式很重要,末尾有福利html
vue-antd-ui開源了一段時間後,收到了一些反饋,尤爲是Form組件上線後,不少用戶對JSX的使用感到迷惑和不習慣,爲此專門介紹下Vue JSX的使用姿式及注意事項。vue
Form組件的自動收集校驗功能須要在JSX下使用,固然若是不須要自動收集校驗,你依然可使用templatereact
Vue 推薦在絕大多數狀況下使用template來建立你的HTML。然而在一些場景中,你真的須要 JavaScript 的徹底編程的能力,就須要使用render函數,它比 template 更接近編譯器。可是複雜的render函數書寫異常痛苦,好在官方提供了一個Babel 插件,能夠將更接近於模板語法的JSX轉譯成JavaScript。git
使用過React的同窗對JSX確定不陌生,可是Vue的JSX寫法和React的仍是有一些區別。github
React中父子之間傳遞的全部數據都是屬性,即全部數據均掛載在props
下(style, className, children, value, onChange等等)。編程
Vue則否則,僅僅屬性就有三種:組件屬性props
,普通html屬性attrs
,Dom屬性domProps
。babel
接下來咱們經過一個示例來詳細解釋他們的區別:antd
本文代碼可在codesandbox查看運行dom
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']
。ide
普通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
)。
第1、屬性分類是編譯階段進行的分類,那麼對於動態屬性如何劃分分類?
在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} /> 複製代碼
上例中的onChange一、onChange二、onChange3都會觸發,而你想要的可能僅僅是onChange3。其它屬性的合併規則我就不一一列舉了,總之,我不建議你使用混合方式,除非你及你的團隊其餘小夥伴對其規則瞭解的足夠透徹。
注:理想狀況你不該該須要動態屬性,在業務開發中也比較少的使用動態屬性,但若是你嘗試開發一些通用性比較強的組件,就很難逃過動態屬性的使用。
第2、若是聲明的屬性就是onXXX怎麼處理?
首先我不建議你這麼作,但若是真的須要,你必須明確該屬性的分類,以下所示:
<div>
<Dynamic value="獲取到value,然而並不能獲取到onXXX" onXXX="😶" /> <Dynamic {...{ props: { onXXX: "獲取到onXXX,但不建議使用" } }} /> </div> 複製代碼
第3、函數式組件的props如何處理?
關於函數式組件的相關概念可查看官方文檔,文檔中有以下一段內容:
注意:在 2.3.0 以前的版本中,若是一個函數式組件想要接受 props,則
props
選項是必須的。在 2.3.0 或以上的版本中,你能夠省略props
選項,全部組件上的屬性都會被自動解析爲 props。
props
和attrs
之間存在着很微妙的關係,在普通組件中,只要明確聲明的屬性會被劃分到props
分類中,剩下的均在attrs
中。而對於函數式組件,只要省略了props
選項,傳參時不論是否明確分類,最終context.props
獲取到的都是所有屬性,若是你須要獲取明確的分類狀況,能夠在context.data
下查看。 總之,在函數式組件中,推薦省略props
選項。
第4、指令是否還可用?
很不幸的告訴你,大多數指令並不能在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的知識,能夠查看官方文檔。
說了那麼多,其實只要記住一點,儘可能使用明確分類的方式傳遞屬性,而不是要babel插件幫你分類及合併屬性。
最後彙報下vue-antd-ui的進度,目前組件數量48個,相較react版,還有List、TreeSelect、Metion、Carousel沒有開發,再過去的一段時間裏,咱們更多的去完善組件單元測試,測試覆蓋率83%,單測數量610個,接下來測試依然是咱們的主要工做。
質量永遠要比數量重要的多。
歡迎star,歡迎pr。
福利環節:
本人蔘與翻譯的React書籍(React Quickly,中文名:快速上手React編程)即將上市,現有樣書4本,爲了答謝支持vue-antd-ui的用戶,使用者可到該issue下按照規範(需截圖)回覆後私信我地址,郵費自理,先到先得,數量有限,敬請諒解。
相對深刻淺出系列,該書更加適合初學者入門,若是你是Vue開發者,想要快速的學習React及周邊技術(Redux、GraphQL、Jest等),我想這本書應該是不二之選。