vue-jsx的写法小全(附高清代码)

5,441 阅读2分钟

写过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函数里 createElementjsx语法后,就能发现两者的写法有某种关联。只可意会,不可言传,一起感受下。

// 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}
    />
  )
}

参考资料