由于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
})}