在vue项目中使用jsx的技巧

1,885 阅读3分钟

1、JSX是什么

JSX 是 Facebook 工程团队创造的一个术语。

JSX 是 JavaScript 的类似XML的语法扩展,没有任何定义的语义。

const div = <div>这是一个div盒子</div>

2、绑定变量

JSX中绑定变量,跟在template中绑定变量,不太一样。

render (createElement) { 
    return ( <button content={this.generatedText}></button> ) 
}

3、绑定HTML

JSX中设置HTML内容,跟在template中也不太一样,在JSX中,是通过domPropsInnerHTML, 在template中,使用的是v-html

在template中:

<template>
    <div v-html="content"></div>
</template>

JSX中:

const div = <div domPropsInnerHTML={content}></div>

4、绑定事件

JSX中绑定事件,是通过on前缀来绑定事件,如onClick事件,原生事件添加nativeOn

const button = <button onClick={this.handleClick}></button>

5、事件修饰符

事件修饰符是通过:来修饰。

const button = <button onClick:prevent={this.handleClick}></button>

官方推荐:

<input vOn:click_stop_prevent="newTodoText" />

也可以使用快捷键

修饰符前缀
.passive&
.capture!
.once~
.capture.once.once.capture~!
使用方式如下:
<el-button {...{
    '!click': this.doThisInCapturingMode,
  '!keyup': this.doThisOnce,
  '~!mouseover': this.doThisOnceInCapturingMode
}}>Click Me!</el-button>

6、组件库事件绑定

当使用组件库开发的时候,事件名称如果有on-*的,可以使用下面的写法。

exrpot default {
  render() {
    return (
      <el-upload {...{
        props: {
          'on-success': () => {
            // 业务逻辑代码...
          }
        }
      }}>上传</el-upload>
    )
  }
}

7、v-for循环

JSX中,使用array.map()来进行循环。

