[toc]
由於vue的createElement跟react的createElement有區別,導致jsx的寫法也有區別.本文將記錄一些vue中比較特殊的jsx的寫法.可以參考官方說明
v-model的寫法
官網中v-model寫法不可行,需要爲:
<el-input v-model="inputValue"/>
//
<el-input vModel_trim={inputValue}/>
//或者使用
<el-input
value={this.inputValue}
on-input={val => this.inputValue = val}/>
v-for
<el-tag
v-for="(item, index) in content"
:key="index"
type="success"
>
{{item.name}}
</el-tag>
//
{
this.content.map((item, index) => {
return (
<el-tag
key={index}
type="success"
>
{item.name}
</el-tag>
)
})
}
事件 & 按鍵修飾符
官方的寫法
<input vOn:click_stop_prevent="newTodoText" />
一些編輯會提示語法錯誤,
推薦可以使用下面的寫法
<el-input
@keyup.native.enter="fetch()"
@click="click()"
class="width-20"
prefix-icon="el-icon-search"
placeholder="關鍵字搜索"
/>
// 或者爲:
<el-input
class="width-20"
nativeOn-keyup={arg => arg.keyCode === 13 && this.fetch()}
on-click={_ => {this.click()} }
prefix-icon="el-icon-search"
placeholder="關鍵字搜索"
/>
需要注意的是,不要使用on-click={this.click() }
這樣寫,會報錯.解決方案是:on-click={this.click.bind(this, args) }
,不過建議的寫法是on-click={() => {this.click(args)} }
,就不需要寫bind(this)
了.
data寫法
jsx其實是createElement
的語法糖.jsx語法最終會轉爲createElement函數.當在jsx的標籤中使用{ ...obj }
時,obj將會編譯爲createElement
的中間參數.
需要注意的是,vue的createElement跟react的createElement函數中間的參數是的意義是一樣的.在vue中,中間的參數是data對象
,而react中,中間參數是props
.
所以如果vue中需要向react中一樣設置動態屬性時,需要:
const props={
name: 'joyer',
},
// react中
<my-button {...props}></my-button>
// vue中
<my-button {...{
props: props,
}}></my-button>
當你不知道一個在template
中的屬性怎麼在jsx
中使用時,可以先轉換爲createElement
的data對象
寫法,然後使用{...data}
寫在jsx
標籤上.
如高級組件中使用了v-on="$listeners"
或者v-bind="$attrs"
代理時,在官網並沒有說明.官網有對v-on="$listeners"
和v-bind="$attrs"的說明,當使用createElement
函數創建時,在第二個參數中可以這樣寫:
return createElement('div', {
props: {
...$attrs,
otherProp: value,
},
on: {
...$listeners,
click() {
},
}
},this.$slots.default])
在jsx中,也可以使用data,語法爲{...data}
:
// 官網推薦寫法
<button domPropsType="submit"><button>
// data方式寫法
<button { ...{
domProps: {
type: 'submit',
},
}}><button>
所以當你不知道jsx中元素上面的屬性怎麼寫時,可以全部寫入一個data對象中,然後用...data
放在元素上.
const data = {
domProps: {
type: 'submit',
},
scopedSlots: {
default: props => createElement('span', props.text)
},
props: {
...$attrs,
otherProp: value,
},
on: {
...$listeners,
click() {
},
}
}
<button { ...data }><button>
這樣就解決了v-on="$listeners"
或者v-bind="$attrs"
.
需要注意的是,如果使用{...data}
的高級組件的中,在{...data}
所在標籤的組件也是一個使用v-bind="$attrs"
或者{...data}
的組件,還需要在當前組件中設置attrs:
如cd-table-column-id
的源碼:
<cd-table-column { ...{
props: this.$attrs,
attrs: this.$attrs,
on: this.$listeners,
scopedSlots,
} } bold>
</cd-table-column>
cd-table-column
的源碼:
<el-table-column { ...{
props: columnAttrs,
on: columnListeners,
scopedSlots,
} }>
</el-table-column>
這是因爲cd-table-column
裏面也是使用了{...data}
寫法,其組件的props爲空,所以設置props是無效的,需要添加一個attrs
,通過attrs
繼承機制將cd-table-column-id
的this.$attrs
傳遞給cd-table-column
的this.$attrs
.
slot寫法
默認
<button>
<slot></slot>
</button>
//
<button>
{this.$scopedSlots.default()}
</button>
具名slot:
<button>
<slot name="before"></slot>
<slot ></slot>
</button>
//
let before = '';
if (this.$scopedSlots.before) {
before = this.$scopedSlots.before(props => props.text);
}
return (
<button>
{ before }
{this.$scopedSlots.default()}
</button>
作用域slot:
<slot :isAdvancedPanelShow="isAdvancedPanelShow"></slot>
//
{this.$scopedSlots.default({
isAdvancedPanelShow: this.isAdvancedPanelShow
})}