JSX in Vue

如果你写过React的JSX,那么对你来说,学的会非常快,但是由于所谓的JSX都是通过解析模板调用createElement函数,最好生成虚拟DOM。
Vue的createElement和React的createElement显然不同,所有对于一些问题的需要特殊处理

安装

vue-cli-v4.x已经直接支持写JSX了,不需要配置

官方文档,请仔细阅读
vuejs/jsx

CreateElemnet了解

1. React中的createElemnet

每个 JSX 元素只是调用React.createElement(component, props, …children) 的语法糖。因此,使用 JSX 可以完成的任何事情都可以通过纯 JavaScript 完成。请注意第二个参数是props,这个props包含所有传参,这也是为什么说,react是函数式编程特点。

2. Vue中的createElemnet

然而,Vue做了一层过滤,当然如果要说的话本质是一样的(JSX是怎么被解析的,它本身和某个库无关,独立的一种标识————Vue做了对参数分类过滤)

那看下Vue是如何做的:

// @returns {VNode}
createElement(
  // {String | Object | Function}
  // 一个 HTML 标签名、组件选项对象,或者
  // resolve 了上述任何一种的一个 async 函数。必填项。
  'div',

  // {Object}
  // 一个与模板中 attribute 对应的数据对象。可选。
  {
    // 与 `v-bind:class` 的 API 相同,
    // 接受一个字符串、对象或字符串和对象组成的数组
    'class': {
      foo: true,
      bar: false
    },
    // 与 `v-bind:style` 的 API 相同,
    // 接受一个字符串、对象,或对象组成的数组
    style: {
      color: 'red',
      fontSize: '14px'
    },
    // 普通的 HTML attribute
    attrs: {
      id: 'foo'
    },
    // 组件 prop
    props: {
      myProp: 'bar'
    },
    // DOM property
    domProps: {
      innerHTML: 'baz'
    },
    // 事件监听器在 `on` 内,
    // 但不再支持如 `v-on:keyup.enter` 这样的修饰器。
    // 需要在处理函数中手动检查 keyCode。
    on: {
      click: this.clickHandler
    },
    // 仅用于组件,用于监听原生事件,而不是组件内部使用
    // `vm.$emit` 触发的事件。
    nativeOn: {
      click: this.nativeClickHandler
    },
    // 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
    // 赋值,因为 Vue 已经自动为你进行了同步。
    directives: [{
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }],
    // 作用域插槽的格式为
    // { name: props => VNode | Array<VNode> }
    scopedSlots: {
      default: props => createElement('span', props.text)
    },
    // 如果组件是其它组件的子组件,需为插槽指定名称
    slot: 'name-of-slot',
    // 其它特殊顶层 property
    key: 'myKey',
    ref: 'myRef',
    // 如果你在渲染函数中给多个元素都应用了相同的 ref 名,
    // 那么 `$refs.myRef` 会变成一个数组。
    refInFor: true
  }

  // {String | Array}
  // 子级虚拟节点 (VNodes),由 `createElement()` 构建而成,
  // 也可以使用字符串来生成“文本虚拟节点”。可选。
  [
    '先写一些文字',
    createElement('h1', '一则头条'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'
      }
    })
  ]
)

第一个参数都一样,但是你发现第二个在Vue叫做数据对象,它将(拿react做对比)props拆分成各种属性,这也是为什么vue会有各种指令然后实现。
值得注意的是props这个属性是数据对象的属性的一个元素

这也导致,在vue的组件上要进行透传,需要这样写

const VNode = (
  <div props={props} ></div>
)

3. 怎么理解createElement

首先进行JSX语法的识别,把标签作为调用createElement的第一个参数,让后获取所有绑定在组件上的attributes,作为第二个参数(vue和react的这个函数的区别就在这里,react将所有的组成一个对象,叫做props;但是vue是数据对象,包含了props),将其所有子节点做第三个参数。

真正在Vue写JSX

看完createElement你就可以写了,不然你会遇见很多奇怪的坑

1.数据绑定,渲染变量

(1) 模板语法

const name = 'zix'
{
  template: `<div>
    {{name}}
  </div>`,
  //第一种绑定this
  created() {
    this.name = name
  },
  //第二种绑定data,这种vue会对其进行监听更新,所有性能上
  data() {
    return {
      name: name
    }
  }
}

注意,这个name要渲染,必须是Vue对象实例上的属性,模板解析的是获取实例的name属性,你以为的获取data只是数据双向绑定的结果,在代码表象上,仍然是实例.name

(2) JSX

{
  render(h) {
    const name = 'zix'
    //所有能访问的变量都可以,绑定属性
    return (
      <div name={name} >{name}</div>
    )
  }
}

2.属性透传

{
  render(h) {
    const {$props} = this
    const name = 'zix'
    //所有能访问的变量都可以,绑定属性
    return (
      <div props={...$props} >{name}</div>
    )
  }
}

3.作用域、插槽

{
  render(h) {
    const {$props, $slots, $scopedSlots } = this
    const defaultSolt =  $slots.default && $slots.default() //默认插槽
    const nameSolt =  $slots.name && $slots.name() //具名插槽,作用域用$scopedSlots
    const name = 'zix'
    //所有能访问的变量都可以,绑定属性
    return (
      <div props={...$props} >
        {{defaultSolt}}
      </div>
    )
  }
}

总结

写JSX的时候只要符合对应库的createMent函数,就不会出问题,当然有些可以JSX和模板语法结合,会有不一样的体验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值