如何在 Vue 中使用 JSX 以及使用它的缘由

做者:JThtml

译者:前端小智前端

来源:scotch.io/vue

点赞再看,养成习惯node

本文 GitHub github.com/qq449245884… 上已经收录,更多往期高赞文章的分类,也整理了不少个人文档,和教程资料。欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。git

Vue.js 具备简单的 API 和几个选项,可用于在咱们的组件中定义HTML模板。github

咱们可使用<template>标签选项,在根组件实例上定义template属性,或者使用单文件组件。面试

上面的选项很棒而且能够完美地工做,可是,在您的应用程序的生命周期中,有时会感到笨拙,设计过分或很是不灵活。npm

那么,咱们为何要使用 JSX 而不是其余模板定义呢?编程

  • JSX 更易读,<div></div> 的写法一看就是比 this.$createElement('div', {}, [...]) 简洁不少。
  • JSX 也是 JavaScript。
  • Vue支持JSX。
  • JSX 使自定义 Vue 组件更容易导入和管理。

简介

先举一个例子来讲明为何 JSX 是好的。json

咱们要构建一个<TextField/>组件,该组件能够是普通的单行文本输入或多行输入(文本区域)。 咱们的模板声明可能看起来像这样。

<div>
   <textarea v-if="multiline" v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false">
   <input v-else v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false">
 </div>
复制代码

从上面的代码片断中能够看到,咱们很快就会遇到一些问题,好比重复代码等等。想象一下,必须支持input上面所列的各类属性。上面的这个小片断将会增加并成为一个难以维护的噩梦。

要解决这个问题,咱们须要使用Vue进行降级处理,所以须要使用理接近Vue的内部API来解决这个问题。

render() 方法

注意:这里并非说没有JSX就没有一种简单的方法来处理上面的问题,只是说将这个逻辑移动到带有JSX的render()方法可使组件更直观。

咱们在 Vue 中建立的每一个组件都有一个render方法。这个就是 Vue 选择渲染组件的地方。即便咱们不定义这个方法,Vue 也会为咱们作这件事。

这意味着当咱们在 Vue 中定义 HTML 模板时,Vue 的模板编译器将其编译为一个createElement函数,该函数带有几个参数并从render函数返回结果。

为了修复上一节中的代码,咱们删除了template属性或template标签,并在组件上定义了render()方法。 若是在组件上定义了render方法,则 Vue 将忽略template定义。

...
 export default {
     name: 'TextField',
     render (createElement) {
         const tag = this.multiline ? 'textarea' : 'input'

        return createElement(tag, {
             class: {
                 'text-input': true,
                 'is-disabled': false
             },
             attrs: {
                 name: this.name,
                 placeholder: this.placeholder,
                 'aria-invalid': false
             }
         })
     } 
 }
...
复制代码

上面的代码作了几件事:

  1. render方法从Vue获取一个createElement助手。
  2. 咱们以编程方式定义咱们的标签。
  3. 而后,咱们建立标签并将其属性,类等做为对象传递。 咱们能够传递给createElement选项不少。
  4. 咱们返回新建立的元素进行渲染。

咱们为 Vue 组件定义的每一个模板都将转换为可返回createElement函数的render方法。 由于这个缘由,render方法将优先于模板定义。

举个例子:

// HTML
<div>
  <p>Only you can stop forest fires</p>
</div>
复制代码

模板编译器将把上面的 HTML 转换成:

...
render (createElement) {
  return createElement(
    'div',
    {},
    createElement(
      'p',
      {},
      'Only you can stop forest fires'
    )
  )
}
...
复制代码

如今你可能会问这个问题:“对可读性来讲这很差吗?” 答案是确定的。 一旦定义了具备许多元素嵌套级别或具备多个同级元素的组件,咱们就会遇到这个新问题。

这就是 JSX 出现的缘由,它能够很好的解决此类问题。

JSX 是什么

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

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

JSX 不打算由引擎或浏览器实现。相反,咱们将使用 Babel 之类的转置器将JSX转换成常规的 JS 。

