寫過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} /> ) } 複製代碼