vue中使用jsx

在了解jsx之前需要理解vue的render函数

Render函数

为什么要使用render函数,因为它比template更接近编译器,某些场景下,template会有些冗余

例如:

<template type="text/x-template">
    <div>
        <h1 v-if="level===1"><slot/></h1>
        <h2 v-if="level===2"><slot/></h1>
        <h3 v-if="level===3"><slot/></h1>
        <h4 v-if="level===4"><slot/></h1>
        <h5 v-if="level===5"><slot/></h1>
        <h6 v-if="level===6"><slot/></h1>
    </div>
</template>    

<script>
    Vue.component('anchored-heading',{
        template: '#id',
        props: {
            level:{type:Number,required:true}
        }
    })
</script>

  我们尝试用render函数来重写上面的例子:

<script>
    Vue.component('anchored-heading',{
        render:function (createElement) {
            return createElement('h'+this.level,this.$slots.default)
        },
        props: {
            level:{
                type: Number,
                requires:true,
            }
        }
    })
</script>

  明显:代码精简了很多!

createElement()参数

  {一个HTML标签,组件设置,一个函数}

  createElement接受的参数有:

  •  第一个参数:'div':一个HTML标签 {String | Object | Function}
  •     第二个参数:一个对应属性的数据对象 {Object}
  •     第三个参数:子节点(VNodes)   {String | Array}:[createElement('h1','hello world),createElement(MyComponent,{props: {comeProp: 'foo'}}),'bar']

createElement的完整数据对象

    {
        // 和`v-bind:class`一样的API
        'class': {
            foo: true,
            bar: false,
        },
        // 和`v-bind:style`一样的API
        style: {
            color: 'red',
            fontSize: '14px',
        },
        //正常的HTML特性
        attrs: {
            id: 'foo'
        },
        // 组件 props
        props: {
            myProp: 'bar'
        },
        // DOM属性
        domProps: {
            innerHTML: 'bara'
        },
        // 事件监听器 基于 "on"
        on: {
            click: this.clickHandler
        },
        // 仅对于组件,用于监听原生事件,而不是组件使用vm.$emit触发的事件
        nativeOn: {
            click: this.nativeClickHandler
        },
        // 自定义指令,注意事项:不能对绑定的旧值设值
        directives: [
            {
                name: 'my-custom-directive',
                value: '2',
                expression: '1+1',
                arg: 'foo',
                modifiers: {
                    bar: true,
                }
            }
        ],
        // 如果子组件有定义slot的名称
        slot: 'name-of-slot',
        key: 'myKey',
        ref: 'myRef',
    }

约束

  VNodes必须唯一

  所有组件树中的VNodes必须唯一。这意味着,下面的render function是无效的。

    render: function(createElement) {
        let myParagraphVNode = createElement('p','h1')
        return createElement('div',[
            myParagraphVNode, myParagraphVNode
        ])
    }

  如果有很多需要重复的元素/组件,可以使用工厂函数来实现。

    render: function (createElement) {
        return createElement('div', Array.apply(null,{length:20}).map(function() {
            return createElement('p','h1')
        }))
    }

JSX

  如果写了很多render函数,会很痛苦。又有一个Babel插件,支持我们在vue中使用JSX语法,让我们回到更接近于模板的语法上。

  

    <script type="javascript/jsx">
        export default {
            name: 'index',
            data() {
              return {
                demo: "hello"
              }
            },
            render:function(h) {
              return (
                <div>
                  {this.isShow? (
                    <h2>isShow</h2>
                  ) : (
                    <h2>asdas</h2>
                  )}
                  <p>Hello</p>
                </div>
              )
            }
        }
    </script>

  

具名插槽使用方法:

scopedSlots和slots

如果是具名插槽使用slots: {slotsName: EmptySlots} h('el-options', {slot: 'slotName'})

posted @ 2020-12-25 17:37  我很怪  阅读(1191)  评论(0编辑  收藏  举报