// 此行是JSX的示例
const heading = <h1>Welcome to Scotch</h1>;
复制代码

基本上,JSX 容许咱们在 JS 中使用相似 Html 的语法。

配置 Vue 以使用 JSX

若是使用的 Vue-cli 大于或等于 3.0 版本,那么就直接可使用JSX的语法了。

若是您使用的是不支持 JSX 的Vue-cli较旧版本,则能够经过安装babel-preset-vue-app来添加它,并将其添加到您的.babelrc文件中。

# Using npm
 npm install --save-dev babel-preset-vue-app

# Using yarn
 yarn add --dev babel-preset-vue-app
复制代码

.babelrc文件中,添加:

{
 "presets": ["vue-app"]
}
复制代码

咱们如今能够在组件的render函数中使用 JSX。

在 Vue 中使用 JSX 须要注意的地方

在 Vue 中使用JSX须要注意几点。

要监听 JSX 中的事件,咱们须要“on”前缀。 例如,将onClick用于单击事件。

render (createElement) {
     return (
         <button onClick={this.handleClick}></button>
     )
 }
复制代码

要修改事件,请使用

render (createElement) {
     return (
         <button onClick:prevent={this.handleClick}></button>
     )
 }
复制代码

绑定变量,注意这里不是使用 :

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

将HTML字符串设置为元素的内容,使用domPropsInnerHTML而不是使用v-html

render (createElement) {
     return (
         <button domPropsInnerHTML={htmlContent}></button>
     )
 }
复制代码

咱们也能够展开一个大对象:

render (createElement) {
     return (
         <button {...this.largeProps}></button>
     )
 }
复制代码

在 render 中使用JSX

回到咱们最初的“TextField”组件。如今咱们已经在 Vue 应用程序中启用了 JSX,咱们如今能够这样作了。

render (createElement) {
     const inputAttributes = {
         class: 'input-field has-outline', // class definition
         onClick: this.handleClick // event handler
         backdrop: false // custom prop
     }
     const inputMarkup = this.multiline
         ? <textarea {...inputAttributes}></textarea>
         : <input {...inputAttributes}/>


    return inputMarkup
 }
复制代码

导入 Vue JS 组件

在 Vue 中使用JSX的另外一个好处是,咱们再也不须要注册所需的每一个组件。 咱们只是导入和使用。

import {Button} from '../components'

export default {
     render (createElement) {
         return <Button primary={true}>Edit</Button>
     }
 }
复制代码

如何使 JSX 与 TypeScript 一块儿使用

TypeScript 用做一种向 JavaScript添加类型检查的机制。要在 JSX 支持 TypeScript中,须要修改 tsconfig.json

要在 TypeScript 中启用 JSX,请先将该文件另存为.tsx文件,而后将tsconfig.json修改成包括:

{
   "compilerOptions": {
     ....
     "jsx": "preserve",
   }
 }
复制代码

jsx选项设置为“preserve”意味着 TypeScript 不该处理JSX。 这样作使 Babel 能够控制全部JSX 和 TypeScript 坚持使用类型,由于它尚不支持 Vue JSX。

而后在项目中建立一个jsx.d.ts文件,并为 Vue 添加 TypeScript JSX 声明。

import Vue, {VNode} from 'vue'

declare global {
   namespace JSX {
     interface Element extends VNode {}
     interface ElementClass extends Vue {}
     interface ElementAttributesProperty {
       $props: {}
     }
     interface IntrinsicElements {
 [elemName: string]: any
     }
   }
 }
复制代码

确保 TypeScript 能够加载声明文件。 或者,能够经过如下方式在tsconfig.json中为其添加自动加载功能:

{
   "compilerOptions": {
     ...
     "typesRoot": ["./node_modules/@types", "./types"]
   }
 }
复制代码

代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug

原文:scotch.io/tutorials/u…


交流

文章每周持续更新,能够微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub github.com/qq449245884… 已经收录,整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,另外关注公众号,后台回复福利,便可看到福利,你懂的。

相关文章
相关标签/搜索