写过react的jsx后,再回来看看vue的jsx,防止混淆,记录下。
class与style
大括号里一个对象,简单明了
render () {
return (
<div
class={{ foo: true, bar: false }}
style={{ color: 'red', fontSize: '14px' }}
/>
)
}
domProps
诸如 innerHTML href title 等等,BOM环境的标签属性需要加个domProps前缀?标签自带的不加貌似都可以。
render () {
return (
<Child
domPropsInnerHTML="bar"
title="我是title"
/>
)
}
事件
- 原生事件,对应模板语法的
@click.native
- 自定义事件(通过
'emit'
触发) - 事件引用,回调
// Parent.vue
export default {
render () {
return (
<div
propsOnCustomEvent={this.customEventHandler}
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
>
</div>
)
},
methods: {
nativeClickHandler () {
console.log('nativeClickHandler') // 原生事件
}
}
}
// Child.vue
export default {
props: {
onCustomEvent: {}
},
render() {
return (
<div
onClick={this.onClick}
>
自闭
</div>
)
},
methods: {
onClick (e) {
this.$emit('click', 'emit onClick') //自定义事件
this.onCustomEvent('i am a listener created by my parent') //回调事件
}
},
}
slot插槽与slotScope
slot插槽需要使用vnode的$slots去获取并渲染,测试发现使用component组件< Title /> 去下发的话无法渲染,曲线救国的办法是放在props中去下发。(ps: 有更好的办法请留言告知)
- slot插槽
// Parent.vue
render () {
const Title = <h1 slot="title">我是title_slot</h1>
return (
<Child
titleSlot={ Title }
>
// <Title /> // 这样无法渲染!!!
<h1>我是default_slot</h1>
</Child>
)
}
// Child.vue
render () {
return (
<div>
{ this.$attrs.titleSlot }
{ this.$slots.default }
</div>
)
}
- slotScope
通过传入scopeSlot的渲染函数,给子组件去调用
// Parent.vue
export default {
data () {
list: [
{ text: 'hello' },
{ text: 'world' },
{ text: '!' },
]
},
render() {
return (
<div>
{
this.list.map(item => (
<ListItem
data={ item }
{...{
scopedSlots: {
default: ({ data }) => {
return (
<div>{data}</div>
)
}
}
}}
/>
))
}
</div>
)
},
}
// Child.vue
export default {
props: {
data: {}
},
render() {
return (
<div>
{
this.$scopedSlots.default({
data: this.data
})
}
</div>
)
},
}
自定义指令
- v-show
直接支持!!!
- v-if
用if-else,三元操作符替代
render () { if (b) { return <A /> } else { return <B /> } // return b ? <A /> : <B /> }
- v-model
回到事件绑定更新值的方式吧,如果不愿意,使用这个官方插件
- v-modifier
直接扔个官方文档 ,因为我没补(素)充(材)
$attrs
与 $listeners
把一堆中间组件中没声明为props的属性往下级组件传播,但中间组件还是要手动绑定一下
// Root.vue
<template>
<div>
<parent
:root-value="rootValue"
@change-root-value="changeRootValue"
/>
</div>
</template>
export default {
data () {
return {
rootValue: 'root'
}
},
methods: {
changeRootValue (val) {
this.rootValue = val
}
}
}
// Parent.vue
// 没有声明props
render () {
return (
<Child
{...{ attrs: this.$attrs }}
{...{ on: this.$listeners }}
/>
)
}
// Child.vue
export default {
render () {
return (
<div
onClick={ this.onClick }
>
{ this.$attrs.titleSlot }
{ this.$slots.default }
</div>
)
},
methods: {
onClick () {
this.$listeners['change-root-value']('child')
}
},
}
其他
- key
- ref
- refInFor(使用列表渲染时使用)
渲染函数与jsx语法,单个属性与扩展运算符的写法对照
当你看多了几遍render函数里 createElement与jsx语法后,就能发现两者的写法有某种关联。只可意会,不可言传,一起感受下。
// createElement渲染函数语法
render (h) {
return h('div', {
attrs: {
id: 'foo'
},
domProps: {
innerHTML: 'bar'
},
on: {
click: this.clickHandler
},
nativeOn: {
click: this.nativeClickHandler
}
})
}
// jsx语法
render () {
// 下面这个b是不是跟createElement的第二个参数一样?
const b = {
attrs: this.$attrs,
domProps: {
innerHTML: 'innerHTML'
},
on: {
click: this.clickHandler
},
nativeOn: {
click: this.nativeClickHandler
}
}
return (
<div
// {...{ ...b }} // 这一行与下面的几行等价
domPropsInnerHTML="bar"
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
/>
)
}