const lis = ```
 <div>
        <ul>
          {
            this.data.map(item => {
              return <li>{ item.title }</li>
            })
          }
        </ul>
      </div>

8、三元运算符

<script>
export default {
  data() {
    return {
      isTrue: true,
    };
  },
  render() {

    const msg = this.isTrue ? '你中奖了' : '很遗憾,没中'
    return (
      <div>
        中奖情况:{ msg }
      </div>
    );
  }
};
</script>

9、style 方式

主要在标签上 使用{...{}}进行绑定

<script>
export default {
  data() {
    return {
      backgroundColor: 'blue',
      styleObject: {
        backgroundColor: 'red',
        fontSize: '20px',
        color: '#fff'
      }
    };
  },
  render() {
    return (
      <div>
        <span {...{
          style: {
            backgroundColor: this.backgroundColor
          }
        }}>我是蓝色背景</span>

        <span {...{
          style: this.styleObject
        }}>我是红色背景</span>
      </div>
    );
  }
};
</script>

10、class 方式

Vuejsx中可以直接写成class="xx"。实际上由于classJS的保留字,因此在DOM中其属性名为className而在HTML属性中为class,我们也可以在Vue中这样写:

<div domPropsClassName="mt__xs"></div>

注意 如果同时写了class="xx" domPropsClassName="yy"那么后者的优先级较高,和位置无关。所以尽量还是采用class的写法 主要在标签上 使用{...{}}进行绑定

<script>
export default {
  data() {
    return {
      isBlue: true,
      classOjbect: ['red']
    };
  },
  render() {
    return (
      <div>
        <span {...{
          class: {
            blue: this.isBlue,
          }
        }}>我是蓝色背景</span>

        <span {...{
          class: this.classOjbect
        }}>我是红色背景</span>
      </div>
    );
  }
};
</script>

11、directive 指令

对于自定义的指令可以使用v-name={value}的语法来写,需要注意的是指令的参数、修饰符此种方式并不支持。以官方文档指令部分给出的示例v-focus使用为例,介绍二种解决办法:

1、直接使用对象传递所有指令属性

<input type="text" v-focus={{value: true}}>

2、使用原始的vnode指令数据格式

{
  directives:{
    focus: {
      inserted: function(el) {
        el.focus()
      }
    }
  },
    
  render() {
    const directives = [
      { name: 'focus', value: true }
    ]
      
    return (
      <div>
          <input type="text" {...{ directives }} />
      </div>
    )
  }
}

11、Attrs 绑定

常用的动态iddata-*赋值

<script>
export default {
  data() {
    return {
    };
  },
  render() {
    return (
      <div>
        <span {...{
          attrs: {
            'id': 'app',
            'data-id': '1234'
          }
        }}>我是蓝色背景</span>
      </div>
    );
  }
};
</script>

高阶组件

render(h) {
 return (<my-button { ...{
  props: this.attrs,
  attrs: this.$attrs,
 } }><my-button>);
}

12、Slots 插槽

<el-table
  data={this.tableData}
  stripe
>
  <el-table-column
    prop='shop_name'
    label='店铺名称'
  >
  </el-table-column>
  <el-table-column
    prop='shop_status'
    label='店铺状态'
    {...{
      scopedSlots: {
        default: props => {
          // props.row 当前行的数据
          return props.row.shop_status ? <el-tag type='success'>启用</el-tag> : <el-tag type='danger'>禁用</el-tag>
        }
      }
    }}
  >
  </el-table-column>
  <el-table-column
    prop='shop_create_time'
    label='创建时间'>
  </el-table-column>
</el-table>

默认插槽模板写法:

<button>
    <slot></slot>
</button>

jsx的写法:

<button>
    {this.$scopedSlots.default()}
</button>

具名插槽模板写法:

<button>
    <slot name="before"></slot>
    <slot ></slot>
</button>

jsx写法:

let before = '';
if (this.$scopedSlots.before) {
    before = this.$scopedSlots.before(props => props.text);
}
return (<button>
    { before }
    {this.$scopedSlots.default()}
</button>)

作用域插槽模板写法:

<slot :isAdvancedPanelShow="isAdvancedPanelShow"></slot>

jsx写法:

{this.$scopedSlots.default({
    isAdvancedPanelShow: this.isAdvancedPanelShow
})}

动态组件

还记得官网怎么介绍 createElement 获取js的完全编程能力吗? 举了一个根据不同的等级使用不同标题的案例:

Vue.component('anchored-heading', {
  render: function (createElement) {
    return createElement(
      'h' + this.level, // 标签名称
      this.$slots.default // 子节点数组
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

这个案例通过jsx的写法为:

Vue.component('anchored-heading', {
  render: function (h) {
   const TagName = 'h' + this.level;
    return <TagName>{ this.$slots.default(this.props) }</TagName>
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

13、v-model

<!-- v-model -->
<el-input v-model={this.vm.name} />

要加修饰符:

<el-input vModel_trim={inputValue}/>
// 或者使用
<el-input 
 value={this.inputValue}
 on-input={val => this.inputValue = val.trim()}/>
 // 或者使用
 <el-input v-model_trim={inputValue}/>

14、空标签

React中,可以使用空标签来渲染DOM,在jSX中,不能直接使用<>空标签。

15、data写法

jsx本质上是createElement的语法糖,最终会被编译器转为createElement函数.当在jsx的标签中使用{ ...obj }时, obj将会编译为createElement的第二个参数.

vuecreateElement跟react的createElement函数第二个参数意义是不一样的.在vue中,第二个参数是 data对象, 而react第二个参数是props。所以本人将这种方式称为data写法

data中的参数:

 render: h => h(CountTo, {
    // 'class': 'count-to', // 给组件最外层盒子添加class类名
    // 或者这样写
    // 'class': ['count-to', true ? 'count-to2' : ''], 
    // 或者这样写
    'class': {
      'count-to': true,
      'count-to2': 1 === 1,
    }, 
    attrs: {}, // 定义属性id等等
    style: {}, // 定义样式
    props: { // 添加属性 这里可以理解为就是<count-to :endValue="100"/>
      endValue: 100
    },
    // domProps: { // dom的一些属性
    //   innerHTML: '11' // 可以设置标签的一些内容
    // },
    on: { // 添加事件
      'on-animation-end': (val) => { // 事件名
        console.log(val)
      }
    },
    nativeOn: { // 组件内没有定义click事件时,给组件最外层元素绑定一个click事件
      'click': () => {
        console.log('click')
      }
    },
    directives: [], // 可以定义自定义指令
    scopedSlots: {},
    slot: '', // 插槽
    key: '', // 设置一个值让每个组件的key不相等
    ref: '' // ref
  })

如在vue中需要设置动态属性时:

const props={
  name: 'joyer',
},

<my-button {...{
  props:props,
}}></my-button>

如官方推荐原生dom属性的jsx写法:

<button domPropsType="submit"><button>

采用data写法为:

<button { ...{
  domProps: {
    type: 'submit',
  }, 
}}><button>