写过react的jsx后,再回来看看vue的jsx,防止混淆,记录下。html
大括号里一个对象,简单明了vue
render () { return ( <div class={{ foo: true, bar: false }} style={{ color: 'red', fontSize: '14px' }} /> ) } 复制代码
诸如 innerHTML href title 等等,BOM环境的标签属性须要加个domProps前缀?标签自带的不加貌似均可以。node
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插槽须要使用vnode的$slots去获取并渲染,测试发现使用component组件< Title /> 去下发的话没法渲染,曲线救国的办法是放在props中去下发。(ps: 有更好的办法请留言告知)react
// 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> ) } 复制代码
经过传入scopeSlot的渲染函数,给子组件去调用git
// 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> ) }, } 复制代码
render () { if (b) { return <A /> } else { return <B /> } // return b ? <A /> : <B /> } 复制代码
$attrs
与 $listeners
把一堆中间组件中没声明为props的属性往下级组件传播,但中间组件仍是要手动绑定一下github
// 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') } }, } 复制代码
当你看多了几遍render函数里 createElement与jsx语法后,就能发现二者的写法有某种关联。只可意会,不可言传,一块儿感觉下。bash
// 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} /> ) } 复制代码